本文主要研究一下InitDestroyAnnotationBeanPostProcessor

DestructionAwareBeanPostProcessor

spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java

public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {

    /**
     * Apply this BeanPostProcessor to the given bean instance before its
     * destruction, e.g. invoking custom destruction callbacks.
     * <p>Like DisposableBean's {@code destroy} and a custom destroy method, this
     * callback will only apply to beans which the container fully manages the
     * lifecycle for. This is usually the case for singletons and scoped beans.
     * @param bean the bean instance to be destroyed
     * @param beanName the name of the bean
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.DisposableBean#destroy()
     * @see org.springframework.beans.factory.support.AbstractBeanDefinition#setDestroyMethodName(String)
     */
    void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;

    /**
     * Determine whether the given bean instance requires destruction by this
     * post-processor.
     * <p>The default implementation returns {@code true}. If a pre-5 implementation
     * of {@code DestructionAwareBeanPostProcessor} does not provide a concrete
     * implementation of this method, Spring silently assumes {@code true} as well.
     * @param bean the bean instance to check
     * @return {@code true} if {@link #postProcessBeforeDestruction} is supposed to
     * be called for this bean instance eventually, or {@code false} if not needed
     * @since 4.3
     */
    default boolean requiresDestruction(Object bean) {
        return true;
    }

}
DestructionAwareBeanPostProcessor继承了BeanPostProcessor方法,它定义了postProcessBeforeDestruction、requiresDestruction两个方法

InitDestroyAnnotationBeanPostProcessor

spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java

public class InitDestroyAnnotationBeanPostProcessor
        implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable {

    @Nullable
    private Class<? extends Annotation> initAnnotationType;

    @Nullable
    private Class<? extends Annotation> destroyAnnotationType;

    private int order = Ordered.LOWEST_PRECEDENCE;    

    @Override
    public int getOrder() {
        return this.order;
    }


    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        LifecycleMetadata metadata = findLifecycleMetadata(beanType);
        metadata.checkConfigMembers(beanDefinition);
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        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;
    }

    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
        try {
            metadata.invokeDestroyMethods(bean, beanName);
        }
        catch (InvocationTargetException ex) {
            String msg = "Destroy method on bean with name '" + beanName + "' threw an exception";
            if (logger.isDebugEnabled()) {
                logger.warn(msg, ex.getTargetException());
            }
            else {
                logger.warn(msg + ": " + ex.getTargetException());
            }
        }
        catch (Throwable ex) {
            logger.warn("Failed to invoke destroy method on bean with name '" + beanName + "'", ex);
        }
    }

    @Override
    public boolean requiresDestruction(Object bean) {
        return findLifecycleMetadata(bean.getClass()).hasDestroyMethods();
    }


    private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
        if (this.lifecycleMetadataCache == null) {
            // Happens after deserialization, during destruction...
            return buildLifecycleMetadata(clazz);
        }
        // Quick check on the concurrent map first, with minimal locking.
        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;
    }    
}        
InitDestroyAnnotationBeanPostProcessor实现了BeanPostProcessor接口定义的postProcessBeforeInitialization方法,DestructionAwareBeanPostProcessor接口的postProcessBeforeInitialization、requiresDestruction方法;其中postProcessBeforeInitialization方法先通过findLifecycleMetadata找到LifecycleMetadata,然后执行invokeInitMethods方法;postProcessBeforeDestruction方法也是先通过findLifecycleMetadata找到LifecycleMetadata,然后执行invokeDestroyMethods方法

LifecycleMetadata

    private class LifecycleMetadata {

        private final Class<?> targetClass;

        private final Collection<LifecycleElement> initMethods;

        private final Collection<LifecycleElement> destroyMethods;

        @Nullable
        private volatile Set<LifecycleElement> checkedInitMethods;

        @Nullable
        private volatile Set<LifecycleElement> checkedDestroyMethods;

        public LifecycleMetadata(Class<?> targetClass, Collection<LifecycleElement> initMethods,
                Collection<LifecycleElement> destroyMethods) {

            this.targetClass = targetClass;
            this.initMethods = initMethods;
            this.destroyMethods = destroyMethods;
        }

        public void checkConfigMembers(RootBeanDefinition beanDefinition) {
            Set<LifecycleElement> checkedInitMethods = new LinkedHashSet<>(this.initMethods.size());
            for (LifecycleElement element : this.initMethods) {
                String methodIdentifier = element.getIdentifier();
                if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier)) {
                    beanDefinition.registerExternallyManagedInitMethod(methodIdentifier);
                    checkedInitMethods.add(element);
                    if (logger.isTraceEnabled()) {
                        logger.trace("Registered init method on class [" + this.targetClass.getName() + "]: " + element);
                    }
                }
            }
            Set<LifecycleElement> checkedDestroyMethods = new LinkedHashSet<>(this.destroyMethods.size());
            for (LifecycleElement element : this.destroyMethods) {
                String methodIdentifier = element.getIdentifier();
                if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {
                    beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier);
                    checkedDestroyMethods.add(element);
                    if (logger.isTraceEnabled()) {
                        logger.trace("Registered destroy method on class [" + this.targetClass.getName() + "]: " + element);
                    }
                }
            }
            this.checkedInitMethods = checkedInitMethods;
            this.checkedDestroyMethods = checkedDestroyMethods;
        }

        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()) {
                for (LifecycleElement element : initMethodsToIterate) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
                    }
                    element.invoke(target);
                }
            }
        }

        public void invokeDestroyMethods(Object target, String beanName) throws Throwable {
            Collection<LifecycleElement> checkedDestroyMethods = this.checkedDestroyMethods;
            Collection<LifecycleElement> destroyMethodsToUse =
                    (checkedDestroyMethods != null ? checkedDestroyMethods : this.destroyMethods);
            if (!destroyMethodsToUse.isEmpty()) {
                for (LifecycleElement element : destroyMethodsToUse) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Invoking destroy method on bean '" + beanName + "': " + element.getMethod());
                    }
                    element.invoke(target);
                }
            }
        }

        public boolean hasDestroyMethods() {
            Collection<LifecycleElement> checkedDestroyMethods = this.checkedDestroyMethods;
            Collection<LifecycleElement> destroyMethodsToUse =
                    (checkedDestroyMethods != null ? checkedDestroyMethods : this.destroyMethods);
            return !destroyMethodsToUse.isEmpty();
        }
    }
LifecycleMetadata的invokeInitMethods遍历checkedInitMethods通过反射执行init方法,invokeDestroyMethods则是遍历checkedDestroyMethods通过反射执行destroy方法

CommonAnnotationBeanPostProcessor

spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java

public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor
        implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {

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

    //......
}        
CommonAnnotationBeanPostProcessor继承了InitDestroyAnnotationBeanPostProcessor,其构造器设置了initAnnotationType为PostConstruct.class,设置destroyAnnotationType为PreDestroy.class

小结

InitDestroyAnnotationBeanPostProcessor实现了BeanPostProcessor接口定义的postProcessBeforeInitialization方法,DestructionAwareBeanPostProcessor接口的postProcessBeforeInitialization、requiresDestruction方法;其中postProcessBeforeInitialization方法先通过findLifecycleMetadata找到LifecycleMetadata,然后执行invokeInitMethods方法;postProcessBeforeDestruction方法也是先通过findLifecycleMetadata找到LifecycleMetadata,然后执行invokeDestroyMethods方法。


codecraft
11.9k 声望2k 粉丝

当一个代码的工匠回首往事时,不因虚度年华而悔恨,也不因碌碌无为而羞愧,这样,当他老的时候,可以很自豪告诉世人,我曾经将代码注入生命去打造互联网的浪潮之巅,那是个很疯狂的时代,我在一波波的浪潮上留下...