org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
本次来探讨下spring是如何解析配置类(即添加了@Configuration的类)
一、环境搭建
POM文件依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.szyrm</groupId>
<artifactId>spring-source</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<spring-version>5.2.5.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
</project>
二、测试
1、POJO类
package cn.szyrm.spring;
/**
* 这个类在演示中,我们将会通过用配置
* 在标注有@Bean方法进行配置
*/
public class Car {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2、配置类
@Configuration
public class AppConfig {
@Bean
public Car car(){
return new Car();
}
}
3、启动测试类
public class ApplicationTest {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext (AppConfig.class);
Car car = context.getBean(Car.class);
Assert.notNull(car,"容器中未查询到对应bean");
}
}
4、运行ApplicationTest 类,发现没有异常。说明已经正确配置
三、源码解读
1、一步一步查找源码入口
这里我们既然是查看怎么解析Configuration配置类
-
1)我们使用全局搜索
Configuration.class发现有如下地方使用:

-
2)、通过上面的搜索,发现是通过
org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry,java.lang.Object)注入到spring中的。 -
3)、搜索上面方法的调用位置

-
4)、查看具体调用的位置

- 5)、追溯到最终调用的位置

通过上面的分析,我们发现往spring 容器中注册了ConfigurationClassPostProcessor 这个工厂后置处理器,那么我们可以借助IDEA工具来查找spring 具体是什么时候实例这个对象?以及实例化该对象后所做的事情?
-
6)、在
ConfigurationClassPostProcessor类声明上添加断点 -
7)、以debug模式启动main方法

这里补充一个知识点,从ConfigurationClassPostProcessor定义可以看出其实现了BeanDefinitionRegistryPostProcessor,那么在初始化完成后,就会调用接口中的相应方法进行处理。下面我们来通过源码进行追踪下。

8)、postProcessBeanDefinitionRegistry 方法的调用
由于该后置处理器同时实现了PriorityOrdered接口,所有会被最先调用。

org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors 方法就会调用我们要继续调用的方法:org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry 。

/**
* Derive further bean definitions from the configuration classes in the registry.
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
9)、postProcessBeanFactory 方法调用


2、核心类方法解析
1)、processConfigBeanDefinitions(registry)方法解读
/**
* Build and validate a configuration model based on the registry of
* {@link Configuration} classes.
*/
public void processConfigBeanDefinitions

本文深入探讨Spring框架如何解析带有@Configuration注解的配置类,详细分析ConfigurationClassPostProcessor的作用及其实现过程,包括解析配置类、注册Bean定义和处理各种注解如@PropertySource、@ComponentScan、@Import等。
最低0.47元/天 解锁文章
2520

被折叠的 条评论
为什么被折叠?



