Spring注解开发(二)生命周期

一,通过@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。

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值