一,通过@Bean注解指定初始化和销毁方法
<bean id="person" class="com.practice.bean.Person" init-method="" destroy-method="" >
和在XML配置文件中的格式一样,在@Bean注解中也有这两个属性
String initMethod() default "";
String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
在Person类中新建init和destroy方法
private void init() {
System.out.println("----->执行init方法");
}
private void destroy() {
System.out.println("----->执行destroy方法");
}
配置类为:
@Configuration
@ComponentScan(value = "com.practice")
public class MainConfig {
@Bean(initMethod = "init",destroyMethod = "destroy")
public Person person() {
return new Person("Alen", 21);
}
}
执行测试类:
@Test
public void test01() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean.toString());
applicationContext.close();
}
打印结果如下:
----->执行init方法
Person{name='Alen', age=21}
----->执行destroy方法
可以看出在容器创建的时候执行了init的方法(可以将getBean(Person.class)注释掉),在容器销毁时执行了destroy方法。
以上是在该对象为单例的情况下,那么在多例的情况下又是如何呢?
//为配置类中加载的组件加上如下注释
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
可以看出,在容器创建的时候并没有执行初始化方法,是在获取该组件的时候执行init方法。而在容器关闭时也不会执行destroy方法。
二,通过实现InitializingBean(定义初始化逻辑)
DisposableBean(定义销毁逻辑)
让Person类实现这两个接口,可以看到需要实现两个方法:
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("--->执行afterPropertiesSet方法");
}
@Override
public void destroy() throws Exception {
System.out.println("--->执行destroy方法");
}
执行测试类,结果如下:
--->执行afterPropertiesSet方法
Person{name='Alen', age=21}
--->执行destroy方法
多例情况下也和第一部分中的情况一致。
三,可以使用JSR250:
@PostConstruct和@PreDestroy注解
在Person类中,实现如下:
@PostConstruct
private void init() {
System.out.println("----->执行init方法");
}
@PreDestroy
private void destroy() {
System.out.println("----->执行destroy方法");
}
执行测试类,结果如下:
----->执行init方法
Person{name='Alen', age=21}
----->执行destroy方法
多例情况下也和第一部分中的情况一致。
四,实现BeanPostProcessor(Bean的后置处理器)
Spring还提供了BeanPostProcessor接口在执行初始化前和初始化后的处理器,在该接口中定义了以下两个方法:
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
Person实现该接口,重写这两个方法。
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("--->执行postProcessBeforeInitialization方法"+beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("--->执行postProcessAfterInitialization方法"+beanName);
return bean;
}
}
执行测试类,结果如下:
--->执行postProcessBeforeInitialization方法mainConfig
--->执行postProcessAfterInitialization方法mainConfig
--->执行postProcessBeforeInitialization方法person
----->执行init方法
--->执行postProcessAfterInitialization方法person
Person{name='Alen', age=21}
----->执行destroy方法
可以看出在执行init方法前后,组件person分别调用了postProcessBeforeInitialization方法和postProcessAfterInitialization方法。
那么它是怎么工作的呢,我们在postProcessBeforeInitialization的返回值前加上断点,debug启动测试类:
从容器创建开始进入,找到postProcessBeforeInitialization方法怎么执行的(按照debug路径):
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//创建一个新的AnnotationConfigApplicationContext,需要进行属性赋值
//tip:此处逻辑后序阅读源码时再学习
this();
//注册传入的配置类
register(annotatedClasses);
//将传入的资源持久化
refresh();
}
进入refresh方法:可以看到调用了finishBeanFactoryInitialization方法--->实例化所有剩下的(非延迟加载)单例。
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
再进入DefaultListableBeanFactory的preInstantiateSingletons方法,按照debug路径,
最终到达AbstractAutowireCapableBeanFactory类的doCreateBean方法,在该方法中有如下代码:
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
- populateBean():使用Bean定义中的属性值填充给定BeanWrapper中的Bean实例。
在initializeBean方法中,我们终于看到了解析BeanPostProcessor的方法
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//执行postProcessBeforeInitialization方法
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()) {
//执行postProcessAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
一。先来看一下applyBeanPostProcessorsBeforeInitialization方法
@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;
}
通过getBeanPostProcessors()方法,获取到所有的BeanPostProcesors列表
0 = {ApplicationContextAwareProcessor@1856}
1 = {ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@1857}
2 = {PostProcessorRegistrationDelegate$BeanPostProcessorChecker@1858}
3 = {MyBeanPostProcessor@1787}
4 = {CommonAnnotationBeanPostProcessor@1768}
5 = {AutowiredAnnotationBeanPostProcessor@1757}
6 = {ApplicationListenerDetector@1859}
并遍历执行,其中有自定义的MyBeanPostProcessor类,此处将会执行我们重写的postProcessBeforeInitialization方法。在列表中还有InitDestroyAnnotationBeanPostProcessor组件,该组件的作用就是找到容器中加了initAnnotationType注解(或destroyAnnotationType)的方法,并通过反射去调用它,@PostConstruct就属于initAnnotationType注解,所以在此处就会执行Person的init方法。
二。再看一下postProcessAfterInitialization方法,流程也是一样
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
getBeanPostProcessors方法获取用于创建该组件的BeanPostProcessors 列表,遍历并执行postProcessAfterInitialization方法,如果返回的为空则直接返回包装好的该实例。
三。在invokeInitMethods方法中做了什么。
在invokeInitMethods主要有以下两个方法:
((InitializingBean) bean).afterPropertiesSet();
invokeCustomInitMethod(beanName, bean, mbd);
1.在该类中先判断了当前组件是否为InitializingBean:bean instanceof InitializingBean。然后执行
((InitializingBean) bean).afterPropertiesSet()方法(在属性赋值完成和BeanPostProcessorsBeforeInitialization方法后)。
2.invokeCustomInitMethod(beanName, bean, mbd)执行客户自定义的初始化方法,此处从RootBeanDefinition获取到initMethodName(此处可以发现@Bean(initMethod = "init",destroyMethod = "destroy")该注解中的init方法)并通过反射调用该方法,执行init方法。
四。BeanPostProcessor在Spring底层的应用
在一中,可以看到applyBeanPostProcessorsBeforeInitialization在获取所有的BeanPostProcesors列表,在列表中还有其他几BeanPostProcessor。
以ApplicationContextAwareProcessor为例,在其方法中为实现ApplicationContextAware接口的组件注入了ApplicationContext;ApplicationContextAwareProcessor源码中可以看出:
先执行实现的postProcessBeforeInitialization,先进行安全验证相关,然后执行了invokeAwareInterfaces(bean)方法:
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
为实现类传入了ApplicationContext。