zoukankan      html  css  js  c++  java
  • BeanPostProcessor详解

    转自: https://www.jianshu.com/p/d26e8ec9c077?

    BeanPostProcessor也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创建过程中(具体为Bean初始化前后)会回调BeanPostProcessor中定义的两个方法。BeanPostProcessor的源码如下

    public interface BeanPostProcessor {
    
    
        Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    
        
        Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
    
    }
    

    其中postProcessBeforeInitialization方法会在每一个bean对象的初始化方法调用之前回调;postProcessAfterInitialization方法会在每个bean对象的初始化方法调用之后被回调。具体执行时期可以参考Spring中Bean的生命周期源码探究

    自定义BeanPostProcessor

    查看BeanPostProcessor源码,可以看到它两个方法的参数都相同,其中第一个参数Object bean表示当前正在初始化的bean对象。此外两个方法都返回Object类型的实例,返回值既可以是将入参Object bean原封不动的返回出去,也可以对当前bean进行包装再返回。来看看下面的自定义BeanPostProcessor

    /**
     * 后置处理器:初始化前后进行处理工作
     * 需要将后置处理器加入到容器中
     */
    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor {
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("postProcessBeforeInitialization..."+beanName+"..."+bean);
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("postProcessAfterInitialization..."+beanName+"..."+bean);
            return bean;
        }
    
    }
    

    Spring容器中加入MyBeanPostProcessor之后,针对容器中每个创建的Bean对象(Spring自身创建的Bean和应用程序创建的Bean),都会回调postProcessBeforeInitializationpostProcessAfterInitialization方法。

    执行原理

    BeanPostProcessor的执行是定义在容器的刷新过程中,容器刷新对象具体的方法为:AbstractApplicationContext.refresh()
    在refresh方法执行的调用栈中会去调用AbstractAutowireCapableBeanFactory.doCreateBean()方法,该方法节选源码如下

    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
        
        invokeInitMethods(beanName, wrappedBean, mbd);
    
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }
    

    看到在调用初始化方法前后会分别调用applyBeanPostProcessorsBeforeInitialization()applyBeanPostProcessorsAfterInitialization()applyBeanPostProcessorsBeforeInitialization()方法的源码如下

    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {
    
        Object result = existingBean;
        //获取所有的BeanPostProcessor进行遍历
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessBeforeInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }
    

    可以看到其逻辑为遍历得到容器中所有的BeanPostProcessor,然后一次执行postProcessBeforeInitialization,一但返回null,就跳出for循环不执行后面的BeanPostProcessor.postProcessorsBeforeInitialization()。也就是说如果返回的是null那么我们通过getBean方法将得不到目标Bean。
    applyBeanPostProcessorsBeforeInitialization()方法的逻辑和上面一致,就是将循环执行的beanProcessor.postProcessBeforeInitialization()替换成beanProcessor.postProcessAfterInitialization()
    Spring底层的很多功能特性都是借助BeanPostProcessor的子类来实现。

    常见BeanPostProcessor分析

    下图是debug过程中,ApplicationContext对象中的包含的BeanPostProcessor。具体包含哪些BeanPostProcessor和具体应用程序相关,除了下标3中的MyBeanPostProcessor为自定义的BeanPostProcessor,其余均为Spring自带的BeanPostProcessor。

     


    下面来分析一下ApplicationContextAwareProcessorAutowiredAnnotationProcessor的执行原理。

    ApplicationContextAwareProcessor

    ApplicationContextAwareProcessor后置处理器的作用是,当应用程序定义的Bean实现ApplicationContextAware接口时注入ApplicationContext对象。

    @Component
    public class Car implements ApplicationContextAware {
    
        private ApplicationContext applicationContext;
    
        public Car(){
            System.out.println("car instance...");
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            System.out.println("ApplicationContextAware...setApplicationContext()");
            this.applicationContext = applicationContext;
        }
    }
    

    那Car是如何通过实现ApplicationContextAware接口就能获得ApplicationContext对象呢?答案是通过ApplicationContextAwareProcessor后置处理器来实现,我们来看看ApplicationContextAwareProcessor的源码

    class ApplicationContextAwareProcessor implements BeanPostProcessor {
    
        private final ConfigurableApplicationContext applicationContext;
    
        private final StringValueResolver embeddedValueResolver;
    
    
        /**
         * Create a new ApplicationContextAwareProcessor for the given context.
         */
        public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
            this.applicationContext = applicationContext;
            this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
        }
    
    
        @Override
        public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
            AccessControlContext acc = null;
            // 这里bean是Car,它实现了ApplicationContextAware接口
            if (System.getSecurityManager() != null &&
                    (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                            bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                            bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
                invokeAwareInterfaces(bean);
            }
    
            return bean;
        }
    
        private void invokeAwareInterfaces(Object bean) {
            if (bean instanceof Aware) {
                if (bean instanceof EnvironmentAware) {
                    ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
                }
                if (bean instanceof EmbeddedValueResolverAware) {
                    ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
                }
                if (bean instanceof ResourceLoaderAware) {
                    ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
                }
                if (bean instanceof ApplicationEventPublisherAware) {
                    ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
                }
                if (bean instanceof MessageSourceAware) {
                    ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
                }
                if (bean instanceof ApplicationContextAware) {
                    // 会执行这里回调car重写的setApplicationContext方法,然后将this.applicationContext注入给Car
                    ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
                }
            }
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) {
            return bean;
        }
    
    }
    

    InitDestroyAnnotationBeanPostProcessor

    InitDestroyAnnotationBeanPostProcessor后置处理器是用来处理自定义的初始化方法和销毁方法。Spring中提供了3种自定义初始化和销毁方法:

    1. 通过@Bean指定init-method和destroy-method属性
    2. Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑);
    3. @PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法@PreDestroy:在容器销毁bean之前通知我们进行清理工作

    InitDestroyAnnotationBeanPostProcessor的作用就是让第3种方式生效。先看看如何使用@PostConstruct@PreDestroy注解。

    @Component
    public class Car {
    
        public Car(){
            System.out.println("car instance...");
        }
    
        /**
         * 自定义的初始化方法
         */
        @PostConstruct
        public void init(){
            System.out.println("car ... init...");
        }
    
        /**
         * 自定义的销毁方法
         */
        @PreDestroy
        public void detory(){
            System.out.println("car ... detory...");
        }
    }
    

    InitDestroyAnnotationBeanPostProcessor会在Bean创建的时候通过反射的方式查找包含@PostConstruct@PreDestroy注解的方法,然后再通过反射执行方法。我们来看看InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization()的源码

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 获取bean的metadata
        LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
        try {
            // 执行@PostConstruct指定的init方法
            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;
    }
    

    metadata中已经解析出initMethods和destroyMethods,其具体内容如下。

     


    metadata.invokeInitMethods(bean, beanName);就是根据反射执行init方法。

    InstantiationAwareBeanPostProcessor

    InstantiationAwareBeanPostProcessorBeanPostProcessor的子接口。

    public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
    
        //实例化Bean之前调用
        Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
    
        //实例化Bean之后调用
        boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
    
        //设置Bean对象中的某个属性时调用
        PropertyValues postProcessPropertyValues(
                PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
    
    }
    

    这两个接口的功能基本类似,不过要注意InstantiationAwareBeanPostProcessorBeanPostProcessor的方法名区别。InstantiationAwareBeanPostProcessor中是Instantiation, 而BeanPostProcessor是Initialization。

  • 相关阅读:
    基于摸板匹配的目標跟蹤算法
    spoj 2713 Can you answer these queries IV
    zoj 3633 Alice's present
    hdu 3642 Get The Treasury
    poj 1195 Mobile phones
    poj 2760 End of Windless Days
    zoj 3540 Adding New Machine
    spoj 1716 Can you answer these queries III
    spoj 1043 Can you answer these queries I
    spoj 2916 Can you answer these queries V
  • 原文地址:https://www.cnblogs.com/qin1993/p/11684633.html
Copyright © 2011-2022 走看看