实现自定义扩展点_Spring必须掌握的Bean增强扩展点与加载流程

本文详细介绍了Spring Bean的扩展点,包括BeanDefinition与BeanFactory扩展、生命周期、Bean实例化中的扩展,如BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor、InstantiationAwareBeanPostProcessor、BeanPostProcessor等。此外,还讨论了其他扩展点如InitializingBean接口、Aware接口及其在Spring容器中的应用和注入时机。
摘要由CSDN通过智能技术生成

Spring Bean扩展点

BeanDefinition与BeanFactory扩展

009457fd20462fb1816721f1aa5b4368.png

生命周期

在整个SpringBean生命周期体系中,可以在BeanFactory中可以看到Spring本身对整个体系的约定:

Bean factory implementations should support the standard bean lifecycle interfacesas far as possible. The full set of initialization methods and their standard order is:BeanNameAware's {@code setBeanName}BeanClassLoaderAware's {@code setBeanClassLoader}BeanFactoryAware's {@code setBeanFactory}EnvironmentAware's {@code setEnvironment}EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}ResourceLoaderAware's {@code setResourceLoader}(only applicable when running in an application context)ApplicationEventPublisherAware's {@code setApplicationEventPublisher}(only applicable when running in an application context)MessageSourceAware's {@code setMessageSource}(only applicable when running in an application context)ApplicationContextAware's {@code setApplicationContext}(only applicable when running in an application context)ServletContextAware's {@code setServletContext}(only applicable when running in a web application context){@code postProcessBeforeInitialization} methods of BeanPostProcessorsInitializingBean's {@code afterPropertiesSet}a custom init-method definition{@code postProcessAfterInitialization} methods of BeanPostProcessors

Bean定义时扩展

BeanDefinitionRegistryPostProcessor

/** * 标准的BeanFactoryPostProcessor SPI扩展 * 允许在普通的BeanFactoryPostProcessor检测之前注册更多的BeanDefinition。 * 特别的是,BeanDefinitionRegistryPostProcessor可以注册BeanFactoryPostProcessor。 */public interface BeanDefinitionRegistryPostProcessor     extends BeanFactoryPostProcessor {        /**     * 可以对在应用上下文中的内部BeanDeinitionRegistry实例化之后进行修改。     * 特别强调!!     * 此时,BeanDefinitionRegistry中所有的普通BeanDefinition都已经加载了,但是未实例化。     * 这个方法允许在后处理阶段之前向BeanDefinitionRegistry添加BeanDefinition。     *(也可以增强,删除和修改Bean定义)     * 注意:此时,与BeanFactoryPostProcessor一样,此时只是Bean定义,不要在此时     * 真正的对Bean进行实例化,否则会导致Bean过早实例化导致难以预期的问题。     */    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)         throws BeansException;}

类图

29a53e5e314f736b09e929fa039b0858.png

接口应用

Spring本身的org.springframework.context.annotation.ConfigurationClassPostProcessor

f48bb05874649dac50937205fa870f1a.png
2537cf5fe64aae0cbcc6e58f0b984aa6.png

用来将注解@Configuration中的相关生成bean的方法所对应的BeanDefinition进行注册。

Mybatis的org.mybatis.spring.mapper.MapperScannerConfigurer实现。

8c68158407f46820ad256ad055004b85.png
d17c0740006aa02e59d2aa2ca68539fa.png

在只有接口没有实现类的情况下找到接口方法与sql之间的联系从而生成BeanDefinition并注册。

BeanFactoryPostProcessor

在BeanFactory生成之后,通过该接口自定义修改应用程序上下文的BeanDefinition,调整上下文的BeanFactory的bean属性值

/** * 允许对应用上下文中的BeanDefinition自定义的修改,调整基础BeanFactory中的Bean属性值。 *  * 应用上下文可以自动发现在BeanDefinitions中的BeanFactoryPostProcessor,并在任意一个 * Bean创建之前进行处理。 *  * 对于系统管理人员自定义配置文件将应用上下文中的Bean特定属性配置进行覆盖非常有作用。 * 祥见PropertyResourceConfigurer及其具体实现,了解这种开箱即用的解决方案。 * * BeanFactoryPostProcessor应该是对BeanDefinition的修改,而不能对Bean进行实例化。 * 在此阶段进行Bean实例化,会导致Bean的过早实例化,违反容器的执行顺序,导致意想不到的后果。 * 如果需要已经实例化的Bean,考虑使用BeanPostProcessor实现代替。 */public interface BeanFactoryPostProcessor {    /**     * 可以修改上下文中的BeanFactory实例对象。所有的BeanDefinition在此时已经全部加载完成,     * 但是还没有进行实例化时,对一些急切实例化的Bean进行重写或者添加属性。     */    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)         throws BeansException;}

接口应用

Spring的org.springframework.context.support.PropertySourcesPlaceholderConfigurer

0871e29d67d0da3de3bd7e7b90720749.png

解析在BeanDefinition的属性值中存在的${...}点位符,和@Value注解的依赖数据,将从Spring的PropertySource设置到当前Enviroment中的对应属性值注入。

Bean实例化中的扩展

Bean实例化分为二个阶段:

  • 实例化:实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中
  • 初始化:初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性

InstantiationAwareBeanPostProcessor

用来实例化时的前后增强器

Instantiation 表示实例化,对象还未生成 Initialization 表示初始化,对象已经生成

BeanPostProcessor的子类,但是与子类不同的点在于,子类的调用时间是在初始化完成之后的增强,而hasInstantiationAwareBeanPostProcessors是在初始化时的增强。

/** * BeanPostProcessor的子接口,用来在实例化之前与实例化之后但未设置相应依赖性或者自动装配之前。 * * 通常用来控制特别目标类的默认实例化。 * 比如,创建特殊的TargetSources代理(连接池,懒加载初始化类等),或者实现注入对象的字段注入。 * * 注意: 这是一个特殊用途的接口,主要是框架的内部接口使用。推荐尽可能的使用BeanPostProcessor接口, * 或者使用InstantiationAwareBeanPostProcessorAdapter的派生类来实现,从而屏蔽一些子类不感兴趣 * 的方法实现细节。 */public interface InstantiationAwareBeanPostProcessor     extends BeanPostProcessor {/** * 在目标类(Bean)实例化之前调用,该方法响应对象应该是目标类(Bean)的代理对象, * 以控制目标类的(Bean)的实例化时机。 * * 如果该方法响应一个非空对象,会中断Bean的创建过程。 * 唯一仍然会被调用的只有BeanPostProcessor#postProcessAfterInitialization。 *(可参考AbstractAutowireCapableBeanFactory#createBean下相关代码)。 *  * 该回调应用于带有Bean定义的Class,同样的,也作用于工厂方法中定义的Bean。 * * 后置增强处理器应该继承SmartInstantiationAwareBeanPostProcessor实现, * 以便于通过提供类型响应方法来预测响应类型。 */@Nullabledefault Object postProcessBeforeInstantiation(Class> beanClass, String beanName)         throws BeansException {return null;}/** * 在Bean实例化(通过构造函数或者工厂方法)完成之后, * 但在属性填充(如properties或AutoWire)之前调用 * * 这是在Spring执行Autowired之前对Bean进行定义字段注入的最理想的时机 *  * 通过响应true或者false控制是否继续或者跳过后续的Bean属性填充 * 正常情况下应该返回为true,如果返回false同时会也阻止调用 * 后续的InstantiationAwareBeanPostProcessor实例 */default boolean postProcessAfterInstantiation(Object bean, String beanName)         throws BeansException {return true;}/** * 在Bean处理需要注意依赖的属性值之前会调用该方法处理即将注入的属性值 * 在这里可以对即将注入Bean的属性值进行动态的调整 */@Nullabledefault PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)throws BeansException {return null;}}

接口应用

这个接口spring不建议用户直接实现,如果必须在这些扩展点应用自己的回调函数,spring建议继承InstantiationAwareBeanPostProcessorAdapter,重写相应的方法即可。

org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator,基于beanName创建代理,就是应用了这个接口,在生成bean前生成代理bean,从而替代默认的实例化。

374469ca7a3dc493b61ba06acfa79c0a.png
06e598a65375ad6f58e2b267ed2ef4c3.png

BeanPostProcessor

特别注意:Spring的Bean初始化前的根据是特指的对应对象的初始化方法,

比如,继承了InitializingBean接口,调用afterPropertiesSet方法,或配置的initMethod。而不是指Java中的类的初始化根据。

该接口的时机是在Bean已经实例化完成,并且已经填充好了对应的依赖属性!!

1b242a556b2d75aee2b8c09fdbb2972a.png
/** * 允许自定义修改一个新的Bean实例。比如:检查接口标记或者代理包裹Bean对象。 * * 通常,通过#postProcessBeforeInitialization(根据接口标记,如@AutoWired)填充Bean * 通过#postProcessAfterInitialization对Bean对象进行代理。 * * 注册: * 应用上下文(ApplicationContext)可以从Bean定义中自动检查BeanPostProcessor,并且在随后的 * 任意Bean创建之后调用所有的后增强处理器(BeanPostProcessor)。 * 一个普通的BeanFactory允许通过以编程的方式注册后处理器,并通过BeanFactory将其应用于所有的Bean。 * * 有序性: * BeanPostProcessor通过PriorityOrdered(优先顺序)与Ordered来进行排序。 * (注意org.springframework.core.annotation.Order注解,在这里是不生效的) * 但是要注意的是,如果通过编程的方式注册,将会忽略PriorityOrdered与Ordered, * 而是按照其注册时的顺序。 */public interface BeanPostProcessor {    /** * 在Bean实例化完成之后, * 初始化(调用InitializingBean#afterPropertiesSet或者自定义init-method初始方法)之前 * 此时,Bean的依赖属性已经填充完成了。 *  * 如果返回null,则后续的其他BeanPostProcessor则不会继续作用。 */@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName)         throws BeansException {return bean;}/** * 在Bean实例化完成之后, * 初始化(调用InitializingBean#afterPropertiesSet或者自定义init-method初始方法)之后 * 此时,Bean的依赖属性已经填充完成了。 * 通常情况下,该方法返回的对象是Bean的代理对象。     *     * 如果返回null,则后续的其他BeanPostProcessor则不会继续作用。 */@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName)         throws BeansException {return bean;}}

接口应用

Spring中的org.springframework.context.support.ApplicationContextAwareProcessor

在bean初始化回调之前,注入应用上下文的

15121346d39853b25b3700c0c23a386f.png
cde5c32491a7d8a84f0b65a5f0c1f16d.png

其他扩展点

InitializingBean接口

在执行完BeanPostProcessor的postProcessBeforeInitialization方法后,如果这个bean实现了InitializingBean接口,则会去调用afterPropertiesSet方法。

Aware

标识一个Bean可以被Spring容器通过回调方法将一个框架中的特定Bean注入的超级接口。

当Spring容器创建的Bean对象在进行具体操作的时候,如果需要容器的其他对象来满足需要,此时可以实现需要对象的Aware接口。

如果某个对象实现了某个Aware接口,比如需要依赖Spring的上下文容器(ApplicationContext),则可以实现ApplicationContextAware接口。

Spring在Bean进行初始化(注意与实例化的区别)之前,会将依赖的ApplicationContext对象通过调用ApplicationContextAware#setApplicationContext注入。

Spring提供内置了以下Aware:

  • BeanNameAware :Bean在BeanFactory中的名称
  • BeanClassLoaderAware :Bean的ClassLoader
  • BeanFactoryAware :Bean所在的BeanFactory
  • EnvironmentAware :Bean运行时的依赖Enviroment
  • EmbeddedValueResolverAware :Spring EL解析,解析如#{xxx}表达式。
  • ResourceLoaderAware :加载Bean的ResourceLoader
  • ApplicationEventPublisherAware :应用事件发布者
  • MessageSourceAware :国际化的
  • ApplicationContextAware : 应用上下文容
  • ServletContextAware :Servlet上下文

BeanDefinition

c352121bf854503fb9dbb9e271f19755.png

BeanDefinition是将开发人员对Bean的属性定义解释成一个对象的实例。

比如在xml配置中:

在定义bean时,可以指定构造函数,设置属性,还可以设置init-method和destroy-method。

构造函数不用说,设置属性是在InstantiationAwareBeanPostProcessor#PostProcessPropertyValues方法后执行的,init-method是在InitializingBean的afterPropertiesSet方法后执行的,而destroy-method是在容器关闭是被调用的。

扩展点在spring中的注入

这些扩展点什么时候被调用或被添加到BeanFactory中等待调用呢?

容器级别

我们得从上下文的抽象类AbstractApplicationContext#refresh方法讲起

@Overridepublic void refresh() throws BeansException, IllegalStateException {    synchronized (this.startupShutdownMonitor) {        // Prepare this context for refreshing.        // 设置上下文启动时间和活跃标记,同时加载属性资源。        prepareRefresh();        // Tell the subclass to refresh the internal bean factory.        // 停掉之前启动的beanFactory如果有的话,同时新生成一个beanFactory,加载配置中的BeanDefinition。        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();        // Prepare the bean factory for use in this context.        // 给beanFactory设置类加载器,添加后置处理器`ApplicationContextAwareProcessor`等等。        prepareBeanFactory(beanFactory);        try {            // Allows post-processing of the bean factory in context subclasses.            postProcessBeanFactory(beanFactory);            // Invoke factory processors registered as beans in the context.            // BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor的调用            // 如果beanFactory是BeanDefinitionRegistry的实现类// 拿到入参所有的BeanFactoryPostProcessor接口实现类,            // 挑选出实现BeanDefinitionRegistryPostProcessor接口的实现类            // 先执行postProcessBeanDefinitionRegistry方法。 接下来调用beanFactory中实现BeanDefinitionRegistryPostProcessor接口的实现类中            // 实现PriorityOrdered接口的实现类,            // 调用这些实现类前先根据PriorityOrdered的getOrder方法进行排序,            // 然后再按顺序调用postProcessBeanDefinitionRegistry方法。 接下来再调用beanFactory中实现BeanDefinitionRegistryPostProcessor接口的实现类中            // 实现了Ordered接口的类,也是按顺序调用postProcessBeanDefinitionRegistry方法。 最后调用beanFactory中其他的实现BeanDefinitionRegistryPostProcessor接口的实现类            // 的postProcessBeanDefinitionRegistry方法。 最后的最后,先调用入参中所有实现BeanDefinitionRegistryPostProcessor接口的实现类            // 的postProcessBeanFactory方法,            // 再调用入参中实现了BeanFactoryPostProcessor接口的实现类            // 的postProcessBeanFactory方法。 如果不是则只把入参中的BeanFactoryPostProcessor实现类全部调用一遍。 上边都做完了,接着从beanFactory中获取实现了BeanFactoryPostProcessor接口的bean            //(没有被执行过),也是分为三类,PriorityOrdered组优先调用,Ordered其次,其他垫底。 // 最终清除beanFactory的metaData缓存(主要是清除类与beanname的映射缓存            invokeBeanFactoryPostProcessors(beanFactory);            // Register bean processors that intercept bean creation.            // BeanPostProcessor接口实现类的注册            // 先添加BeanPostProcessorChecker。// 然后把beanFactory中实现BeanPostProcessor接口的实现类分成四个部分            // 分别添加到beanFactory。// PriorityOrdered部分,实现了PriorityOrdered接口            // 且并不属于MergedBeanDefinitionPostProcessor的// Ordered部分,实现了Ordered接口且并不属于MergedBeanDefinitionPostProcessor的// 其他的不属于MergedBeanDefinitionPostProcessor的// 属于MergedBeanDefinitionPostProcessor的// 其中PriorityOrdered和Ordered部分先排序,然后按上边的顺序            // 分别加入到beanFactory的beanPostProcessors属性中            registerBeanPostProcessors(beanFactory);            // Initialize message source for this context.            initMessageSource();            // Initialize event multicaster for this context.            initApplicationEventMulticaster();            // Initialize other special beans in specific context subclasses.            onRefresh();            // Check for listener beans and register them.            registerListeners();            // Instantiate all remaining (non-lazy-init) singletons.            finishBeanFactoryInitialization(beanFactory);            // Last step: publish corresponding event.            finishRefresh();        }        catch (BeansException ex) {            if (logger.isWarnEnabled()) {                logger.warn("Exception encountered during context initialization - " +                        "cancelling refresh attempt: " + ex);            }            // Destroy already created singletons to avoid dangling resources.            destroyBeans();            // Reset 'active' flag.            cancelRefresh(ex);            // Propagate exception to caller.            throw ex;        }        finally {            // Reset common introspection caches in Spring's core, since we            // might not ever need metadata for singleton beans anymore...            resetCommonCaches();        }    }}

bean级别

其余的bean上的接口属性之类的,都是在bean的生成中逐个调用的。

小结

9fd343dd994921d1bb739b12d0b58a00.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值