代码编织梦想

该系列文章主要学习 雷丰阳老师的《Spring注解驱动》课程总结。
原课程地址:课程地址

包括了自己阅读其他书籍《Spring揭秘》《Spring Boot 实战》等课程。

该系列文档会不断的完善,欢迎大家留言及提意见。

1. 写在之前

本篇会有一些源码的分析,如果暂时觉得没有用处,可以跳过该章节。

为什么要有 BeanPostProcessor 呢?

想要插手容器的管理过程,在实例化对象之前,对注册到容器中的 Bean 的基本信息做一些修改。相当于在容器进行第一道程序之前做一些额外的工作。

2. BeanPostProcessor 是什么

首先查看源码中的定义,主要是在 Bean 的实例化前后加上一些自己的业务逻辑,如果有多个 BeanPostProcessor 怎么办呢?

需要让 该实现类再实现 org.springframework.core.Ordered 接口,定义自己的顺序,会按照它们在容器中注册的顺序执行。

public interface BeanPostProcessor {

	/**
	 * 在 bean实例化之前通过该方法加入自己的 私货
	 */
	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

	/**
	 * bean 实例化之后再加上自己的 私货
	 */
	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

Spring 本身已经提供了现成的 BeanPostProcessor 实现类,如果没有特殊需求我们一般很少自定义 BeanPostProcessor。

CommonAnnotationBeanPostProcessor

AsyncAnnotationBeanPostProcessor

因此今天我们先来分析一下 Spring 给我提供的 Bean 是如何工作的。

3. xxxBeanPostProcessor 源码分析

先自定义一个 MyBeanPostProcessor ,该定义没有任何功能,只是输出了一些日志。

/**
 * 后置处理器,在初始化前后进行处理工作
 */
@Component 
public class MyBeanPostProcessor implements BeanPostProcessor, Ordered {

	@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;
	}

	@Override
	public int getOrder() {
		return 3;
	}

}

我们可以通过debug 模式反着查看,postProcessBeforeInitialization() 方法是在什么时候被触发的。

debug查看postProcessBeforeInitialization运行方式

了解了整个调用过程中之后再来给大家分析 , BeanPostProcessor何时被调用,已经调用的过程。

第一步:main方法入口加载配置类。

这一步没有什么可说的,只是创建了一个 AnnotationConfigApplicationContext 对象。并且通过构造器来触发容器的初始化过程。

public class MainTest {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(PersonConfig.class);
        System.out.println("applicatiomContext: " + applicationContext);
    }
}

第二步:通过 refresh()刷新容器。

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
		this();
		register(annotatedClasses);
  	// 这一步最为关键
		refresh();
}

第三步:通过 refresh() 方法来初始化 Bean 对象。

该方法特别长,此处我们只是抓住我们要分析的重点,直接查看初始化单例模式的组件

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
				//省略其他步骤

        // 初始化单例的组件
				finishBeanFactoryInitialization(beanFactory);

			}

		// 暂时先忽略其他步骤
	}

第四步:完成Bean 工厂环境的初始化,开始初始化所有的单实例 bean 组件。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// spring context的一些设置,此处同样先忽略

		// Instantiate all remaining (non-lazy-init) singletons.
    // 这里和三步一样,对于我们此次要分析的还是啥都没干。
		beanFactory.preInstantiateSingletons();
	}

第五步:跳过一些暂时不相关的步骤来到初始化Bean的过程。

后续的一连串操作只是为了从容器的一大堆 Bean中找到每个Bean ,并且执行初始化方法,所以我们沿着堆栈直接跳到 Bean的初始化方法中。

初始化Bean对象

仔细看初始化 Bean 的方法

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    // 1. security的一些校验,与此次分析无关,可以先忽略
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					invokeAwareMethods(beanName, bean);
					return null;
				}
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}


		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}

		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

其实上面这堆代码主要看这一行,翻译过来就是:在初始化之前先调用 BeanPostProcessors 方法。

wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

第六步:真正的调用 BeanPostProcessors 方法。通过该方法来调用我们自定义的和系统中自带的 BeanPostProcessors 实现类。

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
  throws BeansException {

  Object result = existingBean;
  for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
    result = beanProcessor.postProcessBeforeInitialization(result, beanName);
    if (result == null) {
      return result;
    }
  }
  return result;
}

可以看到我们自定义的 MyBeanPostProcessors 就在其中,Spring 这里利用了增强 for 循环,一次执行每一个 BeanPostProcessors 实现类。

也正是在这里完成了我们自定义 MyBeanPostProcessors 的 postProcessBeforeInitialization()方法调用,另一个的方法 postProcessAfterInitialization 实现的逻辑类似

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p47yDhE6-1629010353889)(/Users/xiaxiaojian/Library/Application%20Support/typora-user-images/image-20210814200753321.png)]

4. Spring框架用该接口干嘛呢?

刚才 debug 过程中,我们发现了 Spring 本身自带了很多 BeanPostProcessors 实现类,我们分析一个类,看看Spring 到底用这个功能干什么。

以 ApplicationContextAwareProcessor 实现类为例,该实现类本身只是用到了 postProcessBeforeInitialization() 方法,具体的实现功能如下。

方法看起来很长,不过大部分代码跟我们这次分析无关,最关键的是 invokeAwareInterfaces()方法

完整方法

核心功能如下

@Override
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		  // 先忽略 security 验证
      // 其实就是调用各种 Aware 接口
 			invokeAwareInterfaces(bean);
		}

		return bean;
	}

关于 invokeAwareInterfaces() 主要逻辑如下,其实就是将各种依赖与bean 组件进行绑定。

关于 各种各样的 Aware 后续有机会给大家介绍,这里先简单说明功能

将 Aware 接口定义中规定的依赖注入给当前实例对象。

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) {
      ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
    }
  }
}

总结

整个 Spring 源码代码量比较大,你想一下 ,Spring已经迭代了多少年了,至少有几十万行(保守估计)。大家可以将复杂的源码拆解,每次一点点的分析。

分析源码目的不是为了看源码而看,而是知道这个功能是什么,是如何实现的,能否有借鉴的思想。

其实 BeanPostProcessors 说白了,定义了一个接口,有众多的实现类,在每次初始化 Bean 之前,依次调用每个实现类的方法,循环调用哦。

在 Spring 中有大量的这种设计模式,循环调用,这也侧面证明了为啥Spring 启动如此慢了。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_37690143/article/details/119713848

spring注解驱动开发——bean的后置处理器_如不來的博客-爱代码爱编程

BeanPostProcessor:是一个接口,bean的后置处理器(实际是在bean的初始化前后执行操作) public class MyBeanPostProcessor implements BeanPostProcessor{ /** * bean是容器调用构造器创建的实例 * beanName是实例的id * 在所有初始化方法之

spring beanpostprocessor 后置处理器学习_tom有了cat的博客-爱代码爱编程

基础概念: 1、实例化—-实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中 2、初始化—-初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性 sprig  beanPostProcessor 后置处理器主要用于对在对象初始化之前或者在对象初始化之后在这期间可以对对象做一些其他事情,

spring注解---BeanPostProcessor后置处理器-爱代码爱编程

.BeanPostProcessor :bean的后置处理器。         postProcessBeforeInitialization:bean实例被创建之后,初始化方法执行之前被执行         postProcessAfterInitialization:初始化方法执行之后被执行         参数:Object bean:当前实例

【Spring源码】 后置处理器BeanPostProcessor底层原理分析-爱代码爱编程

【Spring源码】 BeanPostProcessor底层原理分析 1.Spring中bean的生命周期2.Spring注解开发指定初始化和销毁的方式3.BeanPostProcessor底层原理分析4.Spring中BeanPostProcessor的应用 注:其他一些spring源码解读,如果有需要,可以参考: 【spring源码】sp

简单了解spring中的BeanPostProcessor(后置处理器)-爱代码爱编程

现象 最近项目中使用了spring中的异步处理@EnableAsync和定时任务@EnableSchedule,二者作用在同一个service中,导致异步方法失效,最终发现还是不了解后置处理器作用导致的,还是图样图森破。 BeanPostProcessor 该接口的两个方法如下,都与Bean的生命周期有密切联系, 不了解bean生命周期的同学参考

Spring注解开发——15、生命周期-BeanPostProcessor-后置处理器-爱代码爱编程

15、生命周期-BeanPostProcessor-后置处理器 BeanPostProcessor 接口package org.springframework.beans.factory.config; import org.springframework.beans.BeansException; import org.springframework

Spring Boot使用BeanPostProcessor-后置处理器对Bean进行拦截,改造Bean或做一些逻辑业务-爱代码爱编程

前面我们介绍了一些方式定制Bean的生命周期,这篇博客将介绍如何在把Bean注入容器之前拦截,再根据需求做一些操作。 创建类实现BeanPostProcessor接口,并重写方法。使用@Component注解,把其注入容器(这样Processor才能起作用)。:import com.michael.annotation.demo.POJO.Module;

spring源码:九大后置处理器-爱代码爱编程

目的: spring在完成一个bean的初始化、实例化的过程中,会用到九个后置处理器;本文梳理出这九个后置处理器 九大后置处理器 spring在初始化的过程中,会在九个地方分别调用了五个后置处理的九个方法 第一次调用后置处理器org.springframework.beans.factory.support.AbstractAutowireCapa

spring--bean后置处理器(BeanPostProcessor)原理解析-爱代码爱编程

文章目录 功能描述:如何使用:定义要处理的接口类型添加实际需要处理的类定义后置处理器编写测试类执行日志后置处理器加载解析registerBeanPostProcessors注册拦截bean创建的后置处理器后置处理器的调用bean实例化前、后的处理调用过程举例谈谈spring内部实现了BeanPostProcessor接口的类BeanPostProc

Spring —— BeanPostProcessor 后处理器梳理-爱代码爱编程

Spring —— BeanPostProcessor 后处理器梳理 前言版本BeanPostProcessorApplicationContextAwareProcessorDestructionAwareBeanPostProcessorInitDestroyAnnotationBeanPostProcessorInstantiationAwa

Spring-Bean后置处理器之CommonAnnotationBeanPostProcessor-爱代码爱编程

目录 本文能帮你解答的问题 类定义 作用 类结构 继承父类 构造函数 实现方法分析 InitDestroyAnnotationBeanPostProcessor postProcessMergedBeanDefinition postProcessBeforeInitialization postProcessBeforeDestru

SpringIOC注解启动原理,后置处理器BeanPostProcessor,Spring-Aop原理,Spring-Transaction原理(个人笔记)-爱代码爱编程

【Spring注解驱动原理】 一.this(): 将6种默认的【beanFactory后置处理器】注册到 applicationContext 容器中, 这里的后置处理器分2种,后面会有专门的 invokeBeanFactoryPostProcessors(beanFactory) 方法执行: (1)【BeanDefinitionRegistryPos

Spring的9处调用后置处理器-爱代码爱编程

在Sping的整个生命周期中,有9个地方调用后置处理器。这些后置处理器是spring实现自定义功能或者扩展spring的核心所在 一、实例化前 该方法属于InstantiationAwareBeanPostProcessor后置处理器 public interface InstantiationAwareBeanPostProcessor exten

9. spring-容器: BeanPostProcessor后置处理器-入门-爱代码爱编程

本章讲spring Bean生命周期中非常重要的功能,即BeanPostProcessor后置处理器, 很多功能都依赖BeanPostProcessor实现,如AOP,Autowired,初始化方法调用等。精通BeanPostProcessor并灵活加以利用,spring 容器就学会了一大半。 既然如此重要,还是先看源码: package org.s

10. spring-容器: BeanPostProcessor后置处理器-进阶-爱代码爱编程

再谈bean生命周期 目前整个bean的生命周期,我们可以进行如下控制: bean的实例化: 容器初始化时调用bean的构造方法,我们可以在构造方法中执行必要的逻辑bean的初始化: 在初始化时,可以通过BeanPostProcessor的postProcessBeforeInitialization()方法和postProcessAfterIniti