当前位置: 代码迷 >> 综合 >> Spring的后置处理器到底是怎么回事?
  详细解决方案

Spring的后置处理器到底是怎么回事?

热度:111   发布时间:2023-09-06 13:00:56.0

这里要介绍的是Spring的扩展类点之一的:BeanPostProcessor. 废话不多说,开搞!

1.准备代码

Spring的后置处理器到底是怎么回事?

  • TestProcessor类
@Component
public class TestProcessor implements BeanPostProcessor ,PriorityOrdered{@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("personService")){System.out.println("BeforeInitialization1");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("personService")){System.out.println("AfterInitialization1");}return bean;}@Overridepublic int getOrder() {return 200;}
}
  • TestProcessor2类
@Component
public class TestProcessor2 implements BeanPostProcessor,PriorityOrdered {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("personService")){System.out.println("BeforeInitialization2");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("personService")){System.out.println("AfterInitialization2");}return bean;}@Overridepublic int getOrder() {return 199;}
}
  • PersonService类
@Component
public class PersonService {public PersonService() {System.out.println("personService构造方法执行了");}@PostConstructpublic void init(){System.out.println("init方法执行了");}
}
  • PersonService2类
@Component
public class PersonService2 implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;System.out.println("全局对象:"+ applicationContext);}
}
  • SpringConfiguration类
@ComponentScan("com.v1")
public class SpringConfiguration {}
  • Test01类
public class Test01 {public static void main(String[] args) {//这个构造方法会把Spring所有的环境都准备好AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);}
}

2.点击 AnnotationConfigApplicationContext

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {//这个类有父类,所以会先初始化父类的构造方法,接着初始化自己的构造方法//调用无参构造方法进行初始化一个读取器和扫描仪this();//把配置类加载进 DefaultListableBeanFactory 的map集合中//配置类可以一次性传多个,这个方法执行后,只是把配置类加载进了 DefaultListAbleBeanFactory的map集合中//还没有扫描其他的的加了组件的类register(annotatedClasses);//实例化所有被加了组件的对象refresh();
}

3.点击 refresh() 方法

@Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识//这个方法不是重点,可以暂时认为他不干任何事情prepareRefresh();//获取工厂对象 ,本质是DefaultListableBeanFactory对象//其实读取xml文件变成beanDefinition,也是在这里面完成的//所以这里面的功能和register(annotatedClasses);功能很像//一个是是从xml文件中读取配置信息,一个是通过类的注解读取信息ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//为BeanFactory配置类加载器、后置处理器等等//这个方法比较重要prepareBeanFactory(beanFactory);//剩余的代码省略.....}

4.点击 prepareBeanFactory 方法

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {//添加一个类加载器beanFactory.setBeanClassLoader(getClassLoader());//bean的表达式解析,以后再讲,在前台页面可以获取到bean表达式的一些属性beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));//对象与string类型的转换 <property >beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));//重要方法//为Spring添加后置处理器 ApplicationContextAwareProcessor 实现了BeanProcessor接口//我们主要查看 重写接口的 postProcessBeforeInitialization ()方法//主要作用:判断当前bean对象实现了里面的那些接口,从而在bean类获取对应的对象//一般我们会实现 ApplicationContextAware 接口获取 applicationContextbeanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));//以下是添加自动注入忽略的列表,不是重点beanFactory.ignoreDependencyInterface(EnvironmentAware.class);beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);//等讲到bean的实例化的过程时,会说明beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);//这个ApplicationListenerDetector作用: 某个类实现了ApplicationListener接口,可以获取到一个ApplicationEvent对象//ApplicationEvent对象存储有reader,scanner,registry,beanFactory等对象//注意实现ApplicationListener的前提是,这个bean必须是单例的beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));//剩余的代码省略.....
}

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

解析这个方法之前,我们看一下 BeanFactory工厂里面到底存放了哪些数据

Spring的后置处理器到底是怎么回事?

粉色部分就是 BeanFactory 的示意图

  • 绿色部分: Spring初始化的时候,所有的beanDefinition都存储在这个beanDefinitionMap集合中
  • 黄色部分:beanDefinitionNames集合存储所有 beanDefinition的名称
  • 深紫部分: beanPostProcessors集合存储着所有的后置处理器,也就是实现了 BeanPostProcessor接口的类
  • 浅绿部分: getBeanNamesForType, beanFactory中的一个方法,通过类型得到一个beanName
  • 浅紫部分: singletonObjects,实例化后的类会存储在这个集合中

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))

这个方法把 ApplicationContextAwareProcessor 添加进了 beanPostProcessors,说明这个类是一个实现了

BeanPostProcessors的后置处理器

5.点击 ApplicationContextAwareProcessor `

查看 ApplicationContextAwareProcessor,果然它实现了 BeanPostProcessor

6.点击 BeanPostProcessor


public interface BeanPostProcessor {/* * 在bean的初始化之前执行*/@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}/** 在bean的初始化之后执行*/@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}}
  • BeanPostProcessor是Spring框架提供的一个扩展类点之一
  • 扩展类点其实有很多种的 例如实现 BeanFactoryPostProcessor接口也是
  • BeanPostProcessor作用:
    • 通过实现BeanPostProcessor接口,程序员就可以插手bean的实例化过程,从而减轻beanFactory的负担
    • 这个接口可以被多个类实现,会形成一个列表, 通过实现PriorityOrdered可以改变实现类的执行顺序,getOrder返回值越小越优先执行
    • AOP的就是在bean实例化后期将切面逻辑织入bean实例中的
    • AOP也是通过BeanPostProcessor和IOC容器建立起了联系

Spring默认提供很多BeanPostProcessor的实现类
其实这个接口的本身方法特别的简单,简单到令人发指,但是他的实现类巨多,实现类的方法内的逻辑复杂的程 度也令人发指

前面我们准备了两个处理器 TestProcessor,TestProcessor2都实现了 BeanPostProcessorPriorityOrdered

  • TestProcessor类
@Component
public class TestProcessor implements BeanPostProcessor ,PriorityOrdered{@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {//所有的类的实例化过程中都会执行执行实现了BeanPostProcessor后置处理器//为了避免其他类做实例化的时候,也打印BeforeInitialization1,影响测试if (beanName.equals("personService")){System.out.println("BeforeInitialization1");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("personService")){System.out.println("AfterInitialization1");}return bean;}@Overridepublic int getOrder() {return 200;}
}
  • TestProcessor2类
@Component
public class TestProcessor2 implements BeanPostProcessor,PriorityOrdered {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("personService")){System.out.println("BeforeInitialization2");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("personService")){System.out.println("AfterInitialization2");}return bean;}@Overridepublic int getOrder() {return 199;}
}

两个后置处理器都实现了 BeanPostProcessor的init和after方法,实现了 PriorityOrderedgetOrder方法

实现 getOrder的后置处理器,返回值为 int 类型,返回值越小,执行的顺序越靠前

我们回到 Test01运行测试类

测试结果:

personService构造方法执行了
BeforeInitialization2
BeforeInitialization1
init方法执行了
AfterInitialization2
AfterInitialization1
全局对象:org.springframework.context.annotation.AnnotationConfigApplicationContext@100955a, started on Sun Dec 08 11:48:03 CST 2019

7.我们回到 ApplicationContextAwareProcessor类中

既然我们已经知道了 BeanPostProcessors的作用,我们看看 ApplicationContextAwareProcessor这个Spring内部的后置处理器的init方法和after方法里面到底干了哪些事

class ApplicationContextAwareProcessor implements BeanPostProcessor {private final ConfigurableApplicationContext applicationContext;private final StringValueResolver embeddedValueResolver;public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {this.applicationContext = applicationContext;this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());}@Override@Nullablepublic Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {AccessControlContext acc = null;//这个方法不会进入if (System.getSecurityManager() != null &&(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {acc = this.applicationContext.getBeanFactory().getAccessControlContext();}if (acc != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareInterfaces(bean);return null;}, acc);}else {//这个重点invokeAwareInterfaces(bean);}return bean;}/*** 判断当前的bean,实现了什么类型的接口,然后根据判断设置类* @param bean*/private void invokeAwareInterfaces(Object bean) {if (bean instanceof Aware) {//(1)如果bean实现了EnvironmentAware接口,可以获取环境对象if (bean instanceof EnvironmentAware) {((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());}//(2)如果bean实现了EmbeddedValueResolverAware接口,可以获取embeddedValueResolver对象if (bean instanceof EmbeddedValueResolverAware) {((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);}//(3)如果bean实现了ResourceLoaderAware接口,可以获取applicationContext工厂对象if (bean instanceof ResourceLoaderAware) {((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);}//(4)如果bean实现了ApplicationEventPublisherAware接口,可以获取applicationContext工厂对象if (bean instanceof ApplicationEventPublisherAware) {((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);}//(5)如果bean实现了MessageSourceAware接口,可以获取applicationContext工厂对象if (bean instanceof MessageSourceAware) {((MessageSourceAware) bean).setMessageSource(this.applicationContext);}//(6)如果该bean实现了ApplicationContextAware接口 ,那么就把工厂applicationContext,传进去
//在bean的类中重写ApplicationContextAware的set方法 就可以在该bean中获取到整个工厂
//这时候想获取哪个对象都可以了if (bean instanceof ApplicationContextAware) {((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);}}}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {return bean;}}

通过查看 ApplicationContextAwareProcessor处理器,我们发现 ,它同样是实现了 BeanPostFactory的两个方法 postProcessBeforeInitializationpostProcessAfterInitialization方法,但是 后置方法并没有干任何事,我们重点查看 前置方法

ApplicationContextAwareProcessor方法中,调用 invokeAwareInterfaces方法,

查看 invokeAwareInterfaces方法,我们查询,只要实现某一个接口就能获取相应的对象

例如在准备代码中,我们的 PersonService2实现了 ApplicationContextAware接口

@Component
public class PersonService2 implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;System.out.println("全局对象:"+ applicationContext);}
}

实现了 setApplicationContext就可以获取全局对象

假设你这样一个需求,需要初始化的时候获取到Spring的全局对象,那么你就可以实现 ApplicationContextAware

总结一下 ApplicationContextAwareProcessor到底干了哪些事?

  1. 实现了 BeanPostProcessors接口
  2. postProcessBeforeInitialization方法里面执行 invokeAwareInterfaces方法
  3. invokeAwareInterfaces方法中,判断当前的Bean实现了哪些接口,如果实现了某个接口就可以获取对应的对象

8.我们回到 第四步 点击 prepareBeanFactory `方法

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {//添加一个类加载器beanFactory.setBeanClassLoader(getClassLoader());//bean的表达式解析,以后再讲,在前台页面可以获取到bean表达式的一些属性beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));//对象与string类型的转换 <property >beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));//重要方法//为Spring添加后置处理器 ApplicationContextAwareProcessor 实现了BeanProcessor接口//我们主要查看 重写接口的 postProcessBeforeInitialization ()方法//主要作用:判断当前bean对象实现了里面的那些接口,从而在bean类获取对应的对象//一般我们会实现 ApplicationContextAware 接口获取 applicationContextbeanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));//以下是添加自动注入忽略的列表,不是重点beanFactory.ignoreDependencyInterface(EnvironmentAware.class);beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);//等讲到bean的实例化的过程时,会说明beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);//这个ApplicationListenerDetector作用: 某个类实现了ApplicationListener接口,可以获取到一个ApplicationEvent对象//ApplicationEvent对象存储有reader,scanner,registry,beanFactory等对象//注意实现ApplicationListener的前提是,这个bean必须是单例的beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));//剩余的代码省略.....
}

在该方法中 ,不仅添加了 ApplicationContextAwareProcessor,这个后置处理器,其实还添加了 ApplicationListenerDetector这个处理器

9.点击 ApplicationListenerDetector

我们主要查看 postProcessAfterInitialization方法

@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {//判断当前的bean是否实现了ApplicationListener这个接口,如果没有实现直接跳过if (bean instanceof ApplicationListener) {//如果有实现,则判断当前的bean实现是单例的//singletonNames存储用户所有的bean,// key值为 beanName ,value值为Boolean值 false 代表为不是单例 true代表为单例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 eventslogger.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;}

这个方法主要作用:

执行了 ApplicationListener,必须是 单例的,才可以获取到相应的对象

视频讲解:

<https://www.bilibili.com/video/av67899876?p=4>

视频为自己学习的时候录制的,也方便自己以后看

Spring5源码地址:

<https://gitee.com/zouchangfu/spring_5_source_code>

Spring5源码都是已经构建好的了,无需再使用gradle进行构建了,直接打开就可以跑起来

写在最后:

大二学生一枚,挤时间写博客不容易,看完顺手点个赞,你的点赞是对我最大的鼓励

  相关解决方案