最近,学习Spring注解的时候,看完晚上的教学视频,在此将Spring注解的Bean的生命周期这一章的内容写下来,方便以后自己会看。
Bean创建-------->Bean初始化-------->Bean销毁
自定义初始化和销毁的方法:容器在Bean进行到当前生命周期的时候来调用我我们自定义的初始化和销毁方法。
标签中添加init-method
以及destory-method
这两个属性,指定初始化和销毁的方法。@Bean
的initMethod
以及destoryMethod
这两个属性,指定初始化和销毁的方法。 我们在bean文件包下面创建一个Car类文件,内部有一个无参构造器、一个初始化方法以及一个销毁方法。
package com.xiaojian.bean;
public class Car {
public Car(){
System.out.println("car...constructor");
}
public void init(){
System.out.println("car...init");
}
public void destory(){
System.out.println("car...destory");
}
}
我们在config文件包下面创建一个MainConfig1类文件,内部有一个bean。
package com.xiaojian.config;
import com.xiaojian.bean.Car;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class MainConfig1 {
// @Scope("prototype") //此为多实例
@Bean(value = "car",initMethod = "init",destroyMethod = "destory")
public Car car(){
return new Car();
}
}
我们在test文件包下面创建MainTest1测试类文件。
package com.xiaojian.test;
import com.xiaojian.config.MainConfig1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainTest1 {
public static void main(String[] args) {
//1、创建IOC容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig1.class);
System.out.println("IOC容器创建完成");
Object car = applicationContext.getBean("car");
System.out.println("car的bean创建完成");
//2、关闭容器
applicationContext.close();
System.out.println("IOC容器关闭");
}
}
D:\basic\jdk\jdk1.8.0_131\bin\java ...
car...constructor
car...init
IOC容器创建完成
car的bean创建完成
car...destory
IOC容器关闭
Process finished with exit code 0
如上,为控制台打印的日志文件,可以看出来在单实例的情况下,bean对象在IOC容器初始化完成之前就已经创建完成,同时初始化方法init
在bean对象创建完成之后直接运行,等容器关闭的时候destory
方法运行。
D:\basic\jdk\jdk1.8.0_131\bin\java ...
IOC容器创建完成
car...constructor
car...init
car的bean创建完成
IOC容器关闭
Process finished with exit code 0
如上,为控制台打印的日志文件,可以看出来在多实例的情况下面,IOC容器创建的时候bean对象并没有被创建,而是等到我们容器调用这个bean的时候才创建这个bean,同时运行init这个初始化方法,但是多实例的容器的销毁方法不会运行,也就是IOC容器不管理多实例的bean的销毁。
InitializingBean
(定义初始化逻辑)与DisposableBean
(定义销毁逻辑) 让Bean对象实现InitializingBean
接口,重写它的afterPropertiesSet()
方法;同时让bean对象实现DisposableBean
接口,重写它的destroy()
方法来定义销毁逻辑。
我们在bean文件包下面创建一个Cat类文件,此类实现InitializingBean
、DisposableBean
这两个接口,并且重写对应的方法,同时此类本身有一个无参构造器。
package com.xiaojian.bean;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
//此处使用@Component注解将此bean加入到IOC容器中(也可以在配置类中通过添加@Bean的方式添加)
@Component
public class Cat implements InitializingBean,DisposableBean{
public Cat(){
System.out.println("cat...constructor");
}
@Override
public void destroy() throws Exception {
System.out.println("cat...destory");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("cat...afterPropertiesSet");
}
}
我们在config文件包下面创建一个MainConfig2类文件,此配置类中没有bean对象的方法,而是添加了@ComponentScan
注解来扫描bean对象。
package com.xiaojian.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//通过注解@ComponentScan注解扫描bean文件包下面的所有配置文件
@ComponentScan("com.xiaojian.bean")
@Configuration
public class MainConfig2 {
}
我们在test文件包下面创建MainTest2测试类文件。
package com.xiaojian.test;
import com.xiaojian.config.MainConfig2;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainTest2 {
public static void main(String[] args) {
//1、创建IOC容器
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(MainConfig2.class);
System.out.println("IOC容器创建完成");
System.out.println("IOC容器关闭");
applicationContext.close();
}
}
测试结果:
D:\basic\jdk\jdk1.8.0_131\bin\java ...
cat...constructor
cat...afterPropertiesSet
IOC容器创建完成
IOC容器关闭
cat...destory
Process finished with exit code 0
如上,未控制台打印的日志文件,可以看出来,在IOC容器初始化之前就已经创建好了bean对象,使用了afterPropertiesSet
初始化方法,在IOC容器关闭的时候使用了destory
销毁方法。
@PostConstruct
:在Bean创建完成并且属性赋值完成之后来执行初始化方法。@PreDestory
:在容器销毁Bean之前通知我们进行清理工作。 我们在bean文件包下面创建一个Dog类文件,内部有一个无参构造器,一个init
方法,一个destory
方法。同时init
方法添加上注解@PostConstruct
,destory
方法添加上注解@PreDestory
。
package com.xiaojian.bean;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
//此处使用@Component注解将此bean加入到IOC容器中
// (也可以在配置类中通过添加@Bean的方式添加)
@Component
public class Dog {
public Dog(){
System.out.println("dog...constructor");
}
//对象创建并赋值之后调用
@PostConstruct
public void init(){
System.out.println("dog...@PostConstruct");
}
//在容器销毁之前调用
@PreDestroy
public void destory(){
System.out.println("dog...@PreDestory");
}
}
我们在config文件包下面创建一个MainConfig3类文件,此配置类中没有bean对象的方法,而是添加了@ComponentScan
注解来扫描bean对象。
package com.xiaojian.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//通过注解@ComponentScan注解扫描bean文件包下面的所有配置文件
@ComponentScan("com.xiaojian.bean")
@Configuration
public class MainConfig3 {
}
我们在test文件包下面创建MainTest3测试类文件。
package com.xiaojian.test;
import com.xiaojian.config.MainConfig2;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainTest3 {
public static void main(String[] args) {
//1、创建IOC容器
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(MainConfig2.class);
System.out.println("IOC容器创建完成");
System.out.println("IOC容器关闭");
applicationContext.close();
}
}
测试结果:
D:\basic\jdk\jdk1.8.0_131\bin\java ...
dog...constructor
dog...@PostConstruct
IOC容器创建完成
IOC容器关闭
dog...@PreDestory
Process finished with exit code 0
如上,为控制台打印的日志文件,可以看出来,在IOC容器初始化之前就已经创建好了bean对象,使用了@PostConstruct
注解标注的init
初始化方法,在IOC容器关闭的时候使用了@PreDestory
注解标注的destory
销毁方法。
BeanPostProcessor
-bean的后置处理器(接口) 在Bean初始化进行前后进行一系列的处理操作:
postProcessBeforeInitialization
:在初始化之前工作postProcessAfterInitialization
:在初始化之后工作 在bean文件包下面创建MyBeanPostProcessor类文件,实现BeanPostProcessor
接口。
package com.xiaojian.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
/**
* 后置处理器:初始化前后进行处理
* 将后置处理器加入容器中
*/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization...before..."+beanName+": "+bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization...after..."+beanName+": "+bean);
return bean;
}
}
此处的配置类我们用MainConfig3配置类,测试类也用MainTest3测试类,同时我们使用Cat、Dog这两个bean对象。
运行MainTest3测试类,测试结果如下:
D:\basic\jdk\jdk1.8.0_131\bin\java ...
cat...constructor
postProcessBeforeInitialization...before...cat: com.xiaojian.bean.Cat@71d15f18
cat...afterPropertiesSet
postProcessAfterInitialization...after...cat: com.xiaojian.bean.Cat@71d15f18
dog...constructor
postProcessBeforeInitialization...before...dog: com.xiaojian.bean.Dog@2df32bf7
dog...@PostConstruct
postProcessAfterInitialization...after...dog: com.xiaojian.bean.Dog@2df32bf7
IOC容器创建完成
IOC容器关闭
dog...@PreDestory
cat...destory
Process finished with exit code 0
如上,IOC容器中有两个bean对象,而且在这两个bean对象的初始化前后都有同一个现象。
在Cat这个bean对象初始化之前,容器先运行了MyBeanPostProcessor中的postProcessBeforeInitialization
方法;初始化之后,容器运行了MyBeanPostProcessor中的postProcessAfterInitialization
方法。(Dog同样)
下面按照顺序的执行:
(单例)构造bean
BeanPostProcessor.postProcessBeforeInitialization
初始化:对象创建完成,并赋值好,之后调用方法
BeanPostProcessor.postProcessAfterInitialization
销毁:单实例—在容器关闭的时候销毁(多实例时候容器部管理bean的销毁)
BeanPostProcessor
BeanPostProcessor
遍历得到容器中所有的BeanPostProcessor
:挨个执行beforeInitialization
,一旦返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessBeforeInitialization
。
BeanPostProcessor
内部初始化原理:
populateBean(beanName,mbd,instanceWrapper)
—给bean进行属性赋值
InitializeBean
的工作顺序:
applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName)
;invokeInitMethods(beanName,wrappedBean,mbd)
—执行初始化applyBeanPostProcessorsAfterInitialization(wrappedBean,beanName)
;