Spring源码 - @Resource、@PostConstruct、@PreDestroy原理分析(CommonAnnotationBeanPostProcessor - 上)

目录

一、初始化

CommonAnnotationBeanPostProcessor的静态代码块初始化

CommonAnnotationBeanPostProcessor的无参数构造初始化

二、生命周期和回调时机

1、实现了BeanFactoryAware

2、继承自InitDestroyAnnotationBeanPostProcessor

1)、实现了PriorityOrdered排序接口

2)、实现了MergedBeanDefinitionPostProcessor(生命周期检查阶段)

3)、实现了DestructionAwareBeanPostProcessor接口(生命周期销毁阶段)

3、实现了顶层接口BeanPostProcessor(生命周期初始化阶段)

4、实现了接口InstantiationAwareBeanPostProcessor

总结


    CommonAnnotationBeanPostProcessor处理@Resource、javax.xml.ws.WebServiceRef、javax.ejb.EJB类型;而父类InitDestroyAnnotationBeanPostProcessorinitAnnotationTypedestroyAnnotationType分别存储自定义init方法(@PostConstruct)和@PreDestroy的方法。

 

一、初始化

CommonAnnotationBeanPostProcessor的静态代码块初始化

static {
    try {
        @SuppressWarnings("unchecked")
        Class<? extends Annotation> clazz = (Class<? extends Annotation>)
                ClassUtils.forName("javax.xml.ws.WebServiceRef", CommonAnnotationBeanPostProcessor.class.getClassLoader());
        webServiceRefClass = clazz;
    } catch (ClassNotFoundException ex) {
        webServiceRefClass = null;
    }
    try {
        @SuppressWarnings("unchecked")
        Class<? extends Annotation> clazz = (Class<? extends Annotation>)
                ClassUtils.forName("javax.ejb.EJB", CommonAnnotationBeanPostProcessor.class.getClassLoader());
        ejbRefClass = clazz;
    } catch (ClassNotFoundException ex) {
        ejbRefClass = null;
    }

    resourceAnnotationTypes.add(Resource.class);
    if (webServiceRefClass != null) {
        resourceAnnotationTypes.add(webServiceRefClass);
    }
    if (ejbRefClass != null) {
        resourceAnnotationTypes.add(ejbRefClass);
    }
}

 

CommonAnnotationBeanPostProcessor的无参数构造初始化

public CommonAnnotationBeanPostProcessor() {
    setOrder(Ordered.LOWEST_PRECEDENCE - 3);
    setInitAnnotationType(PostConstruct.class);
    setDestroyAnnotationType(PreDestroy.class);
    ignoreResourceType("javax.xml.ws.WebServiceContext");
}

 

二、生命周期和回调时机

先看一下CommonAnnotationBeanPostProcessor的层级结构,并且按照调用顺序进行分析

1、实现了BeanFactoryAware

    那么会回调设置BeanFactory

2、继承自InitDestroyAnnotationBeanPostProcessor

1)、实现了PriorityOrdered排序接口

    在无参数构造中设置了排序值,在ApplicationContextAwareProcessor之后。

2)、实现了MergedBeanDefinitionPostProcessor(生命周期检查阶段)

    那么在getBean时,第一次缓存中没有,在调用doCreateBean时第3步会对所有MergedBeanDefinitionPostProcessorpostProcessMergedBeanDefinition方法进行回调。调用时机,详见:SpringIoc源码(十七)- BeanFactory(六)- getBean(doCreateBean总览)#3、MergedBeanDefinitionPostProcessor回调

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, 
    Class<?> beanType, String beanName) {
    // 父类处理@PostConstruct、@PreDestroy的生命周期相关(check、init、destory、has)
    super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
    // 子类处理@Resource(javax.xml.ws.WebServiceRef和javax.ejb.EJB不考虑了)
    InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}

    父类和子类按照层级处理各自内部的注解,当然在postProcessMergedBeanDefinition方法中只是check阶段。

3)、实现了DestructionAwareBeanPostProcessor接口(生命周期销毁阶段)

    之前分析过在所有bean在getBean时,只要实现了DisposableBean接口,那么都会往Spring注销容器中添加适配模式的DisposableBeanAdapter对象。详细见SpringIoc源码(十七)- BeanFactory(六)- getBean(doCreateBean总览)#6、注册DisposableBean那么在Bean注销时则会调用所有DestructionAwareBeanPostProcessorpostProcessBeforeDestruction方法,执行生命阶段的销毁方法。

@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    // 省略try catch部分的代码
    metadata.invokeDestroyMethods(bean, beanName);
}

 

3、实现了顶层接口BeanPostProcessor(生命周期初始化阶段)

    则执行时机是该Bean生命周期回调阶段,会回调postProcessBeforeInitialization方法。执行时机在check之后,在destory之前。知道了定义的注解@Resource的个的生命周期,并且按层进行处理。那么主要的就是看生命周期中都这么进行处理的。

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    // 省略try catch部分代码
    metadata.invokeInitMethods(bean, beanName);
    return bean;
}

   

4、实现了接口InstantiationAwareBeanPostProcessor

    实现了InstantiationAwareBeanPostProcessor接口,那么在每个Bean的getBean时生命周期的SpringIoc源码(十九)- BeanFactory(八)- getBean(doCreateBean - populateBean属性填充)3、InstantiationAwareBeanPostProcessor#postProcessPropertyValues属性填充阶段回调。

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
    // 省略try catch部分
    metadata.inject(bean, beanName, pvs);
    return pvs;
}

可能会调用的postProcessPropertyValues回调方法,就是调用了该方法:

@Deprecated
@Override
public PropertyValues postProcessPropertyValues(
    PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {

    return postProcessProperties(pvs, bean, beanName);
}

总结

    CommonAnnotationBeanPostProcessor本类中处理了 @Resource注解,父类中处理了@PostConstruct、@PreDestroy注解。 父类中维护生命周期LifecycleMetadata定义的checkConfigMembers、invokeInitMethods、invokeDestroyMethods、hasDestroyMethods。本类中维护生命周期InjectionMetadata定义的checkConfigMembers、inject、clear。其定义的生命周期,与实现了BeanPostProcessor类型和回调方法关联。静态代码块和构造函数中配置了需要处理的类型,而这三个注解只是其中的一种类型,也保证了扩展性,回调的顺序入下:

1、MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition

    LifecycleMetadata checkConfigMembers (间接调用了findLifecycleMetadata)

    InjectionMetadata checkConfigMembers (间接调用了findResourceMetadata

2、BeanPostProcessor#postProcessBeforeInitialization

    LifecycleMetadata#invokeInitMethods

3、InstantiationAwareBeanPostProcessor#postProcessProperties

    InjectionMetadata#inject

4、DestructionAwareBeanPostProcessor#postProcessBeforeDestruction

    LifecycleMetadata#invokeDestroyMethods

 

    知道了是按层对不同的注解进行处理,也知道注解定义了生命周期,并且知道了回调顺序、时机。并且都调用了findLifecycleMetadata方法和各种生命周期的方法,那么下面需要专门各自生命周期。下一篇专门分析

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值