【SpringBoot源码分析】-Bean的加载过程(2)

通过BeanFactoryPostProcessor加载所有的类

提示:

下文中所提到的"BeanFactoryPostProcessor",均表示类型为BeanFactoryPostProcessor的接口统称,包括了它的扩展接口BeanDefinitionRegistryPostProcessor以及他们的实现类。

invokeBeanFactoryPostProcessors()方法是加载并调用所有的BeanFactoryProcessor,我们在前面的文章中已经详细介绍了它的执行流程和业务细节,不明白的同学可以再去回顾一下SpringBoot启动过程的分析-刷新ApplicationContext。这里再重申一下有关于BeanFactoryPostProcessor的相关概念。加强了这些概念,后续对其他代码的理解也会更容易。

BeanFactoryPostProcessor,是Spring内部诸多PostProcessor中的一种,注意它的前缀名称为BeanFactory,Bean工厂意味着它可以创建Bean,根据它的注释描述可以得知它可以修改Bean的定义,也可以修改Bean的属性值,但是它只能用于处理BeanDefinition,而不能处理Bean的实例。简单说就是,它可以在类实例化之前去修改它。另外一个BeanDefinitionRegistryPostProcessor它继承了BeanFactoryPostProcessor,对其进行了扩展,主要用于修改上下文中的Bean定义,加载所有常规的Bean,添加Bean。简单点理解就是它要比BeanFactoryPostProcessor更先执行。主要用于注册Bean。

在调用AbstractApplicationContext.invokeBeanFactoryPostProcessors()方法的时候需要注意它传入的BeanFactoryPostProcessor参数,具体可以看代码:


// AbstractApplicationContext.java

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {

// ①

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

// ...省略部分代码

}

public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {

return this.beanFactoryPostProcessors;

}

① - 这里需要注意传入的参数,它由getBeanFactoryPostProcessors()方法提供,而这个方法返回的是AbstractApplicationContext.beanFactoryPostProcessor这个属性值。这个属性内部所定义的BeanFactoryPostProcessor都是在ApplicationContextInitializer的扩展中添加进来的,而创建上下文容器时添加的内部的处理器则存放在DefaultListableBeanFactory.beanDefinitionNames这个属性中。所以在处理BeanFactoryPostProcessor的时候首先处理的是ApplicationContextInitializer中的内容。

通过两处不同的BeanFactoryPostProcessor可以反推出BeanFactoryPostProcessor初始化的两种方式:

通过ConfigurableApplicationContext.addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor)来添加

通过BeanDefinitionRegistry.registerBeanDefinition(String beanName, BeanDefinition beanDefinition)来注册一个Bean

本文的重点是分析Bean加载,此处对于BeanFactoryPostProcessor的植入涉及到另外一个课题:Spring框架的扩展点。对扩展点的分析此处先占位,有兴趣可以查看SpringFramework的扩展点

实际上对于Bean加载不光包括我们自己编写的业务代码,也包括SpringBoot自己的其他组件。因为BeanFactoryPostProcessor本身也是一个类。他们在ApplicationContextInitializer接口中被添加,或是在BeanDefinitionRegistry中被注册。区别就是一个是直接添加实例,一个是注册BeanDefinition。言归正传回到Bean的加载中来;此处对于通过ApplicationContextInitializer接口中被添加的BeanFactoryPostProcessor不作分析,因为代码比较简洁,他们本身也没涉及过多的操作,感兴趣的可以自己debug。这里重点分析通过BeanDefinitionRegistry注册的BeanFactoryPostProcessor即DefaultListableBeanFactory.beanDefinitionNames这个属性中注册的类。内置的BeanFactoryPostProcessor是在容器创建的时候加入的,可参考之前的分析注册内定的BeanFactoryPostProcessor。

org.springframework.context.annotation.ConfigurationClassPostProcessor

org.springframework.context.event.DefaultEventListenerFactory

org.springframework.context.event.EventListenerMethodProcessor

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor

经过查看这些内置的类,只有ConfigurationClassPostProcessor和类加载相关。

ConfigurationClassPostProcessor

主要用于对@Configuration注解进行处理。在SpringBoot应用中,往往都是从一个Main函数开始,启动类上面也必须使用@SpringBootApplication注解来标明它的身份;因此@Configuration注解也代表着应用的起点;因在BeanFactoryPostProcessor被调用的时候是按照优先级来的,首先被调用的是BeanDefinitionRegistryPostProcessor,所以首先执行postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法。

// ConfigurationClassPostProcessor.java

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);

}

① - 获取注册ID

② - 判断当前Processor是否被执行过

③ - 添加到已处理列表

④ - 处理配置相关的BeanDefinition


public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {

List<BeanDefinitionHolder> configCandidates = new ArrayList<>();

// 获取所有已注册的BeanDefinition,寻找具有@Configuration注解的类

String[] candidateNames = registry.getBeanDefinitionNames();

// 遍历所有的beanName

for (String beanName : candidateNames) {

// 根据名称找到BeanDefinition

BeanDefinition beanDef = registry.getBeanDefinition(beanName);

// 判断当前类是Full模式还是Lite模式,就为了打印个日志?No,查看日志内容,打印的是:当前类已经被当做一个configuration类被处理过。

// 那就意味着默认情况下它是没有设置ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE 这个属性的。

if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {

if (logger.isDebugEnabled()) {

logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);

}

}

// 判断当前处理的类是不是完整的配置类,也就是是否被@Configuration注解修饰,若被修饰则会给当前的BeanDefinition设置一个attribute(org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass = full)

else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {

// 加入配置候选列表

configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));

}

}

// 若没有被@Configuration注解的类,直接返回

// Return immediately if no @Configuration classes were found

if (configCandidates.isEmpty()) {

return;

}

// 根据优先级排序

// Sort by previously determined @Order value, if applicable

configCandidates.sort((bd1, bd2) -> {

int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());

int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());

return Integer.compare(i1, i2);

});

// 设置BeanNameGenerator用于生成稍后检测到的Bean的名称

// Detect any custom bean name generation strategy supplied through the enclosing application context

SingletonBeanRegistry sbr = null;

if (registry instanceof SingletonBeanRegistry) {

sbr = (SingletonBeanRegistry) registry;

if (!this.localBeanNameGeneratorSet) {

BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);

if (generator != null) {

this.componentScanBeanNameGenerator = generator;

this.importBeanNameGenerator = generator;

}

}

}

if (this.environment == null) {

this.environment = new StandardEnvironment();

}

// 新建一个配置类解析器,用于解析所有@Configuration注解的类

// Parse each @Configuration class

ConfigurationClassParser parser = new ConfigurationClassParser(

this.metadataReaderFactory, this.problemReporter, this.environment,

this.resourceLoader, this.componentScanBeanNameGenerator, registry);

// 将要被解析的配置类

Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);

// 已经被解析的配置类

Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());

do {

// ① 开始解析配置类

parser.parse(candidates);

parser.validate();

// ② 获取解析到的配置类

Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());

configClasses.removeAll(alreadyParsed);

// ③ 构建Reader对象,为加载Bean做准备 Read the model and create bean definitions based on its content

if (this.reader == null) {

this.reader = new ConfigurationClassBeanDefinitionReader(

registry, this.sourceExtractor, this.resourceLoader, this.environment,

this.importBeanNameGenerator, parser.getImportRegistry());

}

// ④ 从配置类开始加载Bean

this.reader.loadBeanDefinitions(configClasses);

alreadyParsed.addAll(configClasses);

candidates.clear();

if (registry.getBeanDefinitionCount() > candidateNames.length) {

String[] newCandidateNames = registry.getBeanDefinitionNames();

Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));

Set<String> alreadyParsedClasses = new HashSet<>();

for (ConfigurationClass configurationClass : alreadyParsed) {

alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());

}

for (String candidateName : newCandidateNames) {

if (!oldCandidateNames.contains(candidateName)) {

BeanDefinition bd = registry.getBeanDefinition(candidateName);

if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&

!alreadyParsedClasses.contains(bd.getBeanClassName())) {

candidates.add(new BeanDefinitionHolder(bd, candidateName));

}

}

}

candidateNames = newCandidateNames;

}

}

while (!candidates.isEmpty());

// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes

if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {

sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());

}

if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {

// Clear cache in externally provided MetadataReaderFactory; this is a no-op

// for a shared cache since it'll be cleared by the ApplicationContext.

((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();

}

}

根据上面的void processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法中的do-while循环可以看到,它内部是按照解析@Configuration->取出@Configuration->构建BeanDefinitionReader->从@Configuration读取BeanDefinition的流程来完成类的加载。

开始解析@Configuration类

@Configuration注解是Spring中基于Java配置容器中的一个注解,属于类级别的注解,它主要用于标明一组@Bean定义的来源。通常@Configuration和@Bean同时使用。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

// ConfigurationClassParser.java

public void parse(Set<BeanDefinitionHolder> configCandidates) {

// 遍历所有具有@Configuration注解的类

for (BeanDefinitionHolder holder : configCandidates) {

BeanDefinition bd = holder.getBeanDefinition();

try {

if (bd instanceof AnnotatedBeanDefinition) {

// 解析AnnotatedBeanDefinition类型的配置类(可以获取类的注解元数据)

parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());

}

else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {

parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());

}

else {

parse(bd.getBeanClassName(), holder.getBeanName());

}

}

catch (BeanDefinitionStoreException ex) {

throw ex;

}

catch (Throwable ex) {

throw new BeanDefinitionStoreException(

"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);

}

}

this.deferredImportSelectorHandler.process();

}

// 包装为ConfigurationClass对象

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {

processConfigurationClass(new ConfigurationClass(metadata, beanName));

}

// 判断是否已经执行过

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {

if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {

return;

}

ConfigurationClass existingClass = this.configurationClasses.get(configClass);

if (existingClass != null) {

if (configClass.isImported()) {

if (existingClass.isImported()) {

existingClass.mergeImportedBy(configClass);

}

// Otherwise ignore new imported config class; existing non-imported class overrides it.

return;

}

else {

// Explicit bean definition found, probably replacing an import.

// Let's remove the old one and go with the new one.

this.configurationClasses.remove(configClass);

this.knownSuperclasses.values().removeIf(configClass::equals);

}

}

// 包装为SourceClass便于统一处理

// Recursively process the configuration class and its superclass hierarchy.

SourceClass sourceClass = asSourceClass(configClass);

do {

// 这里才开始处理配置类

sourceClass = doProcessConfigurationClass(configClass, sourceClass);

}

while (sourceClass != null);

this.configurationClasses.put(configClass, configClass);

}

// 真正开始处理配置的方法

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)

throws IOException {

// 优先处理@Component注解

if (configClass.getMetadata().isAnnotated(Component.class.getName())) {

// 递归处理

// Recursively process any member (nested) classes first

processMemberClasses(configClass, sourceClass);

}

// 处理@PropertySource注解

// Process any @PropertySource annotations

for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(

sourceClass.getMetadata(), PropertySources.class,

org.springframework.context.annotation.PropertySource.class)) {

if (this.environment instanceof ConfigurableEnvironment) {

processPropertySource(propertySource);

}

else {

logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +

"]. Reason: Environment must implement ConfigurableEnvironment");

}

}

// 处理@ComponentScan注解

// Process any @ComponentScan annotations

Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(

sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);

if (!componentScans.isEmpty() &&

!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {

for (AnnotationAttributes componentScan : componentScans) {

// The config class is annotated with @ComponentScan -> perform the scan immediately

Set<BeanDefinitionHolder> scannedBeanDefinitions =

this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

// Check the set of scanned definitions for any further config classes and parse recursively if needed

for (BeanDefinitionHolder holder : scannedBeanDefinitions) {

BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();

if (bdCand == null) {

bdCand = holder.getBeanDefinition();

}

if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {

parse(bdCand.getBeanClassName(), holder.getBeanName());

}

}

}

}

// 处理@Import注解

// Process any @Import annotations

processImports(configClass, sourceClass, getImports(sourceClass), true);

// 处理@ImportResource注解

// Process any @ImportResource annotations

AnnotationAttributes importResource =

AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);

if (importResource != null) {

String[] resources = importResource.getStringArray("locations");

Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");

for (String resource : resources) {

String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);

configClass.addImportedResource(resolvedResource, readerClass);

}

}

// 处理单个@Bean方法

// Process individual @Bean methods

Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);

for (MethodMetadata methodMetadata : beanMethods) {

configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));

}

// 处理接口默认方法

// Process default methods on interfaces

processInterfaces(configClass, sourceClass);

// 处理父类的方法

// Process superclass, if any

if (sourceClass.getMetadata().hasSuperClass()) {

String superclass = sourceClass.getMetadata().getSuperClassName();

if (superclass != null && !superclass.startsWith("java") &&

!this.knownSuperclasses.containsKey(superclass)) {

this.knownSuperclasses.put(superclass, configClass);

// Superclass found, return its annotation metadata and recurse

return sourceClass.getSuperClass();

}

}

// No superclass -> processing is complete

return null;

}

@Configuration配置类同时也和其他注解有关联,这里说的关联是其他注解的行为会影响配置类本身的状态。例如方法中提到的@Component、@ComponentScan、@PropertySource、@Import、@Bean、@ImportResource。

处理@Component注解

@Component注解表示被修饰的类将会被识别为受Spring管理的类。将会被注册到Bean容器中。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {

// 获取成员类

Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();

if (!memberClasses.isEmpty()) {

List<SourceClass> candidates = new ArrayList<>(memberClasses.size());

for (SourceClass memberClass : memberClasses) {

// 判断是否有@Configuration或者@Component注解

if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) && !memberClass.getMetadata().getC

lassName().equals(configClass.getMetadata().getClassName())) {

candidates.add(memberClass);

}

}

// 排序

OrderComparator.sort(candidates);

// 检测是否有循环导入(@Import)的问题

for (SourceClass candidate : candidates) {

if (this.importStack.contains(configClass)) {

this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));

}

else {

this.importStack.push(configClass);

try {

// 递归调用处理

processConfigurationClass(candidate.asConfigClass(configClass));

}

finally {

this.importStack.pop();

}

}

}

}

}

在该方法中,主要用于处理当前传入的configClass内部的嵌套类、成员类中是否有@Configuration、@Component注解。一般来说@Configuratio

n都是单独使用的一个类。

处理@PropertySource注解

@PropertySource注解用于加载指定的properties配置文件到Spring的Environment中

1

2

3

4

5

6

7

8

9

10

// 内部实现比较简单,自行debug即可

for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) {

// 判断当前环境对象是否是可配置的

if (this.environment instanceof ConfigurableEnvironment) {

processPropertySource(propertySource);

}

else {

logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment");

}

}

处理@ComponentScan注解

@ComponentScan注解用于指明当前应用将扫描哪些包下的具有@Component注解的类。这个注解必须添加到@Configuration类中

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

// 根据ComponentScans配置的包路径查找带@Component注解的类

Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);

if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {

// 获取所有带@Component注解的类

for (AnnotationAttributes componentScan : componentScans) {

// The config class is annotated with @ComponentScan -> perform the scan immediately

Set<BeanDefinitionHolder> scannedBeanDefinitions =

this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

// Check the set of scanned definitions for any further config classes and parse recursively if needed

for (BeanDefinitionHolder holder : scannedBeanDefinitions) {

BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();

if (bdCand == null) {

bdCand = holder.getBeanDefinition();

}

if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {

parse(bdCand.getBeanClassName(), holder.getBeanName());

}

}

}

}

这里重点分析它是如何查找@ComponentScans注解的,跳过无用的调用链,查看真正开始查找的方法。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

// AnnotationConfigUtils.java

// 需要注意的是参数:metadata代表从哪里获取,containerClassName表示包含注解(例如@ComponentScans,它本身的值可以包含多个@ComponentScan),annotationClassName是当前要获取的目标注解也就是@ComponentScan

static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata, String containerClassName, String annotationClassName) {

Set<AnnotationAttributes> result = new LinkedHashSet<>();

// ①

// Direct annotation present?

addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName, false));

// ②

// Container annotation present?

Map<String, Object> container = metadata.getAnnotationAttributes(containerClassName, false);

if (container != null && container.containsKey("value")) {

for (Map<String, Object> containedAttributes : (Map<String, Object>[]) container.get("value")) {

addAttributesIfNotNull(result, containedAttributes);

}

}

// Return merged result

return Collections.unmodifiableSet(result);

}

提示:

在这个方法内部分了两个操作,第一个是直接获取@ComponentScan这个注解,第二个是获取@ComponentScans注解。这两者是有区别的。

① - 此处为@ComponentScan,称之为直接注解”,即在类上面直接声明的注解。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

// StandardAnnotationMetadata.class

public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {

return (this.annotations.length > 0 ? AnnotatedElementUtils.getMergedAnnotationAttributes(getIntrospectedClass(), annotationName, classValuesAsString, this.nestedAnnotationsAsMap) : null);

}

// AnnotatedElementUtils.class

public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element,

String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {

AnnotationAttributes attributes = searchWithGetSemantics(element, null, annotationName, new MergedAnnotationAttributesProcessor(classValuesAsString, nestedAnnotationsAsMap));

AnnotationUtils.postProcessAnnotationAttributes(element, attributes, classValuesAsString, nestedAnnotationsAsMap);

return attributes;

}

// 通过一系列的重载方法,最终调用此方法

private static <T> T searchWithGetSemantics(AnnotatedElement element,

Set<Class<? extends Annotation>> annotationTypes, @Nullable String annotationName,

@Nullable Class<? extends Annotation> containerType, Processor<T> processor,

Set<AnnotatedElement> visited, int metaDepth) {

if (visited.add(element)) {

try {

// Start searching within locally declared annotations

// 获取当前元素声明的所有注解

List<Annotation> declaredAnnotations = Arrays.asList(AnnotationUtils.getDeclaredAnnotations(element));

// 获取这些注解中指定的类型

T result = searchWithGetSemanticsInAnnotations(element, declaredAnnotations, annotationTypes, annotationName, containerType, processor, visited, metaDepth);

if (result != null) {

return result;

}

if (element instanceof Class) {  // otherwise getAnnotations doesn't return anything new

Class<?> superclass = ((Class<?>) element).getSuperclass();

if (superclass != null && superclass != Object.class) {

List<Annotation> inheritedAnnotations = new LinkedList<>();

for (Annotation annotation : element.getAnnotations()) {

if (!declaredAnnotations.contains(annotation)) {

inheritedAnnotations.add(annotation);

}

}

// Continue searching within inherited annotations

result = searchWithGetSemanticsInAnnotations(element, inheritedAnnotations,

annotationTypes, annotationName, containerType, processor, visited, metaDepth);

if (result != null) {

return result;

}

}

}

}

catch (Throwable ex) {

AnnotationUtils.handleIntrospectionFailure(element, ex);

}

}

return null;

}

private static <T> T searchWithGetSemanticsInAnnotations(@Nullable AnnotatedElement element,

List<Annotation> annotations, Set<Class<? extends Annotation>> annotationTypes,

@Nullable String annotationName, @Nullable Class<? extends Annotation> containerType,

Processor<T> processor, Set<AnnotatedElement> visited, int metaDepth) {

// 遍历所有注解

// Search in annotations

for (Annotation annotation : annotations) {

// 获取当前注解类型

Class<? extends Annotation> currentAnnotationType = annotation.annotationType();

if (!AnnotationUtils.isInJavaLangAnnotationPackage(currentAnnotationType)) {

// 判断是否处理过、当前注解的名称是否和将要查找的一致、是否默认处理(默认为true,请debug的时候注意传入的参数)

if (annotationTypes.contains(currentAnnotationType) || currentAnnotationType.getName().equals(annotationName) || processor.alwaysProcesses()) {

// 若匹配,则查找内部的注解属性

T result = processor.process(element, annotation, metaDepth);

if (result != null) {

if (processor.aggregates() && metaDepth == 0) {

processor.getAggregatedResults().add(result);

}

else {

return result;

}

}

}

// 如果没有找到

// Repeatable annotations in container?

else if (currentAnnotationType == containerType) {

for (Annotation contained : getRawAnnotationsFromContainer(element, annotation)) {

T result = processor.process(element, contained, metaDepth);

if (result != null) {

// No need to post-process since repeatable annotations within a

// container cannot be composed annotations.

processor.getAggregatedResults().add(result);

}

}

}

}

}

// Recursively search in meta-annotations

for (Annotation annotation : annotations) {

Class<? extends Annotation> currentAnnotationType = annotation.annotationType();

if (!AnnotationUtils.hasPlainJavaAnnotationsOnly(currentAnnotationType)) {

T result = searchWithGetSemantics(currentAnnotationType, annotationTypes, annotationName, containerType, processor, visited, metaDepth + 1);

if (result != null) {

processor.postProcess(element, annotation, result);

if (processor.aggregates() && metaDepth == 0) {

processor.getAggregatedResults().add(result);

}

else {

return result;

}

}

}

}

return null;

}

// AnnotatedElementUtils.class内部类AnnotatedElementUtils.class

public AnnotationAttributes process(@Nullable AnnotatedElement annotatedElement, Annotation annotation, int metaDepth) {

return AnnotationUtils.retrieveAnnotationAttributes(annotatedElement, annotation, this.classValuesAsString, this.nestedAnnotationsAsMap);

}

// AnnotationUtils.class

static AnnotationAttributes retrieveAnnotationAttributes(@Nullable Object annotatedElement,

Annotation annotation, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {

Class<? extends Annotation> annotationType = annotation.annotationType();

AnnotationAttributes attributes = new AnnotationAttributes(annotationType);

// 遍历注解的方法,获取属性名称和属性值,填充至AnnotationAttributes对象内部(实际上就是个Map)

for (Method method : getAttributeMethods(annotationType)) {

try {

Object attributeValue = method.invoke(annotation);

Object defaultValue = method.getDefaultValue();

if (defaultValue != null && ObjectUtils.nullSafeEquals(attributeValue, defaultValue)) {

attributeValue = new DefaultValueHolder(defaultValue);

}

attributes.put(method.getName(), adaptValue(annotatedElement, attributeValue, classValuesAsString, nestedAnnotationsAsMap));

}

catch (Throwable ex) {

if (ex instanceof InvocationTargetException) {

Throwable targetException = ((InvocationTargetException) ex).getTargetException();

rethrowAnnotationConfigurationException(targetException);

}

throw new IllegalStateException("Could not obtain annotation attribute value for " + method, ex);

}

}

return attributes;

}

② - 此处为@ComponentScans,称之为”容器注解”,它可以包含多个@ComponentScan,代码逻辑和获取直接注解@ComponentScan并没有太大差异,可自行debug

看到这里可以得出一个结论:有3种使用注解定义包扫描路径的方法

@SpringBootApplication(scanBasePackages = "com.example")

@ComponentScan(value = {"com.example"})

@ComponentScans({@ComponentScan("com.abcd"), @ComponentScan("com.efgh")})

注意:其中1和2是可以同时存在,1和3可以同时存在,2和3不可以同时存在

1、2同时存在只取2的值

1、3同时存在取1、3的值

处理到这一步,仅仅是获取到了所有的@ComponentScan注解,接下来还需要解析注解里面配置的包路径

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

// ConfigurationClassParser.class 284行

for (AnnotationAttributes componentScan : componentScans) {

// 解析当前注解配置的包路径下的类

// The config class is annotated with @ComponentScan -> perform the scan immediately

Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

// 检查返回的BeanDefinition里面是否有其他的配置类,如果需要的话会递归进行解析

// Check the set of scanned definitions for any further config classes and parse recursively if needed

for (BeanDefinitionHolder holder : scannedBeanDefinitions) {

BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();

if (bdCand == null) {

bdCand = holder.getBeanDefinition();

}

// 若是配置类,执行配置类的解析操作

if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {

parse(bdCand.getBeanClassName(), holder.getBeanName());

}

}

}

// 以下代码为获取BeanDefinition的具体流程

// ComponentScanAnnotationParser.class

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {

// 构建扫描器

ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

// 构建类名生成器

Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");

boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);

scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : BeanUtils.instantiateClass(generatorClass));

// 获取类的作用域模型

ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");

if (scopedProxyMode != ScopedProxyMode.DEFAULT) {

scanner.setScopedProxyMode(scopedProxyMode);

}

else {

Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");

scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));

}

// 获取资源模式(注解配置扫描包都是扫描class因此此处为:**/*.class)

scanner.setResourcePattern(componentScan.getString("resourcePattern"));

// 获取@ComponentScan注解里面配置的include过滤器

for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {

for (TypeFilter typeFilter : typeFiltersFor(filter)) {

scanner.addIncludeFilter(typeFilter);

}

}

// 获取@ComponentScan注解里面配置的exclude过滤器

for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {

for (TypeFilter typeFilter : typeFiltersFor(filter)) {

scanner.addExcludeFilter(typeFilter);

}

}

//  获取@ComponentScan注解里面配置的lazyInit值

boolean lazyInit = componentScan.getBoolean("lazyInit");

if (lazyInit) {

scanner.getBeanDefinitionDefaults().setLazyInit(true);

}

// 获取需要扫描的路径集合

Set<String> basePackages = new LinkedHashSet<>();

String[] basePackagesArray = componentScan.getStringArray("basePackages");

for (String pkg : basePackagesArray) {

String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

Collections.addAll(basePackages, tokenized);

}

for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {

basePackages.add(ClassUtils.getPackageName(clazz));

}

if (basePackages.isEmpty()) {

basePackages.add(ClassUtils.getPackageName(declaringClass));

}

scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {

@Override

protected boolean matchClassName(String className) {

return declaringClass.equals(className);

}

});

// 通过扫描器扫描指定路径下的具有@Component注解的类

return scanner.doScan(StringUtils.toStringArray(basePackages));

}

// ClassPathBeanDefinitionScanner.class

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {

Assert.notEmpty(basePackages, "At least one base package must be specified");

Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();

for (String basePackage : basePackages) {

// 查找所有@Component注解标识的类

Set<BeanDefinition> candidates = findCandidateComponents(basePackage);

for (BeanDefinition candidate : candidates) {

// 获取作用域元数据

ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);

candidate.setScope(scopeMetadata.getScopeName());

// 生成类名

String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);

// 对普通的Bean 进行处理

if (candidate instanceof AbstractBeanDefinition) {

postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);

}

// 对包含有注解的Bean进行处理,比如@Lazy、@Primary

if (candidate instanceof AnnotatedBeanDefinition) {

AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);

}

// 检查当前加载的Bean名称是否有冲突

if (checkCandidate(beanName, candidate)) {

BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);

definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

beanDefinitions.add(definitionHolder);

registerBeanDefinition(definitionHolder, this.registry);

}

}

}

return beanDefinitions;

}

// ClassPathScanningCandidateComponentProvider.class

public Set<BeanDefinition> findCandidateComponents(String basePackage) {

if (this.componentsIndex != null && indexSupportsIncludeFilters()) {

return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);

}

else {

// 真正开始搜索类的方法

return scanCandidateComponents(basePackage);

}

}

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {

Set<BeanDefinition> candidates = new LinkedHashSet<>();

try {

// 获取资源的路径

String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern;

// 获取所有资源

Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);

boolean traceEnabled = logger.isTraceEnabled();

boolean debugEnabled = logger.isDebugEnabled();

// 为每一个类生成BeanDefinition对象

for (Resource resource : resources) {

if (traceEnabled) {

logger.trace("Scanning " + resource);

}

if (resource.isReadable()) {

try {

MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);

// 判断是否具有@Component注解

if (isCandidateComponent(metadataReader)) {

ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);

sbd.setResource(resource);

sbd.setSource(resource);

if (isCandidateComponent(sbd)) {

if (debugEnabled) {

logger.debug("Identified candidate component class: " + resource);

}

candidates.add(sbd);

}

else {

if (debugEnabled) {

logger.debug("Ignored because not a concrete top-level class: " + resource);

}

}

}

else {

if (traceEnabled) {

logger.trace("Ignored because not matching any filter: " + resource);

}

}

}

catch (Throwable ex) {

throw new BeanDefinitionStoreException(

"Failed to read candidate component class: " + resource, ex);

}

}

else {

if (traceEnabled) {

logger.trace("Ignored because not readable: " + resource);

}

}

}

}

catch (IOException ex) {

throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);

}

return candidates;

}

至此,通过@ComponentScan注解配置扫描指定的包,到获取到具体的带有@Component注解的类已经全部获取完毕。

处理@Import注解

@Import注解主要用于引入另外一个@Configuration。和Spring XML配置文件中的标签功能一样。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

// ConfigurationClassParser.class 302行

// 处理@Import注解,请注意参数内部的getImports方法

processImports(configClass, sourceClass, getImports(sourceClass), true);

private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {

Set<SourceClass> imports = new LinkedHashSet<>();

Set<SourceClass> visited = new LinkedHashSet<>();

collectImports(sourceClass, imports, visited);

return imports;

}

// 递归获取@Import注解

private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited) throws IOException {

// 添加已处理的避免无限递归

if (visited.add(sourceClass)) {

// 获取传入资源上的注解列表

for (SourceClass annotation : sourceClass.getAnnotations()) {

// 获取注解名称

String annName = annotation.getMetadata().getClassName();

// 若当前注解不是@Import则递归查找

if (!annName.equals(Import.class.getName())) {

collectImports(annotation, imports, visited);

}

}

// 添加已经获取的所有注解

imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));

}

}

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, boolean checkForCircularImports) {

if (importCandidates.isEmpty()) {

return;

}

if (checkForCircularImports && isChainedImportOnStack(configClass)) {

this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));

}

else {

this.importStack.push(configClass);

try {

for (SourceClass candidate : importCandidates) {

// 是否是ImportSelector的实现

if (candidate.isAssignable(ImportSelector.class)) {

// Candidate class is an ImportSelector -> delegate to it to determine imports

Class<?> candidateClass = candidate.loadClass();

ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);

ParserStrategyUtils.invokeAwareMethods(selector, this.environment, this.resourceLoader, this.registry);

if (selector instanceof DeferredImportSelector) {

this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);

}

else {

String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());

Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);

processImports(configClass, currentSourceClass, importSourceClasses, false);

}

}

// 是否是ImportBeanDefinitionRegistrar的实现

else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {

// Candidate class is an ImportBeanDefinitionRegistrar ->

// delegate to it to register additional bean definitions

Class<?> candidateClass = candidate.loadClass();

ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);

ParserStrategyUtils.invokeAwareMethods(registrar, this.environment, this.resourceLoader, this.registry);

configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());

}

// 都不是的话把它当做@Configuration来处理

else {

// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->

// process it as an @Configuration class

this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());

// 将其作为@Configuration处理

processConfigurationClass(candidate.asConfigClass(configClass));

}

}

}

catch (BeanDefinitionStoreException ex) {

throw ex;

}

catch (Throwable ex) {

throw new BeanDefinitionStoreException(

"Failed to process import candidates for configuration class [" +

configClass.getMetadata().getClassName() + "]", ex);

}

finally {

this.importStack.pop();

}

}

}

processImports() 方法用于处理解析到的Import的类,分为3种类型"ImportSelector"的实现、"ImportBeanDefinitionRegistrar"的实现、"本身也是一个@Configuration"的实现。

ImporSelector的实现:

主要用于导入@Configuration配置类,并且可以实现EnvironmentAware、BeanFactoryAware、BeanClassLoaderAware、ResourceLoaderAware接口,并在调用ImportSelector.selectImports方法之前调用它们。

ImportBeanDefinitionRegistrar的实现:

用于导入导入@Configuration配置了,并可以注册BeanDefinition

@Configuration:

如果导入的是一个配置,则进入配置解析功能

处理@ImportResource注解

用于引入Spring xml配置文件,类似于Spring XML中的标签,默认使用XmlBeanDefinitionReader来解析XML中的标签。

例如:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

@Configuration

@ImportResource("classpath:/com/acme/properties-config.xml")

public class AppConfig {

    @Value("${jdbc.url}")

    private String url;

    @Value("${jdbc.username}")

    private String username;

    @Value("${jdbc.password}")

    private String password;

    @Bean

    public DataSource dataSource() {

        return new DriverManagerDataSource(url, username, password);

    }

}

源码解析:

1

2

3

4

5

6

7

8

9

10

11

12

13

AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);

if (importResource != null) {

// ①

String[] resources = importResource.getStringArray("locations");

// ②

Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");

for (String resource : resources) {

// ③

String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);

// ④

configClass.addImportedResource(resolvedResource, readerClass);

}

}

① - 获取@ImportResource注解的value值

② - 获取BeanDefinitionReader

③ - 处理资源路径下的占位符

④ - 将资源和对应的解析器存放至当前配置类的importedResources属性中,它是一个LinkedHashMap

处理@Bean注解

此处处理的是在配置类中具有@Bean注解的方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

// ①

Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);

for (MethodMetadata methodMetadata : beanMethods) {

// ②

configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));

}

// ④

private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {

for (SourceClass ifc : sourceClass.getInterfaces()) {

Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);

for (MethodMetadata methodMetadata : beanMethods) {

if (!methodMetadata.isAbstract()) {

// A default method or other concrete method on a Java 8+ interface...

configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));

}

}

processInterfaces(configClass, ifc);

}

}

// ⑤

if (sourceClass.getMetadata().hasSuperClass()) {

String superclass = sourceClass.getMetadata().getSuperClassName();

if (superclass != null && !superclass.startsWith("java") &&

!this.knownSuperclasses.containsKey(superclass)) {

this.knownSuperclasses.put(superclass, configClass);

// Superclass found, return its annotation metadata and recurse

return sourceClass.getSuperClass();

}

}

① - 获取所有具有@Bean注解的方法

② - 将获取到的方法包装为BeanMethod对象(表示一个具有@Bean注解的@Configuration类的方法)保存到当前配置类的beanMethods属性中

④ - 处理接口中具有@Bean注解的方法

⑤ - 处理父类中具有@Bean注解的方法

取出@Configuration

直接从Parser中取出之前解析时缓存的配置类,因为这段代码在do-while循环中,因此首先移除已处理的。

1

2

Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());

configClasses.removeAll(alreadyParsed);

构建BeanDefinitionReader

若Reader为空,则创建,用于读取配置中的BeanDefinition

1

2

3

4

5

if (this.reader == null) {

this.reader = new ConfigurationClassBeanDefinitionReader(

registry, this.sourceExtractor, this.resourceLoader, this.environment,

this.importBeanNameGenerator, parser.getImportRegistry());

}

@Configuration读取BeanDefinition

前面对各种注解的的解析最终并没有处理解析的结果,而是将其放在了ConfigurationClass对象的属性当中存储,在这里将通过Reader来处理这

些不同来源的BeanDefinition。

1

2

3

4

5

6

7

8

9

10

11

12

this.reader.loadBeanDefinitions(configClasses);

alreadyParsed.addAll(configClasses);

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {

TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();

// ①

for (ConfigurationClass configClass : configurationModel) {

// ②

loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);

}

}

① - 遍历所有的@Configuration

② - 从@Configuration读取BeanDefinition

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

// ①

if (trackedConditionEvaluator.shouldSkip(configClass)) {

String beanName = configClass.getBeanName();

if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {

this.registry.removeBeanDefinition(beanName);

}

this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());

return;

}

// ②

if (configClass.isImported()) {

registerBeanDefinitionForImportedConfigurationClass(configClass);

}

// ③

for (BeanMethod beanMethod : configClass.getBeanMethods()) {

loadBeanDefinitionsForBeanMethod(beanMethod);

}

// ④

loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());

// ⑤

loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());

}

① - 是否需要跳过

② - 当前配置类本身是否通过@Import导入,若有则将自身注册为BeanDefinition

③ - 当前配置类中是否有@Bean注解修饰的方法,若有则处理

④ - 加载从@ImportResource导入的XML文件中定义的Bean

⑤ - 加载从@Import导入的BeanDefinition

合并已处理的BeanDefinition

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

// ①

String[] candidateNames = registry.getBeanDefinitionNames();

if (registry.getBeanDefinitionCount() > candidateNames.length) {

// ②

String[] newCandidateNames = registry.getBeanDefinitionNames();

// ③

Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));

// ④

Set<String> alreadyParsedClasses = new HashSet<>();

// ⑤

for (ConfigurationClass configurationClass : alreadyParsed) {

alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());

}

// ⑥

for (String candidateName : newCandidateNames) {

// ⑦

if (!oldCandidateNames.contains(candidateName)) {

// ⑧

BeanDefinition bd = registry.getBeanDefinition(candidateName);

if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&

!alreadyParsedClasses.contains(bd.getBeanClassName())) {

candidates.add(new BeanDefinitionHolder(bd, candidateName));

}

}

}

// ⑨

candidateNames = newCandidateNames;

}

① - candidateNames 在方法的一开始就从registry中获取已经处理过的BeanDefinition名称

② - newCandidateNames 表示本次从配置类的解析中加载完毕BeanDefinition之后的BeanDefinition名称列表,它包含第一步里面的名称

③ - 将第一步的名称列表转换为Set集合

④ - 声明已解析的集合,此处用Set因为它可以保证元素不重复

⑤ - 遍历本次已经处理的所有类集合,将其加入第四步声明的Set集合内

⑥ - 遍历registry中现有的列表

⑦ - 当前的BeanDefinition必须是本次代码执行时加入的才进行处理

⑧ - 获取当前处理的类,判断是否为Configuration,并设置FULL模式和LITE模式

⑨ - 获取全部已经处理的类赋值给candidateNames

USB Microphone https://www.soft-voice.com/

Wooden Speakers  https://www.zeshuiplatform.com/

亚马逊测评 www.yisuping.cn

深圳网站建设www.sz886.com

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,348评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,122评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,936评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,427评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,467评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,785评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,931评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,696评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,141评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,483评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,625评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,291评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,892评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,324评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,492评论 2 348

推荐阅读更多精彩内容