Spring需要使用的组件配置pom.xml
1.Bean声明周期概述
Bean的生命周期:指bean“创建-----初始化----销毁”的过程。
Bean的生命周期是由容器进行管理的。
我们可以自定义 Bean初始化和销毁方法: 容器在Bean进行到当前生命周期的时候, 来调用自定义的初始化和销毁方法
2.Bean初始化和销毁的三种方式
2.1 指定初始化和销毁方法
在配置类里通过@Bean(initMethod="init", destroyMethod="destroy")指定
需要注册的Bean:Bike.java
public class Bike {
public Bike(){
System.out.println("Bike constructor..............");
}
public void init(){
System.out.println("Bike .....init.....");
}
public void destory(){
System.out.println("Bike.....destory");
}
}
配置类中指定Bike的init和destory方法
//@Scope("prototype")
@Bean(initMethod="init", destroyMethod="destory")
public Bike bike(){
return new Bike();
}
测试类Ch7Test.java
public class Ch7Test {
@Test
public void test01() {
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Ch7MainConfigOfLifeCycle.class);
System.out.println("IOC容器创建完成........");
app.close();
}
}
结果如下:
给容器中添加person.......
Bike constructor..............
Bike .....init.....
IOC容器创建完成........
Bike.....destory
2.2 让Bean实现 InitializingBean 和 DisposableBean接口
- InitializingBean(定义初始化逻辑,可点进去看此类):afterPropertiesSet()方法:当beanFactory创建好对象,且把bean所有属性设置好之后,会调这个方法,相当于初始化方法
- DisposableBean(定义销毁逻辑,可点进去看此类):destory()方法,当bean销毁时,会把单实例bean进行销毁
实现 InitializingBean 和 DisposableBean接口的Train.java
@Component
public class Train implements InitializingBean, DisposableBean {
public Train(){
System.out.println("Train......constructor............");
}
//当我们bean销毁时,调用此方法
@Override
public void destroy() throws Exception {
System.out.println("Train......destory......");
//logger.error
}
//当我们的bean属性赋值和初始化完成时调用
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Train.......afterPropertiesSet()...");
}
}
配置类
@ComponentScan("com.wangzhen.ch7.bean")
@Configuration
public class Ch7MainConfigOfLifeCycle {
@Bean("person")
public Person person(){
System.out.println("给容器中添加person.......");
return new Person("person",20);
}
//@Scope("prototype")
@Bean(initMethod="init", destroyMethod="destory")
public Bike bike(){
return new Bike();
}
}
结果
Train......constructor............
Train.......afterPropertiesSet()...
IOC容器创建完成........
Train......destory......
2.3 使用JSR250规则定义的(java规范)两个注解来实现
- @PostConstruct: 在Bean创建完成,且属于赋值完成后进行初始化,属于JDK规范的注解
- @PreDestroy: 在bean将被移除之前进行通知, 在容器销毁之前进行清理工作
Jeep.java
@Component
public class Jeep {
public Jeep(){
System.out.println("Jeep.....constructor........");
}
@PostConstruct
public void init(){
System.out.println("Jeep.....@PostConstruct........");
}
@PreDestroy
public void destory(){
System.out.println("Jeep.....@PreDestroy......");
}
}
结果:
Jeep.....constructor........
Jeep.....@PostConstruct........
IOC容器创建完成........
Jeep.....@PreDestroy...
3.后置处理器
负责在初始化方法前后作用。
BeanPostProcessor类[interface]: bean的后置处理器,在bean初始化之前调用进行拦截。
作用:在bean初始化前后进行一些处理工作:
- 1)postProcessBeforeInitialization():在初始化之前进行后置处理工作(在init-method之前)
什么时候调用:它任何初始化方法调用之前(比如在InitializingBean的afterPropertiesSet初始化之前,或自定义init-method调用之前使用) - 2) postProcessAfterInitialization():在初始化之后进行后置处理工作, 比如在InitializingBean的afterPropertiesSet()
//AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
实现后置处理器接口BeanPostProcessor的JamesBeanPostProcessor.java
@Component
public class JamesBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//返回一个的对象(传过来的对象)
//在初始化方法调用之前进行后置处理工作,
//什么时候调用它: init-method=init之前调用
System.out.println("postProcessBeforeInitialization...."+beanName+"..."+bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization...."+beanName+"..."+bean);
return bean;
}
}
结果:
Bike constructor..............
postProcessBeforeInitialization....bike...com.wangzhen.ch7.bean.Bike@1e81f160
Bike .....init.....
postProcessAfterInitialization....bike...com.wangzhen.ch7.bean.Bike@1e81f160
IOC容器创建完成........
4.BeanPostProcessor原理以及三个后置处理器的分析(对bean的增强)
BeanPostProcessor的作用:
- bean的赋值
- 注入其它组件
- 生命周期注解功能(都是通过后置处理器来实现注解功能)
- @Async等等
4.1 后置处理器的跟踪
AnnotationConfigApplicationContext-->refresh()-->
finishBeanFactoryInitialization(beanFactory)--->
beanFactory.preInstantiateSingletons()-->
760行getBean(beanName)--->
199行doGetBean(name, null, null, false)-->
317行createBean(beanName, mbd, args)-->
501行doCreateBean(beanName, mbdToUse, args)-->
541行createBeanInstance(beanName, mbd, args)(完成bean创建)-->
578行populateBean(beanName, mbd, instanceWrapper)(属性赋值)-->
579行initializeBean(beanName, exposedObject, mbd)(Bean初始化)->
1069行到1710行,后置处理器完成对init方法的前后处理.
最终得到如下如下
createBeanInstance(beanName, mbd, args)(完成bean创建)
populateBean(beanName, mbd, instanceWrapper); 给bean进行属性赋值
initializeBean() //初始化Bean方法内容如下,后置处理器对init方法的前后处理
{
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
invokeInitMethods(beanName, wrappedBean, mbd) //执行自定义初始化
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
}
4.2 ApplicationContextAwareProcessor实现分析
此类帮我们组建IOC容器,跟进ApplicationContextAwareProcessor我们发现,这个后置处理器其实就是判断我们的bean有没有实现ApplicationContextAware 接口,并处理相应的逻辑,其实所有的后置处理器原理均如此。
那么怎么组建呢? 只需要实现 ApplicationContextAware 接口。
实现 ApplicationContextAware 接口的Plane.java
@Component
public class Plane implements ApplicationContextAware {
private ApplicationContext applicationContext;
public Plane() {
System.out.println("Plane.....constructor........");
}
@PostConstruct
public void init(){
System.out.println("Plane.....@PostConstruct........");
}
@PreDestroy
public void destory(){
System.out.println("Plane.....@PreDestroy......");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//将applicationContext传进来,可以拿到
this.applicationContext = applicationContext;
}
}
分析源码如下:
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
//ApplicationContextAwareProcessor实现的postProcessBeforeInitialization
@Override
@Nullable
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction
step1.在创建Plane对象,还没初始化之前, 先判断是不是实现了ApplicationContextAware接口,
如果是的话就调用invokeAwareInterfaces方法, 并给里面注入值;step2.进入invokeAwareInterfaces()方法,判断是哪个aware, 如果是ApplicationContextAware, 就将当前的bean转成ApplicationContextAware类型, 调用setApplicationContext(), 把IOC容器注入到Plane里去;
-
step3.用debug调用; 测试用例打断点测试
- step4.也可看debug调用栈来分析;
注: debug可以打在ApplicationContextAwareProcessor处理器类的applyBeanPostProcessorsBeforeInitialization()方法里, 方便调试, 当bean为Plane类型时,F5跟进看, 最终在 InvokeAwareInterfaces()方法里返回我们的IOC容器applicationContext.
4.3 BeanValidationPostProcessor分析:数据校验
当对象创建完,给bean赋值后,在WEB用得特别多;把页面提交的值进行校验。
4.4 InitDestroyAnnotationBeanPostProcessor
此处理器用来处理@PostConstruct, @PreDestroy, 怎么知道这两注解是前后开始调用的呢, 就是 InitDestroyAnnotationBeanPostProcessor这个处理的。
以@PostConstruct为例, 为什么声明这个注解后就能找到初始化init方法呢?
参考
- 1)享学课堂James老师笔记