【小家Spring】Spring注解驱动开发---Spring Ioc容器中Bean的生命周期详解(BeanPostProcessor解析)(下)

简介: 【小家Spring】Spring注解驱动开发---Spring Ioc容器中Bean的生命周期详解(BeanPostProcessor解析)(下)

五个接口十个扩展点


1、BeanPostProcessor Bean后置处理器(和初始化相关)


  1. postProcessBeforeInitialization:实例化、依赖注入完毕。在调用**显示的初始化之前(init-method、InitializingBean等之前)**完成一些定制的初始化任务。如:

            1. BeanValidationPostProcessor完成JSR-303 @Valid注解Bean验证

            2. InitDestroyAnnotationBeanPostProcessor:完成@PostConstruct注解的初始化方法调用(所以它是在init显示调用之前执行的)

            3. ApplicationContextAwareProcessor完成一些Aware接口的注入(如EnvironmentAware、ResourceLoaderAware、ApplicationContextAware)


  2.postProcessAfterInitialization: 整个初始化都完全完毕了。做一些事情,如

            1. AspectJAwareAdvisorAutoProxyCreator:完成xml风格的AOP配置(aop:config)的目标对象包装到AOP代理对象

            2. AnnotationAwareAspectJAutoProxyCreator:完成@Aspectj注解风格(aop:aspectj-autoproxy @Aspect)的AOP配置的目标对象包装到AOP代理对象


2、MergedBeanDefinitionPostProcessor 合并Bean定义(继承BeanPostProcessor)


1.postProcessMergedBeanDefinition:执行Bean定义的合并


3、InstantiationAwareBeanPostProcessor 实例化Bean(继承BeanPostProcessor)


        1.postProcessBeforeInstantiation:实例化之前执行。给调用者一个机会,返回一个代理对象(相当于可以摆脱Spring的束缚,可以自定义实例化逻辑) 若返回null,继续后续Spring的逻辑。若返回不为null,就最后面都仅仅只执行 BeanPostProcessor #postProcessAfterInitialization这一个回调方法了。如:

            1. 当AbstractAutoProxyCreator的实现者注册了TargetSourceCreator(创建自定义的TargetSource)将会按照这个流程去执行。绝大多数情况下调用者不会自己去实现TargetSourceCreator,而是Spring采用默认的SingletonTargetSource去生产AOP对象。 当然除了SingletonTargetSource,我们还可以使用ThreadLocalTargetSource(线程绑定的Bean)、CommonsPoolTargetSource(实例池的Bean)等等


  1. postProcessAfterInitialization:实例化完毕后、初始化之前执行。 若方法返回false,表示后续的InstantiationAwareBeanPostProcessor都不用再执行了。(一般不建议去返回false,它的意义在于若返回fasle不仅后续的不执行了,就连自己个的且包括后续的处理器的postProcessPropertyValues方法都将不会再执行了) populateBean()的时候调用,若有返回false,下面的postProcessPropertyValues就都不会调用了


     3.postProcessPropertyValues:紧接着上面postProcessAfterInitialization执行的(false解释如上)。如:

            1. AutowiredAnnotationBeanPostProcessor执行@Autowired注解注入

            2. CommonAnnotationBeanPostProcessor执行@Resource等注解的注入,

            3. PersistenceAnnotationBeanPostProcessor执行@ PersistenceContext等JPA注解的注入,


4. RequiredAnnotationBeanPostProcessor执行@ Required注解的检查等等


4、SmartInstantiationAwareBeanPostProcessor 智能实例化Bean(继承InstantiationAwareBeanPostProcessor)


    1.predictBeanType:预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null; 当你调用BeanFactory.getType(name)时当通过Bean定义无法得到Bean类型信息时就调用该回调方法来决定类型信息。方法:getBeanNamesForType(,)会循环调用此方法~~~ 如:

            1. BeanFactory.isTypeMatch(name, targetType)用于检测给定名字的Bean是否匹配目标类型(在依赖注入时需要使用)

    2.determineCandidateConstructors:检测Bean的构造器,可以检测出多个候选构造器,再有相应的策略决定使用哪一个。 在createBeanInstance的时候,会通过此方法尝试去找到一个合适的构造函数。若返回null,可能就直接使用空构造函数去实例化了 如:1. AutowiredAnnotationBeanPostProcessor:它会扫描Bean中使用了@Autowired/@Value注解的构造器从而可以完成构造器注入

   3.getEarlyBeanReference:和循环引用相关了。当正在创建A时,A依赖B。此时会:将A作为ObjectFactory放入单例工厂中进行early expose,此处又需要引用A,但A正在创建,从单例工厂拿到ObjectFactory**(其通过getEarlyBeanReference获取及早暴露Bean)**从而允许循环依赖。

1. AspectJAwareAdvisorAutoProxyCreator或AnnotationAwareAspectJAutoProxyCreator他们都有调用此方法,通过early reference能得到正确的代理对象。 有个小细节:这两个类中若执行了getEarlyBeanReference,那postProcessAfterInitialization就不会再执行了。

因为我们经常实现SmartInstantiationAwareBeanPostProcessor或者InstantiationAwareBeanPostProcessor只想实现其中的某个方法,因此本处介绍Spring为我们提供的一个适配器:InstantiationAwareBeanPostProcessorAdapter,它做了所有的空实现。这样我们需要哪个自己去实现对应方法即可,减少了干扰


5、DestructionAwareBeanPostProcessor 销毁Bean(继承BeanPostProcessor)

    1.postProcessBeforeDestruction:销毁后处理回调方法,该回调只能应用到单例Bean。如

            1.InitDestroyAnnotationBeanPostProcessor完成@PreDestroy注解的销毁方法调用


Spring内置的一些BeanPostProcessor


Spring内置了非常非常多的处理器,这里只举例子:


ApplicationContextAwareProcessor


它的postProcessBeforeInitialization方法里处ApplicationContextAware、MessageSourceAwareResourceLoaderAware、EnvironmentAware、EmbeddedValueResolverAware、ApplicationEventPublisherAware


CommonAnnotationBeanPostProcessor


继承InitDestroyAnnotationBeanPostProcessor。


提供对JSR-250规范注解的支持@javax.annotation.Resource、@javax.annotation.PostConstruct和@javax.annotation.PreDestroy等的支持


postProcessPropertyValues:通过此回调进行@Resource注解的依赖注入;(最重要)

postProcessBeforeInitialization()将会调用bean的@PostConstruct方法;(次重要)

postProcessBeforeDestruction()将会调用单例 Bean的@PreDestroy方法


AutowiredAnnotationBeanPostProcessor


提供对JSR-330规范注解(@Inject)的支持和Spring自带注解的支持(@Autowired和@Value)


determineCandidateConstructors:决定候选构造器;

postProcessPropertyValues:进行依赖注入


AbstractAutoProxyCreator AOP中对处理器的典型应用


继承自SmartInstantiationAwareBeanPostProcessor。AspectJAwareAdvisorAutoProxyCreator(提供对<aop:config>的支持)和AnnotationAwareAspectJAutoProxyCreator(提供对@AspectJ注解的支持)都是继承AbstractAutoProxyCreator


当使用aop:config配置时自动注册AspectJAwareAdvisorAutoProxyCreator,而使用aop:aspectj-autoproxy时会自动注册AnnotationAwareAspectJAutoProxyCreator。


predictBeanType:预测Bean的类型,如果目标对象被AOP代理对象包装,此处将返回AOP代理对象的类型(而不是目标对象的类型)


postProcessBeforeInstantiation:当我们配置TargetSourceCreator进行自定义TargetSource创建时,会创建代理对象并中断默认Spring创建流程


getEarlyBeanReference:获取early Bean引用(只有单例Bean才能回调该方法) wrapIfNecessary(bean, beanName, cacheKey);

postProcessAfterInitialization:如果之前调用过getEarlyBeanReference获取包装目标对象到AOP代理对象(如果需要),则不再执行 。否则包装目标对象到AOP代理对象(如果需要) wrapIfNecessary(bean, beanName, cacheKey);


getEarlyBeanReference和postProcessAfterInitialization是二者选一的,而且单例Bean目标对象只能被增强一次,而原型Bean目标对象可能被包装多次


MethodValidationPostProcessor


基于Hibernate Validator的校验。


提供对方法参数/方法返回值的进行验证(即前置条件/后置条件的支持),通过JSR-303注解验证,使用方式如:

public @NotNull Object myValidMethod(@NotNull String arg1, @Max(10) int arg2)


默认只对@org.springframework.validation.annotation.Validated(它是jsr303注解javax.validation.Valid的变体)注解的Bean进行验证,我们可以修改validatedAnnotationType为其他注解类型来支持其他注解验证。而且目前只支持Hibernate Validator实现,在未来版本可能支持其他实现。


有了这东西之后我们就不需要在进行如Assert.assertNotNull()这种前置条件/后置条件的判断了。


ScheduledAnnotationBeanPostProcessor


当配置文件中有task:annotation-driven自动注册或@EnableScheduling自动注册。(提供对注解@Scheduled任务调度的支持)


postProcessAfterInitialization:通过查找Bean对象类上的@Scheduled注解来创建ScheduledMethodRunnable对象并注册任务调度方法(仅返回值为void且方法是无形式参数的才可以)。


AsyncAnnotationBeanPostProcessor


当配置文件中有task:annotation-driven自动注册或@EnableAsync自动注册。


提供对@ Async和EJB3.1的@javax.ejb.Asynchronous注解的异步调用支持。

postProcessAfterInitialization:通过ProxyFactory创建目标对象的代理对象,默认使用AsyncAnnotationAdvisor(内部使用AsyncExecutionInterceptor 通过AsyncTaskExecutor(继承TaskExecutor)通过submit提交异步任务)。


ServletContextAwareProcessor


在使用Web容器时自动注册。类似于ApplicationContextAwareProcessor,当你的Bean 实现了ServletContextAware/ ServletConfigAware会自动调用回调方法注入ServletContext/ ServletConfig。


BeanPostProcessor的执行顺序


如果使用BeanFactory实现,非ApplicationContext实现,BeanPostProcessor执行顺序就是添加顺序。

如果使用的是AbstractApplicationContext(实现了ApplicationContext)的实现,则通过如下规则指定顺序。PriorityOrdered > Ordered > 无实现接口的 > 内部Bean后处理器(实现了MergedBeanDefinitionPostProcessor接口的是内部Bean PostProcessor,将在最后且无序注册)


总结


Spring提供了多种方式,让我们可以参与控制Bean的生命周期,从而达到我们的业务目的。相信有了这些功能之后,我们处理起来就会更加的游刃有余了。


备注:

1、实现InitializingBean接口是直接调用afterPropertiesSet方法,而init-method是通过反射来实现,效率较低,但是init-method方式消除了对spring的依赖。

2、InitializingBean接口实现先于init-method方法,如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法(画外音:若不出错,就都会调用)。

相关文章
|
5月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
593 2
|
12月前
|
存储 Java 文件存储
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— logback.xml 配置文件解析
本文解析了 `logback.xml` 配置文件的详细内容,包括日志输出格式、存储路径、控制台输出及日志级别等关键配置。通过定义 `LOG_PATTERN` 和 `FILE_PATH`,设置日志格式与存储路径;利用 `&lt;appender&gt;` 节点配置控制台和文件输出,支持日志滚动策略(如文件大小限制和保存时长);最后通过 `&lt;logger&gt;` 和 `&lt;root&gt;` 定义日志级别与输出方式。此配置适用于精细化管理日志输出,满足不同场景需求。
2810 1
|
XML Java 开发者
Spring底层架构核心概念解析
理解 Spring 框架的核心概念对于开发和维护 Spring 应用程序至关重要。IOC 和 AOP 是其两个关键特性,通过依赖注入和面向切面编程实现了高效的模块化和松耦合设计。Spring 容器管理着 Beans 的生命周期和配置,而核心模块为各种应用场景提供了丰富的功能支持。通过全面掌握这些核心概念,开发者可以更加高效地利用 Spring 框架开发企业级应用。
406 18
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
传感器 监控 安全
智慧工地云平台的技术架构解析:微服务+Spring Cloud如何支撑海量数据?
慧工地解决方案依托AI、物联网和BIM技术,实现对施工现场的全方位、立体化管理。通过规范施工、减少安全隐患、节省人力、降低运营成本,提升工地管理的安全性、效率和精益度。该方案适用于大型建筑、基础设施、房地产开发等场景,具备微服务架构、大数据与AI分析、物联网设备联网、多端协同等创新点,推动建筑行业向数字化、智能化转型。未来将融合5G、区块链等技术,助力智慧城市建设。
640 1
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
1399 2
|
12月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
1124 29
|
12月前
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
470 4
|
12月前
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
移动开发 前端开发 JavaScript
从入门到精通:H5游戏源码开发技术全解析与未来趋势洞察
H5游戏凭借其跨平台、易传播和开发成本低的优势,近年来发展迅猛。接下来,让我们深入了解 H5 游戏源码开发的技术教程以及未来的发展趋势。

推荐镜像

更多
  • DNS