Skip to content

Commit 1977910

Browse files
authored
Create ConfigurationClassPostProcessor.txt
1 parent 0ebf98f commit 1977910

File tree

1 file changed

+229
-0
lines changed

1 file changed

+229
-0
lines changed
+229
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
ConfigurationClassPostProcessor
2+
3+
4+
@Override
5+
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
6+
... // 忽略不必要的代码
7+
8+
processConfigBeanDefinitions(registry);
9+
}
10+
11+
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
12+
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
13+
// 从当前beandifinition注册表中取出所有的候选类,这里面有很多都是spring 的内置bean ,所以这些不需要处理。
14+
String[] candidateNames = registry.getBeanDefinitionNames();
15+
16+
for (String beanName : candidateNames) {
17+
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
18+
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
19+
if (logger.isDebugEnabled()) {
20+
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
21+
}
22+
}
23+
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
24+
// 将不是spring 的内置bean 取出来。这里的判断条件是有注解@Configuration 所标识的类才会被识别并添加。
25+
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
26+
}
27+
}
28+
29+
// Return immediately if no @Configuration classes were found
30+
if (configCandidates.isEmpty()) {
31+
return;
32+
}
33+
34+
// 支持@Order 注解,以及Ordered 接口,排序能力。
35+
// Sort by previously determined @Order value, if applicable
36+
configCandidates.sort((bd1, bd2) -> {
37+
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
38+
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
39+
return Integer.compare(i1, i2);
40+
});
41+
42+
// Detect any custom bean name generation strategy supplied through the enclosing application context
43+
// 是否有用户自定义的spring bean name 的生成器,如果有就取出使用。
44+
SingletonBeanRegistry sbr = null;
45+
if (registry instanceof SingletonBeanRegistry) {
46+
sbr = (SingletonBeanRegistry) registry;
47+
if (!this.localBeanNameGeneratorSet) {
48+
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
49+
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
50+
if (generator != null) {
51+
this.componentScanBeanNameGenerator = generator;
52+
this.importBeanNameGenerator = generator;
53+
}
54+
}
55+
}
56+
57+
if (this.environment == null) {
58+
this.environment = new StandardEnvironment();
59+
}
60+
61+
// Parse each @Configuration class
62+
// 构建出一个解析器,对前面使用@Configuration 标识的类,进行解析。
63+
ConfigurationClassParser parser = new ConfigurationClassParser(
64+
this.metadataReaderFactory, this.problemReporter, this.environment,
65+
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
66+
67+
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
68+
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
69+
do {
70+
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
71+
// 解析动作,进去。
72+
parser.parse(candidates);
73+
parser.validate();
74+
75+
... // 后面的没有详细看,但核心功能不在这里面,基本都是跳过的。
76+
}
77+
while (!candidates.isEmpty());
78+
79+
... // 不太关心的代码。
80+
}
81+
82+
83+
ConfigurationClassParser
84+
85+
public void parse(Set<BeanDefinitionHolder> configCandidates) {
86+
for (BeanDefinitionHolder holder : configCandidates) {
87+
BeanDefinition bd = holder.getBeanDefinition();
88+
try {
89+
if (bd instanceof AnnotatedBeanDefinition) {
90+
// 基本都是走的这一条分支,但是这三个分支,最终调用的都是同一个方法 processConfigurationClass(..)
91+
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
92+
}
93+
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
94+
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
95+
}
96+
else {
97+
parse(bd.getBeanClassName(), holder.getBeanName());
98+
}
99+
}
100+
catch (BeanDefinitionStoreException ex) {
101+
throw ex;
102+
}
103+
catch (Throwable ex) {
104+
throw new BeanDefinitionStoreException(
105+
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
106+
}
107+
}
108+
109+
// 这里是一个后置处理,前端的逻辑会为其填充基本数据,在这里做实际的动作。
110+
this.deferredImportSelectorHandler.process();
111+
}
112+
113+
114+
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
115+
// 是否添加了@Conditional 注解,并校验。
116+
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
117+
return;
118+
}
119+
120+
... // 这些不关心
121+
122+
// Recursively process the configuration class and its superclass hierarchy.
123+
SourceClass sourceClass = asSourceClass(configClass, filter);
124+
do {
125+
// 关键在这里
126+
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
127+
}
128+
while (sourceClass != null);
129+
130+
this.configurationClasses.put(configClass, configClass);
131+
}
132+
133+
// 处理配置类的解析工作
134+
protected final SourceClass doProcessConfigurationClass(
135+
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
136+
throws IOException {
137+
138+
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
139+
// Recursively process any member (nested) classes first
140+
// 这里并不重要,因为基本没人这么实现
141+
// 它会检查当前类里面的内部类,对该内部类也要进行解析。
142+
// 如果有,那最终也会在某个位置递归到当前方法来的。
143+
processMemberClasses(configClass, sourceClass, filter);
144+
}
145+
146+
// Process any @PropertySource annotations
147+
// 对存在注解@PropertySource 的类进行解析,并处理对应的逻辑
148+
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
149+
sourceClass.getMetadata(), PropertySources.class,
150+
org.springframework.context.annotation.PropertySource.class)) {
151+
if (this.environment instanceof ConfigurableEnvironment) {
152+
processPropertySource(propertySource);
153+
}
154+
else {
155+
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
156+
"]. Reason: Environment must implement ConfigurableEnvironment");
157+
}
158+
}
159+
160+
// Process any @ComponentScan annotations
161+
// 对存在注解@ComponentScan 的类进行解析,并处理对应的逻辑
162+
// 对于spring-boot 应用这里是很关键的一点,@SpringBootApplication 的解析,这里就是入口。
163+
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
164+
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
165+
if (!componentScans.isEmpty() &&
166+
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
167+
for (AnnotationAttributes componentScan : componentScans) {
168+
// The config class is annotated with @ComponentScan -> perform the scan immediately
169+
// 这里将对应的扫描包路径下面的所有被识别为Bean 的Class 都解析出来,并将其相关的信息封闭到BeanDefinition 中,最终包装到BeanDefinitionHolder 中。
170+
Set<BeanDefinitionHolder> scannedBeanDefinitions =
171+
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
172+
// Check the set of scanned definitions for any further config classes and parse recursively if needed
173+
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
174+
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
175+
if (bdCand == null) {
176+
bdCand = holder.getBeanDefinition();
177+
}
178+
// 如果对应的Class 被注解@Configuration 标识,那么会递归调用 parse(..) 方法,继续处理。
179+
// 我们要知道:当前方法也是从某个 parse(..) 方法调用进来的。
180+
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
181+
parse(bdCand.getBeanClassName(), holder.getBeanName());
182+
}
183+
}
184+
}
185+
}
186+
187+
// Process any @Import annotations
188+
// 处理@Import 注解
189+
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
190+
191+
// Process any @ImportResource annotations
192+
// 处理@ImportResource 注解
193+
AnnotationAttributes importResource =
194+
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
195+
if (importResource != null) {
196+
String[] resources = importResource.getStringArray("locations");
197+
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
198+
for (String resource : resources) {
199+
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
200+
configClass.addImportedResource(resolvedResource, readerClass);
201+
}
202+
}
203+
204+
// Process individual @Bean methods
205+
// 对@Bean 注解标注的方法的处理
206+
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
207+
for (MethodMetadata methodMetadata : beanMethods) {
208+
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
209+
}
210+
211+
// Process default methods on interfaces
212+
// 对于jdk 1.8 之后,接口上面也有默认方法的实现,对这些方法的处理。
213+
processInterfaces(configClass, sourceClass);
214+
215+
// Process superclass, if any
216+
// 处理父类的
217+
if (sourceClass.getMetadata().hasSuperClass()) {
218+
String superclass = sourceClass.getMetadata().getSuperClassName();
219+
if (superclass != null && !superclass.startsWith("java") &&
220+
!this.knownSuperclasses.containsKey(superclass)) {
221+
this.knownSuperclasses.put(superclass, configClass);
222+
// Superclass found, return its annotation metadata and recurse
223+
return sourceClass.getSuperClass();
224+
}
225+
}
226+
227+
// No superclass -> processing is complete
228+
return null;
229+
}

0 commit comments

Comments
 (0)