当前位置: 首页 > news >正文

Spring源码-xxxAware实现类和BeanPostProcessor接口调用过程

xxxAware实现类作用

以ApplicationContextAware接口为例
ApplicationContextAware的作用是可以方便获取Spring容器ApplicationContext,从而可以获取容器内的Bean


package org.springframework.context;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.Aware;/**
public interface ApplicationContextAware extends Aware {/**
设置该对象运行的ApplicationContext。通常,这个调用将用于初始化对象。
<p>在填充普通bean属性之后调用,但在初始回调之前调用,
例如{@link org.springframework.beans.factory.InitializingBeanafterPropertiesSet()}
或自定义初始化方法。
在{@link ResourceLoaderAwaresetResourceLoader}, 
{@link ApplicationEventPublisherAwaresetApplicationEventPublisher}
和{@link MessageSourceAware}之后调用,如果适用的话。
@param applicationContext这个对象要使用的applicationContext对象
@在context初始化错误的情况下抛出
ApplicationContextException 
@如果被应用程序context方法抛出则抛出BeansException @参见org.springframework.beans.factory.BeanInitializationException*/void setApplicationContext(ApplicationContext applicationContext) throws BeansException;}

下面这个例子就是ApplicationContextUtil 实现了ApplicationContextAware 这个接口,重写了setApplicationContext(ApplicationContext applicationContext)方法,在调用到这个方法的时候给类里的applicationContext 属性赋值,后续别的方法在拿到这个applicationContext进行操作,比如根据getBean方法获取Bean对象以及调用beanFactory.registerBeanDefinition(beanName, definition);方法进行添加BeanDefinition即bean的元数据信息。

public class ApplicationContextUtil implements ApplicationContextAware {private static ApplicationContext applicationContext = null;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {if (this.applicationContext == null) {this.applicationContext = applicationContext;}}//获取applicationContextpublic static ApplicationContext getApplicationContext() {return applicationContext;}//通过name获取 Bean.public static Object getBean(String name) {return getApplicationContext().getBean(name);}//通过class获取Bean.public static <T> T getBean(Class<T> clazz) {return getApplicationContext().getBean(clazz);}/*** 同步方法注册bean到ApplicationContext中** @param beanName* @param clazz* @param original bean的属性值*/public static synchronized void setBean(String beanName, Class<?> clazz, Map<String,Object> original) {checkApplicationContext();DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();if(beanFactory.containsBean(beanName)){return;}//BeanDefinition beanDefinition = new RootBeanDefinition(clazz);GenericBeanDefinition definition = new GenericBeanDefinition();//类classdefinition.setBeanClass(clazz);//属性赋值definition.setPropertyValues(new MutablePropertyValues(original));//注册到spring上下文beanFactory.registerBeanDefinition(beanName, definition);}}

上述是相关使用,为什么实现这个接口就会调用这个set方法,接下来根据spring源码,讲解xxxAware接口的前世今生。
不重要的步骤给出调用链路

AnnotationConfigApplicationContext## AnnotationConfigApplicationContext(String... basePackages) 构造函数
AbstractApplicationContext##refresh()容器刷新
AbstractApplicationContext##prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)beanFactory的准备工作,对各种属性进行填充

prepareBeanFactory准备工作

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// 添加beanPostProcessor,ApplicationContextAwareProcessor此类用来完成某些Aware对象的注入beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));// 设置要忽略自动装配的接口,很多同学理解不了为什么此处要对这些接口进行忽略,原因非常简单,这些接口的实现是由容器通过set方法进行注入的,// 所以在使用autowire进行注入的时候需要将这些接口进行忽略beanFactory.ignoreDependencyInterface(EnvironmentAware.class);beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);}

看下ApplicationContextAwareProcessor这个类:

/*** 接口beanPostProcessor规定的方法,会在bean创建时,实例化后,初始化前,对bean对象应用* @param bean the new bean instance* @param beanName the name of the bean* @return* @throws BeansException*/@Override@Nullablepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){return bean;}AccessControlContext acc = null;if (System.getSecurityManager() != null) {acc = this.applicationContext.getBeanFactory().getAccessControlContext();}if (acc != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {// 检测bean上是否实现了某个aware接口,有的话进行相关的调用invokeAwareInterfaces(bean);return null;}, acc);}else {invokeAwareInterfaces(bean);}return bean;}

在这个类postProcessBeforeInitialization(Object bean, String beanName)这个方法内部会调用invokeAwareInterfaces(Object bean) 这个方法,判断bean的类型是属于哪一个xxxAware接口然后执行对应的setXXX()方法,至此和前边实现ApplicationContextAware接口重写setApplicationContext()方法串起来了,在哪里调用setApplicationContext方法完成。

/*** 如果某个bean实现了某个aware接口,给指定的bean设置相应的属性值** @param bean*/private void invokeAwareInterfaces(Object bean) {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);}}

还有一个问题,ApplicationContextAwareProcessor这个类的postProcessBeforeInitialization(Object bean, String beanName) 方法什么时候在哪里进行调用呢?这个类实现了BeanPostProcessor这个接口

/*** bean的后置处理器接口,在依赖注入的初始化方法前后进行调用*/
public interface BeanPostProcessor {/*** 初始化方法调用前要进行的处理逻辑*/@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}/*** 在初始化方法指定后要进行的处理逻辑*/@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}}

接下来看实现了BeanPostProcessor 这个接口的实现类在哪里会被触发调用里面的postProcessBeforeInitialization方法!!!!
通过看调用链路,下面是整个过程是在完成实例化,属性填充,执行初始化的时候在initializeBean方法调用 applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
在这里插入图片描述
applyBeanPostProcessorsBeforeInitialization细节,对实现BeanPostProcessor 的类进行调用postProcessBeforeInitialization这个方法,这里会调用到ApplicationContextAwareProcessor的postProcessBeforeInitialization方法来对invokeAwareInterfaces实现Aware接口的类进行set操作

	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {//初始化返回结果为existingBeanObject result = existingBean;//遍历 该工厂创建的bean的BeanPostProcessors列表for (BeanPostProcessor processor : getBeanPostProcessors()) {// postProcessBeforeInitialization:在任何Bean初始化回调之前(如初始化Bean的afterPropertiesSet或自定义的init方法)// 将此BeanPostProcessor 应用到给定的新Bean实例。Bean已经填充了属性值。返回的Bean实例可能时原始Bean的包装器。// 默认实现按原样返回给定的 BeanObject current = processor.postProcessBeforeInitialization(result, beanName);// 如果 current为nullif (current == null) {//直接返回result,中断其后续的BeanPostProcessor处理return result;}//让result引用processor的返回结果,使其经过所有BeanPostProcess对象的后置处理的层层包装result = current;}//返回经过所有BeanPostProcess对象的后置处理的层层包装后的resultreturn result;}

同时,在完成实例化,属性填充,执行初始化的时候在initializeBean方法调用 applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);将BeanPostProcessors应用到给定的现有Bean实例,调用它们的postProcessAfterInitialization方法。

@Overridepublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {//初始化结果对象为result,默认引用existingBeanObject result = existingBean;//遍历该工厂创建的bean的BeanPostProcessors列表for (BeanPostProcessor processor : getBeanPostProcessors()) {//回调BeanPostProcessor#postProcessAfterInitialization来对现有的bean实例进行包装Object current = processor.postProcessAfterInitialization(result, beanName);//一般processor对不感兴趣的bean会回调直接返回result,使其能继续回调后续的BeanPostProcessor;// 但有些processor会返回null来中断其后续的BeanPostProcessor// 如果current为nullif (current == null) {//直接返回result,中断其后续的BeanPostProcessor处理return result;}//让result引用processor的返回结果,使其经过所有BeanPostProcess对象的后置处理的层层包装result = current;}//返回经过所有BeanPostProcess对象的后置处理的层层包装后的resultreturn result;}

至此,BeanPostProcessor接口的调用以及实现xxxAware的类的调用使用处理过程讲解结束

    初始化方法调用前要进行的处理逻辑default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}在初始化方法指定后要进行的处理逻辑default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}
http://www.lryc.cn/news/376741.html

相关文章:

  • Uni-app x
  • Python 基础:文件
  • WebForms 母版页
  • Java应用打包成Docker镜像
  • 什么是自动驾驶中的CopyCat?
  • 为什么没人详细说过智能猫砂盆?最受欢迎的好用智能猫砂盆解析!
  • AI视频智能监管赋能城市管理:打造安全有序的城市环境
  • 多态性(Java)
  • 国际期货行情相关术语
  • LeetCode20.有效的括号
  • 尚玩助手广告变现app开发
  • Anti-human IL-10 mAb (12G8), biotin:Mabtech热销品
  • 【植物大战僵尸杂交版】致敬传奇游戏玩家——一个普通人的六年坚持
  • 【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 部门组队编程(200分) - 三语言AC题解(Python/Java/Cpp)
  • 民生银行信用卡中心金融科技24届春招面经
  • HTML李峋同款跳动的爱心代码(双爱心版)
  • 【linux】内核从tcp层调用IP层摸索中
  • Python 中的 Pandas(数据分析与处理)
  • 【文档智能 RAG】RAG增强之路-智能文档解析关键技术难点及PDF解析工具PDFlux
  • 五大API接口:提升你的应用性能与用户体验
  • RabbitMQ实践——在Ubuntu上安装并启用管理后台
  • Ubuntu中防火墙的使用 和 开放 关闭 端口
  • ansible 模块进阶及变量
  • MYSQL数据库安装
  • Pycharm配置远程调试
  • 【Java面试】二十二、JVM篇(下):JVM参数调优与排查
  • 统计信号处理基础 习题解答10-17
  • 嵌套使用模板类
  • adb卸载系统应用
  • Rapidfuzz,一个高效的 Python 模糊匹配神器