更多文章点击--spring源码分析系列

主要分析内容:

一、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor简述与demo示例
二、BeanFactoryPostProcessor源码分析:注册时机和触发点

(源码基于spring 5.1.3.RELEASE分析)

一、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor简述与demo示例

1、BeanFactoryPostProcessor是spring容器级别的拓展接口,是在BeanDefinition加载完成之后,未实例化之前.可以拓展接口,对定制化修改BeanDefinition.

 public interface BeanFactoryPostProcessor {

     void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

2、BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,是一种比较特殊的BeanFactoryPostProcessor。
BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry方法可实现自定义的bean注册定义。
通常spring注册bean使用静态方式, 如:xml、@Bean注解或@Component方式实现注册.不能通过程序来选择是否注册。

而实现BeanDefinitionRegistryPostProcessor的类可以获得BeanDefinitionRegistry 对象,通过它可以动态的注册组件,是实现动态注册的钩子函数。spring典型的ConfigurationClassPostProcessor拓展BeanDefinitionRegistryPostProcessor 解析@Configuration配置类 .

 public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

     void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

demo示例:

 public class CustomBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor {

     @Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
GenericBeanDefinition definition = new GenericBeanDefinition();
//设置类
definition.setBeanClass(RegistryBean.class);
//设置scope
definition.setScope("singleton");
//设置是否懒加载
definition.setLazyInit(false);
//设置是否可以被其他对象自动注入
definition.setAutowireCandidate(true); // 给属性赋值
MutablePropertyValues mpv = new MutablePropertyValues() ;
mpv.add("name", "CustomBeanDefinitionRegistry settings") ;
definition.setPropertyValues(mpv); registry.registerBeanDefinition("registryBean", definition);
} @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// do noting }
}

CustomBeanDefinitionRegistry.java

 public class LogicBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

     @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition bd = beanFactory.getBeanDefinition("bean") ;
MutablePropertyValues mpv = null ;
if(bd != null && (mpv = bd.getPropertyValues())!=null){
PropertyValue value = mpv.getPropertyValue("name");
System.out.print("修改之前 a 的value是:"+value.getValue()+"\n");
value.setConvertedValue("postProcessBeanFactory修改属性");
}
}
}

LogicBeanFactoryPostProcessor.java

 public class RegistryBean {

     public RegistryBean(){

     }

     public RegistryBean(String name){
this.name = name ;
} private String name ; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "RegistryBean{" +
"name='" + name + '\'' +
'}';
}
}

RegistryBean.java

 <?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="bean" class="com.nancy.ioc.Bean">
<property name="name" value="zhouxiaoxing"/>
</bean> <bean id="logicBeanFactoryPostProcessor" class="com.nancy.ioc.BeanFactoryPostProcessor.LogicBeanFactoryPostProcessor"/>
<bean id="customBeanDefinitionRegistry" class="com.nancy.ioc.BeanFactoryPostProcessor.CustomBeanDefinitionRegistry"/> </beans>

ioc-BeanFactoryPostProcessor.xml

 public class BeanFactoryPostProcessorTest {
private ApplicationContext applicationContext ; @Before
public void beforeApplicationContext(){
/**
* ApplicationContext 自动注册 BeanPostProcessor、InstantiationAwareBeanPostProcessor、BeanFactoryPostProcessor
* 不需要手动注册
* */
applicationContext = new ClassPathXmlApplicationContext("ioc-BeanFactoryPostProcessor.xml") ;
} @Test
public void test(){
Bean bean = applicationContext.getBean("bean", Bean.class) ;
RegistryBean registryBean = applicationContext.getBean("registryBean", RegistryBean.class) ;
System.out.println(bean);
System.out.println("registryBean :" + JSON.toJSONString(registryBean));
} @After
public void after(){
((ClassPathXmlApplicationContext)applicationContext).close();
}
}

BeanFactoryPostProcessorTest.java

运行结果: 可以看到实现动态的加载 RegistryBean 进入bean容器 和 定制化修改bean definition

修改之前 name 的value是:TypedStringValue: value [zhouxiaoxing], target type [null]
Bean{name='postProcessBeanFactory修改属性'}
registryBean :{"name":"CustomBeanDefinitionRegistry settings"}

详细demo示例可以参考:https://gitee.com/zhouxiaoxing91/learning-src/tree/master/spring-src/src/main/java/com/nancy/ioc

二、BeanFactoryPostProcessor源码分析:注册时机和触发点

注册和触发的入口在AbstractApplicationContext#refresh 容器刷新阶段, 只会调用一次 属于容器级别的拓展接口:

 @Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh(); // Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory); try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context.
// 注册BeanFactoryPostProcessor 在bean definition 加载完成之后
invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory); // Initialize message source for this context.
initMessageSource(); // Initialize event multicaster for this context.
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
onRefresh(); // Check for listener beans and register them.
registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
} // Destroy already created singletons to avoid dangling resources.
destroyBeans(); // Reset 'active' flag.
cancelRefresh(ex); // Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
} /**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}

这里先说说LoadTimeWeaver(LTW):

在Java 语言中,从织入切面的方式上来看,存在三种织入方式:编译期织入、类加载期织入和运行期织入。编译期织入是指在Java编译期,采用特殊的编译器,将切面织入到Java类中;而类加载期织入则指通过特殊的类加载器,在类字节码加载到JVM时,织入切面;运行期织入则是采用CGLib工具或JDK动态代理进行切面的织入。

AspectJ采用编译期织入和类加载期织入的方式织入切面,是语言级的AOP实现,提供了完备的AOP支持。它用AspectJ语言定义切面,在编译期或类加载期将切面织入到Java类中。

AspectJ提供了两种切面织入方式,第一种通过特殊编译器,在编译期,将AspectJ语言编写的切面类织入到Java类中,可以通过一个Ant或Maven任务来完成这个操作;第二种方式是类加载期织入,也简称为LTW(Load Time Weaving)。

跟进PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors 实例化并触发相关回调:

 public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any.
// 优先触发BeanDefinitionRegistryPostProcessor类型bean, 纪录已经触发回调的beanName
Set<String> processedBeans = new HashSet<String>(); // 1、容器需要具备BeanDefinitionRegistry功能, beanFactoryPostProcessors集合中为容器自身注册的实例, 已知实例集合
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>(); // 1.1、优先触发已知实例集合beanFactoryPostProcessors 中 BeanDefinitionRegistryPostProcessor实例
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
} /**
* 1.2、 从beanFactory容器中,获取已经加载的BeanDefinitionRegistryPostProcessor实例,并触发回调
*
* 1.2.1、不会实例化FactoryBeans, 而是留到工厂后置类进行处理. 通过beanFactory.getBeanNamesForType 参数 allowEagerInit 为false控制
* 1.2.2、严格遵循顺序, 触发顺序为实现PriorityOrdered->实现Ordered->普通类型接口
* 1.2.3、同PriorityOrdered、Ordered则以getOrder()返回值排序, 越小优先级别越高
*/
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>(); // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 纪录已触发实例beanName
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear(); // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear(); // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
} // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 1.3、触发所有BeanDefinitionRegistryPostProcessor实例的 postProcessBeanFactory 回调
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 1.4、触发所有BeanFactoryPostProcessor实例的 postProcessBeanFactory 回调
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
} else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
} /**
* 2、 从beanFactory容器中,获取已经加载的BeanFactoryPostProcessor实例,并触发回调
*
* 2.1、不会实例化FactoryBeans, 而是留到工厂后置类进行处理. 通过beanFactory.getBeanNamesForType 参数 allowEagerInit 为false控制
* 2.2、严格遵循顺序, 触发顺序为实现PriorityOrdered->实现Ordered->普通类型接口
* 2.3、同PriorityOrdered、Ordered则以getOrder()返回值排序, 越小优先级别越高
*/
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
} // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); // Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}

对应的触发和排序源码:

 private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
Comparator<Object> comparatorToUse = null;
if (beanFactory instanceof DefaultListableBeanFactory) {
comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
}
if (comparatorToUse == null) {
comparatorToUse = OrderComparator.INSTANCE;
}
postProcessors.sort(comparatorToUse);
} /**
* Invoke the given BeanDefinitionRegistryPostProcessor beans.
*/
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) { for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
} /**
* Invoke the given BeanFactoryPostProcessor beans.
*/
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) { for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}

spring源码分析系列 (1) spring拓展接口BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor的更多相关文章

  1. spring源码分析系列 (3) spring拓展接口InstantiationAwareBeanPostProcessor

    更多文章点击--spring源码分析系列 主要分析内容: 一.InstantiationAwareBeanPostProcessor简述与demo示例 二.InstantiationAwareBean ...

  2. spring源码分析系列 (5) spring BeanFactoryPostProcessor拓展类PropertyPlaceholderConfigurer、PropertySourcesPlaceholderConfigurer解析

    更多文章点击--spring源码分析系列 主要分析内容: 1.拓展类简述: 拓展类使用demo和自定义替换符号 2.继承图UML解析和源码分析 (源码基于spring 5.1.3.RELEASE分析) ...

  3. spring源码分析系列 (2) spring拓展接口BeanPostProcessor

    Spring更多分析--spring源码分析系列 主要分析内容: 一.BeanPostProcessor简述与demo示例 二.BeanPostProcessor源码分析:注册时机和触发点 (源码基于 ...

  4. 【Spring源码分析系列】ApplicationContext 相关接口架构分析

    [原创文章,转载请注明出处][本文地址]http://www.cnblogs.com/zffenger/p/5813470.html 在使用Spring的时候,我们经常需要先得到一个Applicati ...

  5. spring源码分析系列

    spring源码分析系列 (1) spring拓展接口BeanFactoryPostProcessor.BeanDefinitionRegistryPostProcessor spring源码分析系列 ...

  6. spring源码分析系列 (8) FactoryBean工厂类机制

    更多文章点击--spring源码分析系列 1.FactoryBean设计目的以及使用 2.FactoryBean工厂类机制运行机制分析 1.FactoryBean设计目的以及使用 FactoryBea ...

  7. spring源码分析系列 (15) 设计模式解析

    spring是目前使用最为广泛的Java框架之一.虽然spring最为核心是IOC和AOP,其中代码实现中很多设计模式得以应用,代码看起来简洁流畅,在日常的软件设计中很值得借鉴.以下是对一些设计模式的 ...

  8. 【Spring源码分析系列】启动component-scan类扫描加载过程

    原文地址:http://blog.csdn.net/xieyuooo/article/details/9089441/ 在spring 3.0以上大家都一般会配置一个Servelet,如下所示: &l ...

  9. spring源码分析系列3:BeanFactory核心容器的研究

    目录 @(spring源码分析系列3:核心容器的研究) 在讲容器之前,再明确一下知识点. BeanDefinition是Bean在容器的描述.BeanDefinition与Bean不是一个东西. Be ...

随机推荐

  1. centos中进程管理工具

    进程管理:  二进制的格式为ELF,是CPU指令集中的指令  程序=指令+数据,  进程是程序的副本,可以有多个  内核是一个资源调度监视器  Linux是抢占式多任务  内存被事先划分成多个相同大小 ...

  2. 篮球弹起问题(for循环)

  3. myEclipse配置java版本(环境、项目、编译)

    从别的地方导入一个项目的时候,经常会遇到eclipse/Myeclipse报Description  Resource Path Location Type Java compiler level d ...

  4. jdk提供的数组扩容方法:System.arraycopy

    package chapter7; /* * jdk提供的扩容方法 * System.arraycopy */public class TestArrayjdk { public static voi ...

  5. 2018-2019 2 20165203 《网络对抗技术》Exp6 信息搜集与漏洞扫描

    2018-2019 2 20165203 <网络对抗技术>Exp6 信息搜集与漏洞扫描 实践目标 掌握信息搜集的最基础技能与常用工具的使用方法. 实践内容 (1)各种搜索技巧的应用 (2) ...

  6. 【C++ Primer 第7章】定义抽象数据类型

    参考资料 1. C++Primer #7 类 Sales_data类 Sales_data.h #include<iostream> #include<string> clas ...

  7. 超实用!!!使用IDEA插件Alibaba Cloud Toolkit工具一键部署本地应用到ECS服务器

    最近看到阿里云发布了一款名为 Alibaba Cloud Toolkit 的插件,可以帮助开发者高效开发并部署适合在云端运行的应用,瞬间击中了我的小心脏,这个对于个人开发者来说超级棒啊,终于不需要再手 ...

  8. HDU5730

    cdq分治+FFT 转移:dp[i]=Σdp[i-j]*a[j](1<=j<=i)

  9. P1197 [JSOI2008]星球大战 并查集 反向

    题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧 ...

  10. 神舟战神 HotKey 主面板无法打开? Fn+Esc失效?

    战神笔记本的 Fn+Esc快捷键是打开 HotKey 主面板的, 其实就是  Control Center Windows更新可能导致 Control Center 无法打开,解决办法就是   更新驱 ...