生命周期BeanPostProcessor(3)---Spring源码从入门到精通(九)

简介: 生命周期BeanPostProcessor(3)---Spring源码从入门到精通(九)

上篇文章主要介绍了Bean生命周期,bean生命周期:创建bean--->初始化init--->销毁destory,而初始化和销毁是可以用@Bean指定的,或者用@PostCoustruct@preDestory注解,或者用InitializingBean和DisposableBean接口都能指定调用的初始化和销毁方法:

Bean生命周期(2)---Spring源码从入门到精通(八)


这篇主要介绍BeanPostProcessor,在spring框架非常重要,里面有两个接口,一个是postProcessBeforeInitialization 和 postProcessAfterInitialization两个方法,顾名思义,前者在类初始化前调用,后者在类初始化之后调用。

下面主要分为三个部分:

1、BeanPostProcessor实用。

2、BeanPostProcessor源码解析。

3、Spring底层使用BeanPostProcessor。


1、BeanPostProcessor实用


先自定义类MyBeanPostProcessor实现接口,会重写里面的两个方法,可以打印出当前初始化的类。


/**
 * 自定义类实现beanPostProcessor接口,两个重写的方法在bean初始化前后调用。
 *
 * 初始化之前用populateBean()方法,给bean属性赋值
 * 初始化开始:
 * 「
 * applyBeanPostProcessorsBeforeInitialization()初始化之前调用的方法 , 接口BeanPostProcessor
 * invokeInitMethods()方法初始化 ,执行bean初始化
 * applyBeanPostProcessorsAfterInitialization()初始化之后调用的方法 , 接口BeanPostProcessor
 * 」
 *
 * @author keying
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(
            "postProcessBeforeInitialization.....Before..." + bean.getClass() + ",【beanName】=" + beanName);
        return bean;
    }
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(
            "postProcessAfterInitialization.....After..." + bean.getClass() + ",【beanName】=" + beanName);
        return bean;
    }
}


junitTest还和上篇文章一样不变,直接运行,为了方便理解,再贴一遍:


@Test
    public void test() {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
            ConfigLifeCycle.class);
        System.out.println("容器创建完毕");
        //多实例情况下,需要获取组件,才会初始化,并且不会销毁
        //Object carObject = annotationConfigApplicationContext.getBean("car");
        //getDefinitionNames(annotationConfigApplicationContext);
        annotationConfigApplicationContext.close();
    }


控制台打印如下,我们创建的三个bean在初始化的前后都会打印:

image.png


2、BeanPostProcessor源码解析。


1、刚开始AnnotationConfigApplicationContext主要调用refresh()方法

image.png

2、点进去之后,refresh主要调用finishBeanFactoryInitialization方法,初始化所有单实例对象  

image.png

3、点进去之后,调用下图的beanFactory.preInstantiateSingletons方法

image.png

4、初始化单实例 bean之后,点进去此方法,可以看到getBean方法

image.png

5、点进getBean之后,可以看到下图方法,获取单实例,若获取不到,就会createBean创建对象并且返回。

image.png

6、createBean里有个doCreateBean,点进此方法,里面有个populateBean方法作用是在初始化对象之前,给bean注入信息,bean名,工厂名,之后下面的initializeBean方法,后面的方法就是处理器的调用。

image.png

   

7、点进initializaBean方法可以看到,里面有三个方法,中间invokeInitMethods方法就是初始化bean,applyBeanPostProcessorsBeforeInitialization方法为初始化之前调用的,applyBeanPostProcessorsAfterInitialization方法为初始化之后调用的。

image.png

8、点击applyBeanPostProcessorsBeforeInitialization方法,进入可以看到,遍历获取容器所有的beanPostProcessors,挨个执行beforeInitialization若返回为 null,则跳出for循环,不会执行后面的postBeforeBeforeInitialization方法。      

image.png


3、Spring底层使用BeanPostProcessor


可以传递ApplicationContext对象,用bean实现ApplicationContextAware方法,代码如下:


@Component
public class Cat implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    public Cat(){
        System.out.println("Cat...construct");
    }
    /**
     * construct 构造函数创建对象之后执行
     */
    @PostConstruct
    public void init(){
        System.out.println("cat ...PostConstruct.");
    }
    /**
     * 销毁之前调用
     */
    @PreDestroy
    public void destory(){
        System.out.println("cat ...PreDestroy");
    }
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}


源码如下,ApplicationContextAwareProcessor类就是集成了此接口,里面可以设置代码里的ApplicationContext。

image.png

BeanValidationPostProcessor类,作用在bean初始化前后进行效验,源码如下。


public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (!this.afterInitialization) {
            this.doValidate(bean);
        }
        return bean;
    }
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (this.afterInitialization) {
            this.doValidate(bean);
        }
        return bean;
    }

之前用的@PostConstruct,和@PreDestroy注解也是因为BeanPostProcessor才运行的,在InitDestroyAnnotationBeanPostProcessor类里,调用invokeInitMethods方法

image.png点进invokeInitmethods方法可以看到,会用反射调用element.invoke方法,找到对应的bean

image.png

还有AutowiredAnnotationBeanPostProcessor类,就是在对象创建完之后,处理@Autowired注解获取到bean对象。


所有@Bean注入对象,其他方法注入组件,@Autowired,生命周期注解,@Async异步注解等等,都是基本BeanPostProcessor接口实现的。


简单总结:spring生命周期,主要为bean创建--->init初始化--->销毁,

单实例在容器加载完毕前,创建和初始化,多实例在获取bean的时候才会创建bean和初始化。@Bean注释可以指定init-method和destory-method来初始化和销毁,@PostConstruct注解和接口也可以实现,这些都基于BeanPostRrocessor接口,控制生命周期,并且实现此接口,可以在bean初始化前后处理事务。


相关文章
|
17天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
1天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
9 2
|
7天前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
28 9
|
1月前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
104 5
|
1月前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
1月前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
23 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
|
1月前
|
Java API Spring
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中过滤器的基础知识和实战项目应用的教程。
22 0
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
|
1月前
|
XML Java 数据格式
手动开发-简单的Spring基于注解配置的程序--源码解析
手动开发-简单的Spring基于注解配置的程序--源码解析
45 0
|
存储 Java 程序员
深入理解 Spring BeanPostProcessor
回顾上一篇博客中,在AbstractApplicationContext这个抽象类中,Spring使用invokeBeanFactoryPostProcessors(beanFactory);执行BeanFactoryPostProcessor,通过回调Spring自己添加的ConfigurationClassPostProcessor以及用户添加的bean工厂的后置处理器,完成了包扫描以及对主配置类代理的工作 本篇博文将继续往下跟进
150 0
|
2月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。