Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种⾏为模式,⽐如 singleton 单例作⽤域,就
表示 Bean 在整个 Spring 中只有⼀份,它是全局共享的,那么当其他⼈修改了这个值之后,那么另⼀个⼈读取到的就是被修改的值
singleton:单例作⽤域
prototype:原型作⽤域(多例作⽤域)
request:请求作⽤域
session:回话作⽤域
application:全局作⽤域
websocket:HTTP WebSocket 作⽤域
描述:该作⽤域下的Bean在***IoC容器***中只存在⼀个实例:获取Bean(即通过applicationContext.getBean等⽅法获取)及装配Bean(即通过@Autowired注⼊)都是同⼀个对象。
场景:通常⽆状态的Bean使⽤该作⽤域。⽆状态表示Bean对象的属性状态不需要更新
备注:Spring默认选择该作⽤域
描述:每次对该作⽤域下的Bean的请求都会创建新的实例:获取Bean(即通过applicationContext.getBean等⽅法获取)及装配Bean(即通过@Autowired注⼊)都是新的对象实例
场景:通常有状态的Bean使⽤该作⽤域。有状态表示Bean对象的属性需要更新
描述:每次http请求会创建新的Bean实例,类似于prototype
场景:⼀次http的请求和响应的共享Bean
备注:限定SpringMVC中使⽤
描述:在⼀个http session中,定义⼀个Bean实例
场景:⽤户回话的共享Bean, ⽐如:记录⼀个⽤户的登陆信息
备注:限定SpringMVC中使⽤
描述:在⼀个http servlet Context中,定义⼀个Bean实例
场景:Web应⽤的上下⽂信息,⽐如:记录⼀个应⽤的共享信息
备注:限定SpringMVC中使⽤
描述:在⼀个HTTP WebSocket的⽣命周期中,定义⼀个Bean实例
场景:WebSocket的每次会话中,保存了⼀个Map结构的头信息,将⽤来包裹客户端消息头。第⼀次初始化后,直到WebSocket结束都是同⼀个Bean
备注:限定Spring WebSocket中使用
使⽤ @Scope 标签就可以⽤来声明 Bean 的作⽤域, @Scope 标签既可以修饰⽅法也可以修饰类,@Scope设置方法:
1.直接设置作用域的具体值,如:@Scope(“prototype”);
2.设置 ConfigurableBeanFactory 和 WebApplicationContext 提供的 SCOPE_XXX 变量,如 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)。
注意:无论我们是使用类注解还是方法注解来将对象保存到Spring容器中,要改变该bean对象的作用域,只有在添加一个@Scope进行设置就行
使用方法注解:
@Component
public class UserBeans {
@Scope("prototype")
@Bean("userService_1")
public UserService getUserService() {
return new UserService();
}
}
使用类注解:
@Controller
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class UserController {
public void doUserController() {
System.out.println("do UserController.");
}
}
启动容器
Bean的初始化
将bean对象注册到Spring容器中(给bean对象开辟内存空间)
配置文件中的bean、配置了加载文件路径的类的扫描(看看有没使用类注解或者方法注解)
装配bean对象的属性(对象注入)
使用bean对象
Spring销毁
所谓的生命周期就是,一个对象从创建到销毁的过程
Bean对象的生命周期分为5大部分:
实例化bean对象(不是初始化bean对象,就是给bean对象分配内存空间)
设置bean属性(对象注入)
初始化bean
执行各种通知,如 BeanNameAware、BeanFactoryAware、
ApplicationContextAware 的接⼝⽅法;
初始化的前置方法(xml配置文件bean标签有init-method属性来设置前置方法,@PostConstruct注解也能解决这问题,只有在方法前加上这个注解就行)
初始化方法
初始化的后置方法
使用bean对象
销毁bean对象(xml配置文件bean标签里有destroy-method属性来指定bean对象在销毁时使用哪个方法,@PreDestroy注解也能解决这个问题,在哪个方法前加上这个就行了)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class UserController implements BeanNameAware {
@Autowired
public UserService userService;
public UserController() {
System.out.println("无参构造方法:UserController()");
}
public void init() {
System.out.println("通过xml配置文件来设置前置方法:UserController.init()");
}
@PostConstruct
public void before() {
System.out.println("通过注解来设置化前置⽅法:UserController.before()");
}
public void doUserController() {
System.out.println("bean对象的使用");
}
@Override
public void setBeanName(String s) {
System.out.println("Aware 通知:"+s);
}
@PreDestroy
public void destroy() {
System.out.println("bean对象的销毁:UserController.destroy()");
}
}
@Service
public class UserService implements BeanNameAware {
public UserService() {
System.out.println("无参构造方法:UserService()");
}
@PostConstruct
public void before() {
System.out.println("通过注解来设置化前置⽅法:UserService.before()");
}
@PreDestroy
public void destroy() {
System.out.println("bean对象的销毁:UserService.destroy()");
}
public void doUserService() {
System.out.println("do UserService.");
}
@Override
public void setBeanName(String s) {
System.out.println("Aware 通知:"+s);
}
}
xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:content="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置扫描注解的路径 -->
<content:component-scan base-package="com"></content:component-scan>
<bean id="userController" class="com.wwj.controller.UserController" init-method="init"></bean>
</beans>