Bean作用域与生命周期
独一无二的哈密瓜 人气:01. Bean 的作用域
1.1 观看案例
现在有一个公共 Bean
@Component public class UserBean { @Bean public User user1() { User user = new User(); user.setId(1); user.setName("张三"); user.setAge(18); return user; } }
现在有一个用户1, 进行了修改的操作
@Controller public class UserControllerA { @Autowired private User user1; public User getUser1() { User user = user1; System.out.println("用户1修改之前: " + user1); user.setName("王五"); return user; } }
现在有用户2, 进行读取操作
@Controller public class UserControllerB { @Autowired private User user1; public User getUser1() { User user = user1; return user; } }
打印用户1和用户2公共Bean的值
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); UserControllerA userControllerA = context.getBean("userControllerA",UserControllerA.class); User user = userControllerA.getUser1(); System.out.println("用户1修改之后: " + user); UserControllerB userControllerB = context.getBean("userControllerB",UserControllerB.class); User user1 = userControllerB.getUser1(); System.out.println("用户2读取到的: " + user1); }
运行结果
原因:
Spring 中 Bean 的作用域默认是 singleton 单例模式. 所有人使用的都是同一个对象.
1.2 作用域的定义
之前所说的作用域, 是在程序中定义的某个变量的某个区域就叫做作用域.这里的Bean作用域不同.
Bean 的作用域指: Bean在 Spring 整个框架中的某种行为模式,
比如 singleton 单例作用域, 就表示 Bean 在整个 Spring 中只有一份, 它是全局共享的, 那么当其他人修改了这个值之后, 那么另一个人读取到的就是被修改的值.
1.3 Bean 的 6 种作用域
Spring 容器在初始化一个 Bean 的示例时, 同时会指定该实例的作用域.
Spring 有 6 种作用域.
singleton
: 单例作用域prototype
: 原型作用域 (多例作用域)request
: 请求作用域session
: 回话作用域application
: 全局作用域websocket
: HTTP WebSocket 作用域
3~6 这四种是 Spring MVC 中的值.
1.4 如何设置 Bean 的作用域
@Scope 既可以用于方法注解, 也可以用于类注解
① @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
② @Scope(“prototype”)
注意事项:
如果是 @Bean + @Scope , 这里的@Scope 就不能写成类注解的方式了.
2. Bean 的生命周期
2.1 Bean 的执行流程
- 启动 Spring 容器
- 加载 Spring 配置文件
- 加载 Spring 配置文件中的 Bean, 或根据配置文件中的组件根路径, 进行 Bean 对象的扫描(扫描@Controller…)
- Bean 注册到 Spring 中
- 执行完毕,执行销毁操作
2.2 Bean 生命周期
Bean 的生命周期分为 5 大部分:
实例化 Bean (为Bean分配内存空间)
设置属性 (Bean 进行初始化注入)
Bean 初始化 (一系列准备工作)
① 各种通知 (xxxAware
)
② 执行初始化前置方法 BeanPostProcessor
③ 执行 @PostConstruct
初始化方法
④ 执行 init-mehtod
初始化方法
⑤ 执行初始化后置方法 BeanPostProcessor
使用 Bean
销毁 Bean
- ① 执行销毁前方法
@PreDestory
- ② 如果有接口
DisposableBean
, 执行实现方法 - ③ 执行销毁前的方法
destory-method
2.3 生命周期演示代码
主要代码
package com.wwzz.util; import org.springframework.beans.factory.BeanNameAware; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @Component public class BeanLifeComponent implements BeanNameAware { @Override public void setBeanName(String s) { System.out.println("执行通知: BeanNameAware " + s); } @PostConstruct public void postConstruct(){ System.out.println("执行 @PostConstruct"); } public void init() { System.out.println("执行 init-method"); } @PreDestroy public void preDestroy(){ System.out.println("执行 @PreDestroy"); } public void destroy() { System.out.println("执行 destroy"); } }
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"> <!-- 配置 Spring 扫描的根路径(此根路径下的所有 Spring 存对象的注解才能生效) --> <content:component-scan base-package="com.wwzz"></content:component-scan> <beans> <bean id="beanLifeComponent" class="com.wwzz.util.BeanLifeComponent" init-method="init" destroy-method="destroy"></bean> </beans></beans><?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"> <!-- 配置 Spring 扫描的根路径(此根路径下的所有 Spring 存对象的注解才能生效) --> <content:component-scan base-package="com.wwzz"></content:component-scan> <beans> <bean id="beanLifeComponent" class="com.wwzz.util.BeanLifeComponent" init-method="init" destroy-method="destroy"></bean> </beans> </beans>
测试运行
public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); BeanLifeComponent beanLifeComponent = context.getBean("beanLifeComponent",BeanLifeComponent.class); context.destroy(); }
查看结果
加载全部内容