美文网首页
聊聊InitDestroyAnnotationBeanPostP

聊聊InitDestroyAnnotationBeanPostP

作者: go4it | 来源:发表于2023-10-18 09:26 被阅读0次

    本文主要研究一下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方法。

    相关文章

      网友评论

          本文标题:聊聊InitDestroyAnnotationBeanPostP

          本文链接:https://www.haomeiwen.com/subject/cazqidtx.html