7.1什么是Bean的生命周期
Spring其实就是一个管理Bean对象的工厂。它负责对象的创建,对象的销毁等。
生命周期就可以理解为一个Bean对象从创建到销毁的过程
7.2 Bean生命周期----五步
- 实例化Bean
- Bean属性赋值
- 初始化Bean
- 使用Bean
- 销毁Bean
在这里我们给一个Bean对象
public class User {
private String name;
public User() {
System.out.println("1.实例化Bean");
}
public void setName(String name) {
this.name = name;
System.out.println("2.Bean属性赋值");
}
public void initBean(){
System.out.println("3.初始化Bean");
}
public void destroyBean(){
System.out.println("5.销毁Bean");
}
}
xml文件
<bean id="user" class="com.myStudy.User" init-method="initBean" destroy-method="destoryBean" >
<property name="name" value="zhangsan"></property>
这里需要注意的是 多了两个标签 , 这里就是指定初始化方法和销毁方法 而这两个标签的值就是对应的方法名 (感觉这一部分肯定跟反射有关)
测试类
public void testLifecycle(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
User userBean = applicationContext.getBean("userBean", User.class);
System.out.println("4.使用Bean");
// 只有正常关闭spring容器才会执行销毁方法因为销毁方法ApplicationContext没有 所以要向下转型 (多态弊端 不能调用子类特有的方法)
ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;
context.close();
}
运行结果
注意事项
- 第一:只有正常关闭spring容器,bean的销毁方法才会被调用。
- 第二:ClassPathXmlApplicationContext类才有close()方法。
- 第三:配置文件中的init-method指定初始化方法。destroy-method指定销毁方法
7.3 Bean生命周期----七步
在以上的5步中,第3步是初始化Bean,如果你还想在初始化前和初始化后添加代码,可以加入“Bean后处理器”。
编写一个类实现BeanPostProcessor接口 重写before和after方法
public class LogBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean后处理器的before方法执行,即将开始初始化");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean后处理器的after方法执行,已完成初始化");
return bean;
}
编写xml文件
<!--配置Bean后处理器。这个后处理器将作用于当前配置文件中所有的bean。-->
<bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/>
测试结果
所以这里的七步流程应该如下图所示
7.4Bean生命周期----十步
十步就是更加详细的生命周期了 它与七步的差别就是实现了一些接口
Aware相关的接口包括:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
- 当Bean实现了BeanNameAware,Spring会将Bean的名字传递给Bean。
- 当Bean实现了BeanClassLoaderAware,Spring会将加载该Bean的类加载器传递给Bean。
- 当Bean实现了BeanFactoryAware,Spring会将Bean工厂对象传递给Bean。
测试以上10步,可以让User类实现5个接口,并实现所有方法:
- BeanNameAware
- BeanClassLoaderAware
- BeanFactoryAware
- InitializingBean
- DisposableBean
我们重新改一下User类
public class User implements BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, InitializingBean, DisposableBean {
private String name;
public User() {
System.out.println("第一步 实例化bean");
}
public void setName(String name) {
System.out.println("第二步 set注入给属性赋值");
this.name = name;
}
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("这是第三步中可以得到类加载器的"+classLoader);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("这是第三步中可以得到BeanFactory的" +beanFactory);
}
@Override
public void setBeanName(String name) {
System.out.println("这是第三步中得到BeanName的"+name);
}
//第四步 Bean后处理器before方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("第五步 Properties执行");
}
// init初始化方法 方法名随意 但需要在xml配置
public void initBean(){
System.out.println("第六步 初始化bean");
// 第七步 Bean后处理器的after方法
// 第八步 使用Bean
@Override
public void destroy() throws Exception {
System.out.println("第九步 DisposableBean");
}
// destory销毁方法 方法名随意 但需要在xml配置
public void destoryBean(){
System.out.println("第十步 销毁bean");
}
}
测试结果
通过测试可以看出来:
- InitializingBean的方法早于init-method的执行。
- DisposableBean的方法早于destroy-method的执行。
7.5 Bean作用域不同 管理方式不同
Spring 根据Bean的作用域来选择管理方式。
- 对于Singleton作用于的Bean(单例模式) Spring负责生命周期的整个过程 包括创建 初始化销毁等…
- 而对于 prototype 作用域的 Bean,Spring 不会对 Bean 进行完整的生命周期管理是因为在多例模式下,每次获取 Bean 都会创建一个新的实例,而且 Spring 不会对这些实例进行跟踪和管理
我们可以把之前的配置文件修改成多例模式 (scope=“prototype”)
<bean id="user" class="com.myStudy.User" init-method="initBean" destroy-method="destoryBean" scope="prototype">
<property name="name" value="zhangsan"></property>
测试结果
通过测试一目了然。只执行了前8步,第9和10都没有执行。