Spring 注解面面通 之 @PostConstruct 深入源码解析

  @PostConstruct的应用以及与afterPropertiesSetinit-method对比请查看《Spring 注解面面通 之 @PostConstruct 应用解析以及与afterPropertiesSet、init-method对比》

  @PostConstructInitializingBean的源码流程有一部分是重叠的,可以参考《Spring 知识面面通 之 InitializingBean 深入源码解析》

  Spring利用BeanPostProcessor后置处理器来处理@PostConstruct@PreDestroy注解,InitDestroyAnnotationBeanPostProcessor是处理@PostConstruct@PreDestroy注解的主要参与者。

  源码解析

  1) AbstractAutowireCapableBeanFactoryinitializeBean(...)方法。

  ① 若Bean实现了Aware接口,则触发方法调用。包括:BeanNameAwareBeanClassLoaderAwareBeanFactoryAware

  ② 调用注册的BeanPostProcessorpostProcessBeforeInitialization(...)方法。其中InitDestroyAnnotationBeanPostProcessor用来处理@PostConstruct@PreDestroy注解。

  ③ 调用初始化方法,包括InitializingBeanafterPropertiesSet()方法和Beaninit-method指定的方法。

  ④ 调用注册的BeanPostProcessorpostProcessAfterInitialization(...)方法。

/**
 * 初始化给定的Bean实例,应用工厂回调、init方法和Bean后处理程序.
 * 对于传统定义的Bean,从createBean调用,对于现有的Bean实例从initializeBean调用.
 * @param beanName 工厂中的Bean名称(用于调试).
 * @param bean 需要初始化新的Bean实例.
 * @param mbd 创建Bean时使用的Bean定义(如果给定现有的Bean实例,也可以是null).
 * @return 初始化的Bean实例(可能被包装).
 */
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    // 若Bean实现了Aware接口,则触发方法调用.
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    // 在Bean初始化前处理BeanPostProcessor.
    // !mbd.isSynthetic()表示用户自定义而非框架所有.
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    // 进行Bean初始化,包括如下两种方式:
    // 1.调用InitializingBean.afterPropertiesSet()方法.
    // 2.调用Bean配置的init-method方法.
    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
    }
    // 在Bean初始化后处理BeanPostProcessor.
    // !mbd.isSynthetic()表示用户自定义而非框架所有.
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

  2) InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(...)方法。

  ① 获取指定Bean类型生命周期元数据。

  ② 调用Bean类型生命周期元数据的初始化方法。

/**
 * 初始化之前处理程序.
 */
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // 获取Bean类型生命周期元数据.
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    try {
        // 调用元数据的初始化方法.
        metadata.invokeInitMethods(bean, beanName);
    }
    catch (InvocationTargetException ex) {
        throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
    }
    return bean;
}

  3) InitDestroyAnnotationBeanPostProcessor.invokeInitMethods(...)方法。

  ① 遍历搜集到Bean的所有初始化方法。

  ② 进行Bean实际初始化方法调用。

/**
 * 调用元数据的初始化方法.
 */
public void invokeInitMethods(Object target, String beanName) throws Throwable {
    Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
    Collection<LifecycleElement> initMethodsToIterate =
        (checkedInitMethods != null ? checkedInitMethods : this.initMethods);
    if (!initMethodsToIterate.isEmpty()) {
        boolean debug = logger.isDebugEnabled();
        for (LifecycleElement element : initMethodsToIterate) {
            if (debug) {
                logger.debug("Invoking init method on bean '" + beanName + "': " + element.getMethod());
            }
            // 调用实际方法.
            element.invoke(target);
        }
    }
}

  4) InitDestroyAnnotationBeanPostProcessor.findLifecycleMetadata(...)方法。

  ① lifecycleMetadataCache生命周期元数据缓存为空,则重新创建生命周期元数据。

  ② 采用双重检查锁机制来进行快速检查,尽量减少对锁的使用。

  ③ 若需新建生命周期元数据,调用buildLifecycleMetadata(...)创建生命周期元数据。

/**
 * 查找指定类型的生命周期元数据.
 */
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
    // lifecycleMetadataCache为空,则重新创建生命周期元数据.
    if (this.lifecycleMetadataCache == null) {
        return buildLifecycleMetadata(clazz);
    }
    // 首先进行快速检查,只需最少的锁竞争.
    LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
    if (metadata == null) {
        synchronized (this.lifecycleMetadataCache) {
            metadata = this.lifecycleMetadataCache.get(clazz);
            if (metadata == null) {
                metadata = buildLifecycleMetadata(clazz);
                this.lifecycleMetadataCache.put(clazz, metadata);
            }
            return metadata;
        }
    }
    return metadata;
}

  5) InitDestroyAnnotationBeanPostProcessor.buildLifecycleMetadata(...)方法。

  ① 创建初始化和销毁方法存储集合。

  ② 查找initAnnotationType类型注释的方法,放入初始化方法集合。

  ③ 查找destroyAnnotationType类型注释的方法,放入初始化方法集合。

/**
 * 创建生命周期元数据.
 */
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
    final boolean debug = logger.isDebugEnabled();
    // 初始化方法集合.
    LinkedList<LifecycleElement> initMethods = new LinkedList<>();
    // 销毁方法集合.
    LinkedList<LifecycleElement> destroyMethods = new LinkedList<>();
    Class<?> targetClass = clazz;

    do {
        // 当前循环初始化方法集合.
        final LinkedList<LifecycleElement> currInitMethods = new LinkedList<>();
        // 当前循环销毁方法集合.
        final LinkedList<LifecycleElement> currDestroyMethods = new LinkedList<>();

        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            // 查找initAnnotationType类型注释的方法.
            if (initAnnotationType != null && method.isAnnotationPresent(initAnnotationType)) {
                LifecycleElement element = new LifecycleElement(method);
                currInitMethods.add(element);
                if (debug) {
                    logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
                }
            }
            // 查找destroyAnnotationType类型注释的方法.
            if (destroyAnnotationType != null && method.isAnnotationPresent(destroyAnnotationType)) {
                currDestroyMethods.add(new LifecycleElement(method));
                if (debug) {
                    logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);
                }
            }
        });
        // 合并数据.
        initMethods.addAll(0, currInitMethods);
        destroyMethods.addAll(currDestroyMethods);
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return new LifecycleMetadata(clazz, initMethods, destroyMethods);
}

  6) CommonAnnotationBeanPostProcessor.CommonAnnotationBeanPostProcessor()方法。

  ① 设置@PostConstruct注解类型,便于后续搜索@PostConstruct注释的方法。

  ② 设置@PreDestroy注解类型,便于后续搜索@PreDestroy注释的方法。

/**
 * 创建CommonAnnotationBeanPostProcessor,
 * 初始化和销毁注解类型设置为javax.annotation.PostConstruct和javax.annotation.PreDestroy.
 */
public CommonAnnotationBeanPostProcessor() {
    // 设置序号.
    setOrder(Ordered.LOWEST_PRECEDENCE - 3);
    // 设置@PostConstruct注解类型.
    setInitAnnotationType(PostConstruct.class);
    // 设置@PreDestroy注解类型.
    setDestroyAnnotationType(PreDestroy.class);
    ignoreResourceType("javax.xml.ws.WebServiceContext");
}

  InitDestroyAnnotationBeanPostProcessor.setInitAnnotationType(...)InitDestroyAnnotationBeanPostProcessor.setDestroyAnnotationType(...)方法。

  ① setInitAnnotationType(...)指定要检查的初始化注解,指示Bean配置后要调用的初始化方法。由于没有必需的注解属性,可以使用任何自定义注解。一般情况下,使用JSR-250规范提供的javax.annotation.PostConstruct

  ② setDestroyAnnotationType指定要检查的销毁注解,指示上下文关闭时要调用的销毁方法。由于没有必需的注解属性,可以使用任何自定义注解。一般情况下,使用JSR-250规范提供的javax.annotation.PreDestroy

/**
 * 指定要检查的初始化注解,指示Bean配置后要调用的初始化方法.
 * 可以使用任何自定义注解,因为没有必需的注解属性.
 * 一般情况下,使用JSR-250规范提供的javax.annotation.PostConstruct.
 */
public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {
    this.initAnnotationType = initAnnotationType;
}

/**
	 * 指定要检查的销毁注解,指示上下文关闭时要调用的销毁方法.
	 * 可以使用任何自定义注解,因为没有必需的注解属性.
	 * 一般情况下,使用JSR-250规范提供的javax.annotation.PreDestroy.
	 */
public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {
    this.destroyAnnotationType = destroyAnnotationType;
}

  总结

  查看源码可以深入了解其实现逻辑,避免应用过程中出现差异。

  源码解析基于spring-framework-5.0.5.RELEASE版本源码。

  若文中存在错误和不足,欢迎指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值