JSR250
提供的两个注解;BeanPostProcessor
后置处理器;可以使用 @Bean
注解的两个属性设置初始化和销毁方法:
@Bean(initMethod = "init", destroyMethod = "destroy") public Car car() { return new Car(); }
这里在实体类中创建了几个方法。
public class Car { public Car() { System.out.println("汽车构造器..."); } public void init() { System.out.println("汽车初始化..."); } public void destroy() { System.out.println("汽车销毁了..."); } }
实际的测试结果如下:
汽车构造器... 汽车初始化了... 容器初始化了...
这两个类都是接口,其中 InitializingBean
有一个抽象方法 afterPropertiesSet
,DisposableBean
有一个抽象方法 destroy
,分别代表 init
和 destroy
方法。
继承之后可以重写这两个方法:
public void destroy() { System.out.println("汽车销毁了..."); } @Override public void afterPropertiesSet() throws Exception { System.out.println("汽车初始化了..."); }
效果也和上面一样,这样就不用再使用 @Bean 指定初始化和销毁方法了。
注意:
这两个注解都是 JSR250
提供的注解:
@PostConstruct
: 在 bean 创建完成并且属性赋完值的时候调用方法;@PreDestroy
: 在容器销毁 bean 之前通知我们进行清理操作;该注解在实体类上的方法使用:
/** * 对象创建并赋值之后调用 */ @PostConstruct public void init() { System.out.println("汽车初始化..."); } /** * 容器移除对象之前调用 */ @PreDestroy public void destroy() { System.out.println("汽车销毁了..."); }
该类的作用就是在 bean
初始化前后进行一些处理工作,它是一个接口;
该接口有两个方法:
postProcessBeforeInitialization
:在初始化之前调用;postProcessAfterInitialization
: 在初始化之后调用;所以我们可以写一个实现类来实现这些方法:
@Component public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化之前:" + beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化之后:" + beanName); return bean; } }
执行之后,这两个方法会在初始化方法被调用的前后分别被调用,应用于容器中所有的 bean
。
下面分析一下 BeanPostProcessor 的执行原理:
这是截取的一段源代码,出自 AbstractAutowireCapableBeanFactory
类,该方法叫做 doCreateBean
:
// Initialize the bean instance. Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); }
这段代码很容易理解,就是初始化 bean 实例,涉及两个方法:
populateBean
:将属性值填充到 Bean
中,就是给 Bean 属性赋值;initializeBean
:初始化 Bean
;来看一下该类的 initializeBean
方法做了什么:
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); }
该方法中有三处比较重要:
applyBeanPostProcessorsBeforeInitialization
:在 Bean 初始化之前执行;invokeInitMethods
:执行自定义初始化;applyBeanPostProcessorsAfterInitialization
:在 Bean 初始化之后执行;查看前置方法的源码,发现他就是循环遍历所有的 BeanPostProcessor
,然后依次执行,后置方法同理。
@Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessBeforeInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
而且这两个方法和我们写实现类重写的两个方法同名,作用也一致,这里是 Spring
使用了代理模式进行了增强,我们重写的部分就是增强的内容。
注:
Spring 底层很多地方都使用了 BeanPostProcessor
及其子类,如 AutowiredAnnotationBeanPostProcessor
,就是 @Autowired
注解。
本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。
我来说两句