Spring中bean对象的生命周期

Posted Magic_Li

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring中bean对象的生命周期相关的知识,希望对你有一定的参考价值。

Spring提供了一些接口来提供一些方法,体现了bean对象在Spring容器中的生命周期
      具体的过程可以体现为:

      读取权限类名->构建一个类对象->用这个类对象通过无参构造器newInstance()构建对象
                               ↓
                           调用set方法注入依赖
                               ↓
                      如果这个Bean已经实现了BeanNameAware接口
                      调用它实现的setBeanName(String name)方法
                      此处传递的就是Spring配置文件中Bean的name值
                               ↓
                      如果这个Bean已经实现了BeanFactoryAware接口
                      容器会调用它实现的setBeanFactory方法
                      该方法接收的参数就是当前容器本身(可以用这个方式来获取其它Bean)
                               ↓
                      如果这个Bean已经实现了ApplicationContextAware接口
                      容器会调用setApplicationContext方法,该步和第四步类似
                               ↓
                      如果有类实现了BeanPostProcessor接口并且注入到容器中
                      那么会执行该类中重写的postProcessBeforeInitialization(Object bean, String beanName)
                      这个方法在自己定义的init-method之前调用
                               ↓
                      执行自己在xml配置文件中注入对象定义的init-method方法
                               ↓
                      如果有类实现了BeanPostProcessor接口并且注入到容器中
                      那么会执行该类中重写的postProcessAfterInitialization(Object bean, String beanName)
                      这个方法在自己定义的init-method之后调用
                               ↓
                      当Bean不再需要时,会经过清理阶段
                      如果Bean实现了DisposableBean这个接口
                      会调用那个其实现的destroy()方法
                               ↓
                      最后,如果这个Bean的Spring配置中配置了destroy-method属性
                      会自动调用其配置的销毁方法

 

设计一个类来测试bean对象的生命周期

/*这里面测试的是spring容器中bean对象完整的生命周期*/
public class Life implements BeanNameAware,BeanFactoryAware,ApplicationContextAware,DisposableBean{

private String name;

public String getName() {
return name;
}
//1、容器创建该Bean的对象
public Life() {
System.out.println("第一步,创建对象");
}
//2、容器给这个Bean对象注入依赖
public void setName(String name) {
System.out.println("第二步,依赖注入");
this.name = name;
}
//3、如果这个Bean已经实现了BeanNameAware接口,容器会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值
@Override
public void setBeanName(String name) {
System.out.println("第三步,调用setBeanName方法,因为bean类实现了BeanNameAware");
}
//4、如果这个Bean已经实现了BeanFactoryAware接口,容器会调用它实现的setBeanFactory方法
//该方法接收的参数就是当前容器本身(可以用这个方式来获取其它Bean)
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("第四步,调用setBeanFactory方法,因为bean类实现了BeanFactoryAware");
}

//5、如果这个Bean已经实现了ApplicationContextAware接口,容器会调用setApplicationContext方法,该步和第四步类似,ApplicationContext是BeanFactory的子接口,有更多的实现方法
@Override
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
System.out.println("第五步,调用setApplicationContext方法,因为bean类实现了ApplicationContextAware");
}
//9、当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法;
@Override
public void destroy() throws Exception {
System.out.println("第九步,调用destroy方法,因为bean类实现了ApplicationContextAware");
}

/**
*注意下面的两个方法是自定义的初始化和销毁对象方法
*需要在注入对象的时候指定init-method="..",destroy-method="..."
*注意方法的执行顺序
*init-method在各个初始化方法执行之后才执行
*destroy-method在最后执行
*/
//7、如果Bean在Spring配置文件中配置了init-method属性则会自动调用其配置的初始化方法
//init-method="myInit"
public void myInit(){
System.out.println("第七步,调用myInit方法,因为bean在xml中的配置里面使用了init-method属性来指定初始化方法");
}

//10、最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法
public void myDestroy(){
System.out.println("第十步,调用myDestroy方法,因为bean在xml中的配置里面使用了destroy-method属性来指定初始化方法");
}

}

 

再写一个类用来实现BeanPostProcessor接口

/*注意:需要把这个类注册到spring的容器中,才能生效*/
public class MyBeanPostProcessor implements BeanPostProcessor{

//这个方法在自己定义的init-method之前调用
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第六步,调用postProcessBeforeInitialization方法,因为spring容器中注册了BeanPostProcessor接口的实现类");
return bean;
}
//这个方法在自己定义的init-method之后调用
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第八步,调用postProcessAfterInitialization方法,因为spring容器中注册了BeanPostProcessor接口的实现类");
return bean;
}

}

 

我们在配置文件中进行一个配置

<bean class="com.briup.ioc.life.MyBeanPostProcessor"></bean>

<bean name="life" class="Life" init-method="myInit" destroy-method="myDestroy">
<property name="name" value="张三"></property>
</bean>

以上是完整的生命周期,下面来说的是非完整的生命周期,一般来说在开发的时候没有必要每次都让一个对象都具有完整生命周期的方法

/*这里面测试的是spring容器中bean对象普通的声明周期*/
/*Bean中不实现spring提供的任何接口,之后项目大多数Bean是这种情况*/
public class LifeBean{
private String name;

public LifeBean(){
System.out.println("LifeBean() 构造器");
}
public String getName() {
return name;
}

public void setName(String name) {
System.out.println("setName() 方法");
this.name = name;
}

public void init(){
System.out.println("init方法执行");
}

public void destory(){
System.out.println("destory方法执行");
}

}

 

生命周器对于单例对象和非单例对象来说,非单例对象在创建后会脱离容器的控制
单例管理的对象:
1.默认情况下,spring在读取xml文件的时候,就会创建对象
2.进行依赖注入,如果有依赖的话
3.会去调用init-method=".."属性值中所指定的方法,如果有该配置的话
4.Bean对象可以被正常使用
5.对象在被销毁的时候,会调用destroy-method="..."属性值中所指定的方法,如果有该配置的话

注意1:调用container.destroy()方法会销毁单例对象
注意2:lazy-init="true",可以让这个Bean对象在第一次被访问的时候创建,而不是读取xml文件就被创建
注意3:因为是单例,所以该对象只会被创建一次


非单例管理的对象:
1.使用这个对象的时候,spring容器会创建这个对象
2.进行依赖注入,如果有依赖的话
3.会去调用init-method=".."属性值中所指定的方法,如果有该配置的话
4.Bean对象可以被正常使用

注意1:spring容器不会销毁非单例对象
注意2:因为是非单例,所以每次使用都会创建一个新的Bean对象
非单例也是当获取对象的时候再加载,不会受到Spring容器的管理

以上是关于Spring中bean对象的生命周期的主要内容,如果未能解决你的问题,请参考以下文章

Spring中bean对象的生命周期

Spring Bean 在容器的生命周期是什么样的?

Spring Bean的生命周期:

Spring Bean的生命周期

Spring Bean 作用域和生命周期

spring bean的生命周期是怎样的,代码示例