Spring 源码解析 – BeanPostProcessor 扩展接口

一、BeanPostProcessor 扩展接口

BeanPostProcessorSpring中的一个扩展接口,它可以在Spring容器实例化bean之后,在执行 bean的初始化方法前后,允许我们自定义修改新的 bean实例。比如修改 bean 的属性,将 bean 替换为动态代理等。其中 AOP 的底层创建代理实例,就是通过实现 BeanPostProcessor 来实现的。

BeanPostProcessor 包含两个方法:

public interface BeanPostProcessor {
    /**
     *  实例化及依赖注入完成后、bean 初始化方法触发之前执行
     */

    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    /**
     *  bean 初始化方法触发后执行
     */

    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

}

如果在 Bean 实例化、配置和其他初始化过程中有任何错误,由 Spring 抛出 BeansException 异常。由于 BeanPostProcessor 可以干预 Bean 实例化、配置和初始化的每个阶段,因此实现过程需要非常谨慎。

BeanPostProcessor 是怎么干预 Bean 实例化的呢?可以通过下面这个案例感受一下:

这里我们创建一个测试 bean

@Component
public class Test {
    public void test() {
        System.out.println("test...");
    }
}

下面创建一个类实现 BeanPostProcessor 接口,在后通知中使用 CGLIB 创建一个动态代理对象:

@Component
public class TestBeanPostProcessor implements BeanPostProcessor {

    /**
     * 实例化及依赖注入完成后、bean 初始化方法触发之前执行
     */

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
       return bean;
    }

    /**
     * bean 初始化方法触发后执行
     */

    public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
        Class beanClass = bean.getClass();
        if (beanClass == Test.class) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(beanClass);
            enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
                System.out.println("<目标方法之前开始执行....>");
                Object result = methodProxy.invokeSuper(o, objects);
                System.out.println("<目标方法之后开始执行....>");
                return result;
            });
            return enhancer.create();
        }
        return bean;
    }
}

下面测试下效果:

public class App {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext("com.example.demo.beanpost");
        Test hello = (Test) context.getBean("test");
        hello.test();
    }
}
Spring 源码解析 - BeanPostProcessor 扩展接口

这样是不是就感受到 BeanPostProcessor 扩展接口的强大之处了吧,可以看出它可以干预 Bean 的实例化,因此使用的话需要非常谨慎。

下面从源码角度分析下,在 Spring 中是如何使用 BeanPostProcessor 进行扩展的。

二、BeanPostProcessor 的注册

从上面的实例中可以感觉出来,我们并没有对 BeanPostProcessor 进行特殊处理,仅仅将其加入 Spring 容器中即会生效,那 Spring 是如何读取BeanPostProcessor 呢?

在本专栏的其他 Spring 源码分析的文章中,分析的入口都是基于 AbstractApplicationContext 中的 refresh() 方法,那现在也是从这里入手,主要逻辑在该方法下触发的 registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) 方法:

Spring 源码解析 - BeanPostProcessor 扩展接口

主要逻辑则在 PostProcessorRegistrationDelegate 下的 registerBeanPostProcessors 方法,源码如下:

public static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext)
 {

    // 从bean工厂中获取到所有实现了 BeanPostProcessor 接口的 beanName
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    // Register BeanPostProcessorChecker that logs an info message when
    // a bean is created during BeanPostProcessor instantiation, i.e. when
    // a bean is not eligible for getting processed by all BeanPostProcessors.
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    // 往bean工厂中添加一个BeanPostProcessor -> BeanPostProcessorChecker
    // BeanPostProcessorChecker 是一个在创建bean期间记录信息消息的 BeanPostProcessor
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    // Separate between BeanPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    // 存放实现了PriorityOrdered接口的BeanPostProcessor
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    // 存放实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
    // 存放实现了Ordered接口的BeanPostProcessor
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    // 存放普通的BeanPostProcessor
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    for (String ppName : postProcessorNames) {
        // 如果实现了PriorityOrdered接口
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 从工厂中获取对应的 Bean实例
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);

            // 如果同时实现了MergedBeanDefinitionPostProcessor接口
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        // 如果实现了Ordered接口
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        // 普通的 BeanPostProcessor
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // 排序
    sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
    // 注册实现了PriorityOrdered 接口的 BeanPostProcessor
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    // Next, register the BeanPostProcessors that implement Ordered.
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : orderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        orderedPostProcessors.add(pp);
        // 如果同时实现了MergedBeanDefinitionPostProcessor接口
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    // 排序
    sortPostProcessors(beanFactory, orderedPostProcessors);
    //  注册实现了Ordered接口的BeanPostProcessor
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    // Now, register all regular BeanPostProcessors.
    // 注册其他普通的BeanPostProcessor
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        // 如果实现了 MergedBeanDefinitionPostProcessor 接口
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    // 通过 beanFactory.addBeanPostProcessor(postProcessor) 添加 BeanPostProcessor
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // Finally, re-register all internal BeanPostProcessors.
    // 排序
    sortPostProcessors(beanFactory, internalPostProcessors);
    // 通过beanFactory.addBeanPostProcessor(postProcessor)添加BeanPostProcessor
    // 注册所有 BeanPostProcessor
    registerBeanPostProcessors(beanFactory, internalPostProcessors);

    // Re-register post-processor for detecting inner beans as ApplicationListeners,
    // moving it to the end of the processor chain (for picking up proxies etc).
    // 往bean工厂中添加一个BeanPostProcessor -> ApplicationListenerDetector
    // ApplicationListenerDetector主要是检测bean是否实现了ApplicationListener接口
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

三、BeanPostProcessor 触发点

BeanPostProcessor 与 bean 的实例化过程息息相关,因此可以从 bean 实例化的入口 AbstractAutowireCapableBeanFactory 类的 createBean 方法入手:

3.1 resolveBeforeInstantiation

首先看到 createBean 方法下触发的 resolveBeforeInstantiation 方法,主要是针对于 InstantiationAwareBeanPostProcessor 类型的 BeanPostProcessor ,并且使用是 postProcessBeforeInstantiation 和 postProcessAfterInitialization 方法,也是一种扩展通知,并且如果返回 bean 不为空则直接跳过 Spring 的实例化过程:

Spring 源码解析 - BeanPostProcessor 扩展接口

在这会尝试通过 BeanPostProcessors 获取一个对象,这个可能是代理实例也可能是其他实例:

Spring 源码解析 - BeanPostProcessor 扩展接口

Spring 源码解析 - BeanPostProcessor 扩展接口

这里判断如果有 InstantiationAwareBeanPostProcessor 类型的 BeanPostProcessor ,则尝试使用 postProcessBeforeInstantiation 方法获取一个代理实例。

3.2 getEarlyBeanReference

如果上面没有生成代理实例的话,再回到 createBean 方法中,在 doCreateBean 方法下,创建实例后,会曝光至三级缓存中:

Spring 源码解析 - BeanPostProcessor 扩展接口

在 getEarlyBeanReference 方法中,会尝试使用 SmartInstantiationAwareBeanPostProcessor 类型的 BeanPostProcessor 创建一个早期的实例,虽说 SmartInstantiationAwareBeanPostProcessor 没有直接实现 BeanPostProcessor 但其父类 InstantiationAwareBeanPostProcessor 实现了 BeanPostProcessor :

Spring 源码解析 - BeanPostProcessor 扩展接口

Spring AOP 代理对象就是在此处获取,因此三级缓存存入ObjectFactory<?>而不是具体的 bean 的意义在此。

3.3 initializeBean

上面都是对特殊类型的 BeanPostProcessor 进行触发,在 doCreateBean 的 initializeBean 中则触发了全部的BeanPostProcessor :

Spring 源码解析 - BeanPostProcessor 扩展接口

这里在 invokeInitMethods 方法前后触发了 BeanPostProcessor 的 postProcessBeforeInitialization 和 postProcessAfterInitialization

Spring 源码解析 - BeanPostProcessor 扩展接口

Spring 源码解析 - BeanPostProcessor 扩展接口

四、Spring 中的 BeanPostProcessor 常用子类

从上面的触发点源码中,可以看出有些地方是触发的特定类型的 BeanPostProcessor 子类,而这些子类又有着不同的用途。

4.1 InstantiationAwareBeanPostProcessor

Spring 源码解析 - BeanPostProcessor 扩展接口

可以在Bean生命周期实例化Bean之前和实例化Bean之后对Bean进行操作,比如在上面源码中 createBean 方法下触发的 resolveBeforeInstantiation 方法。

InstantiationAwareBeanPostProcessor 类型的子类,会在目标Bean实例化之前尝试使用该类型的实例生成一个代理对象,如果方法返回的是一个非空对象, 将会跳过后续 Spring 默认的创建流程:

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

    // 在目标Bean实例化之前执行尝试使用该类型的生成一个代理对象,如果方法返回的是一个非空对象, 将会跳过后续 Spring 默认的创建流程
    @Nullable
    default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }

    // 在目标Bean实例化之后、属性填充前执行,如果方法返回false,将会跳过后续的属性填充过程,通常情况下返回true
    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

    // 允许对填充前的属性进行处理,比如对属性进行验证
    @Nullable
    default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
            throws BeansException {

        return null;
    }

    // 对属性值进行修改,通过基于原始的PropertyValues创建一个新的MutablePropertyValues实例,添加或删除特定的值
    // 已标记过期,官方推荐使用 postProcessProperties()方法
    @Deprecated
    @Nullable
    default PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
 throws BeansException {
        return pvs;
    }
}

4.2 SmartInstantiationAwareBeanPostProcessor

Spring 源码解析 - BeanPostProcessor 扩展接口

SmartInstantiationAwareBeanPostProcessor 也是一个接口继承了上面的 InstantiationAwareBeanPostProcessor 因此拥有 InstantiationAwareBeanPostProcessor 的特征,在此之外又提供了获取早期实例的方法。

在 Spring 的三级缓存中则会尝试使用 getEarlyBeanReference 获取一个早期实例。

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {

    //在 Bean 实例化前预测最终返回的 Class 类型,触发时机是在InstantiationAwareBeanPostProcessor的 postProcessBeforeInstantiation()之前
    @Nullable
    default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }

    //决定使用哪个构造器构造Bean,如果不指定,默认为null,即bean的无参构造方法;
    @Nullable
    default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
            throws BeansException {

        return null;
    }

    //获得提前暴露的bean引用,主要用于 Spring 循环依赖问题的解决
    default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        return bean;
    }

}

4.3 ApplicationContextAwareProcessor

Spring 源码解析 - BeanPostProcessor 扩展接口

应用上下文感知Bean后置处理器,在postProcessBeforeInitialization方法中通过invokeAwareInterfaces方法给目标 Bean 注入指定的属性值:

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
    @Nullable
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
                bean instanceof ApplicationStartupAware)) {
            return bean;
        }

        AccessControlContext acc = null;

        if (System.getSecurityManager() != null) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareInterfaces(bean);
                return null;
            }, acc);
        }
        else {
            invokeAwareInterfaces(bean);
        }

        return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
        // 给bean设置Environment属性
        if (bean instanceof EnvironmentAware) {
            ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
        }
        // 给bean设置EmbeddedValueResolver属性
        if (bean instanceof EmbeddedValueResolverAware) {
            ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
        }
        // 给bean设置ResourceLoader属性
        if (bean instanceof ResourceLoaderAware) {
            ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
        }
        // 给bean设置ApplicationEventPublisher属性
        if (bean instanceof ApplicationEventPublisherAware) {
            ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
        }
        // 给bean设置MessageSource属性
        if (bean instanceof MessageSourceAware) {
            ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
        }
        // 给bean设置 ApplicationStartupAware属性
        if (bean instanceof ApplicationStartupAware) {
            ((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
        }
        // 给bean设置ApplicationContext属性
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
        }
    }

}

4.4 ApplicationListenerDetector

Spring 源码解析 - BeanPostProcessor 扩展接口

判断目标 Bean 是否实现 ApplicationListener ,如果有则注册事件:

class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {

    private static final Log logger = LogFactory.getLog(ApplicationListenerDetector.class);

    private final transient AbstractApplicationContext applicationContext;

    private final transient Map<String, Boolean> singletonNames = new ConcurrentHashMap<>(256);


    public ApplicationListenerDetector(AbstractApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }


    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        if (ApplicationListener.class.isAssignableFrom(beanType)) {
            this.singletonNames.put(beanName, beanDefinition.isSingleton());
        }
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if (bean instanceof ApplicationListener) {
            // potentially not detected as a listener by getBeanNamesForType retrieval
            Boolean flag = this.singletonNames.get(beanName);
            if (Boolean.TRUE.equals(flag)) {
                // 添加事件
                this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
            }
            else if (Boolean.FALSE.equals(flag)) {
                if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
                    // inner bean with other scope - can't reliably process events
                    logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
                            "but is not reachable for event multicasting by its containing ApplicationContext " +
                            "because it does not have singleton scope. Only top-level listener beans are allowed " +
                            "to be of non-singleton scope.");
                }
                this.singletonNames.remove(beanName);
            }
        }
        return bean;
    }

    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) {
        if (bean instanceof ApplicationListener) {
            try {
                ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster();
                multicaster.removeApplicationListener((ApplicationListener<?>) bean);
                multicaster.removeApplicationListenerBean(beanName);
            }
            catch (IllegalStateException ex) {
                // ApplicationEventMulticaster not initialized yet - no need to remove a listener
            }
        }
    }

    @Override
    public boolean requiresDestruction(Object bean) {
        return (bean instanceof ApplicationListener);
    }


    @Override
    public boolean equals(@Nullable Object other) {
        return (this == other || (other instanceof ApplicationListenerDetector &&
                this.applicationContext == ((ApplicationListenerDetector) other).applicationContext));
    }

    @Override
    public int hashCode() {
        return ObjectUtils.nullSafeHashCode(this.applicationContext);
    }

}


原文始发于微信公众号(狂热Java小毕超):Spring 源码解析 – BeanPostProcessor 扩展接口

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/241043.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!