当前位置: 代码迷 >> 综合 >> Spring 注解面面通 之 @PostConstruct 深入源码解析
  详细解决方案

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

热度:25   发布时间:2024-01-17 00:59:34.0

??@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版本源码。

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

  相关解决方案