时隔一年多,在掌握了Spring、SpringBoot、SpringCloud之后
我再次回头,重新学习Spring框架
Bean的生命周期学习:
在传统的XML配置中,可以这样自定义初始化和销毁方法:
init-method="" destroy-method=""
注解方式的简单使用:
@Configuration public class LifeCircleConfig {@Bean(initMethod = "init",destroyMethod = "destroy")public Car car(){return new Car();} }
public class Car {public Car(){System.out.println("Construct Car!");}public void init(){System.out.println("Car init!");}public void destroy(){System.out.println("Car destroy!");} }
public class LifeCircleTest {private static AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeCircleConfig.class);@Testpublic void test(){applicationContext.close();} }
注意:要有close方法,否则不会打印Car销毁方法
打印如下:
Construct Car! Car init! Car destroy!
这里默认的是单实例Bean
如果是多实例的话,按照以上的测试代码是不会打印的,因为多实例情况下,在获取Bean的情况下才会创建对象
而且在多例情况下,只会调用初始化和构造方法,不会调用销毁方法
以上测试代码只完成了初始化IOC容器,所以什么都不打印
实现Spring中接口方式:这时候不需要在@Bean中进行配置
public class Car implements InitializingBean, DisposableBean {public Car() {System.out.println("Construct Car!");}public void afterPropertiesSet() throws Exception {System.out.println("Car init!");}public void destroy() {System.out.println("Car destroy!");}}
使用Java原生注解:
public class Car {public Car() {System.out.println("Construct Car!");}@PostConstructpublic void init() {System.out.println("Car init!");}@PreDestroypublic void destroy() {System.out.println("Car destroy!");}}
使用Spring中Bean的后置处理器:
@Component public class MyBeanPostProcessor implements BeanPostProcessor {/*** 初始化前调用*/public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessBeforeInitialization " + bean + " " + beanName);return bean;}/*** 初始化后调用*/public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessAfterInitialization " + bean + " " + beanName);return bean;} }
@Configuration @ComponentScan("org.dreamtech.bean") public class LifeCircleConfig {@Beanpublic Car car(){return new Car();} }
测试后部分打印如下:
Construct Car!
postProcessBeforeInitialization org.dreamtech.bean.Car@2d9d4f9d car
postProcessAfterInitialization org.dreamtech.bean.Car@2d9d4f9d car
BeanPostProcessor原理:
查看这一段源码:
initializeBean(beanName, exposedObject, 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);}
在invokeInitMethods初始化方法之前
调用了applyBeanPostProcessorsBeforeInitialization,也就是调用了所有PostProcessor的Before方法
在invokeInitMethods初始化方法之后
调用了applyBeanPostProcessorsAfterInitialization,也就是调用了所有PostProcessor的After方法
进入applyBeanPostProcessorsBeforeInitialization方法查看源码:
遍历所有的Processor,一旦返回null,就会跳出循环
@Overridepublic Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {result = beanProcessor.postProcessBeforeInitialization(result, beanName);if (result == null) {return result;}}return result;}
在initializeBean方法之前,调用的是populateBean方法
作用:给属性赋值
// Initialize the bean instance.Object exposedObject = bean;try {populateBean(beanName, mbd, instanceWrapper);if (exposedObject != null) {exposedObject = initializeBean(beanName, exposedObject, mbd);}}
所以:BeanPostProcessor是在Bean赋值之后,初始化的过程前后执行的
BeanPostProcessor在Spring底层的使用:
获取IOC容器的接口:
public interface ApplicationContextAware extends Aware {void setApplicationContext(ApplicationContext var1) throws BeansException; }
而它就是基于BeanPostProcessor的,代码过长就不截取了
class ApplicationContextAwareProcessor implements BeanPostProcessor
或者是参数校验:也使用到了BeanPostProcessor
public class BeanValidationPostProcessor implements BeanPostProcessor, InitializingBean
部分代码如下:
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (!this.afterInitialization) {this.doValidate(bean);}return bean;}public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (this.afterInitialization) {this.doValidate(bean);}return bean;}