ConfigurationClassPostProcessor
ConfigurationClassPostProcessor类层次
这个后置处理器是spring的核心处理器,注解@ComponentScans @Configuration @Component @ComponentScan @Import @ImportResource @Lazy @Primary @DependsOn @Role @Description 等注解都是由这个类触发进行处理后注册元数据到容器中的。
该类实现了BeanDefinitionRegistryPostProcessor接口,该接口继承了BeanFactoryPostProcessor接口。前一个接口方法实现可以注册Bean的定义信息,后者的实现可以干预BeanFactory的创建。这两个接口的实现方法是核心方法,特别是注册的方法。
postProcessBeanDefinitionRegistry方法(核心)
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
//省略校验代码.....
this.registriesPostProcessed.add(registryId);
//调用处理方法
processConfigBeanDefinitions(registry);
}
processConfigBeanDefinitions方法
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//拿到所有的候选组件名称(用户定义的就只有启动类,启动类是扫描的入口)
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
//判断是不是配置类型(以下注解标记的类是配置类型):
//@Configuration注解标记的类是配置类,Bean定义信息被标记为full 类型
//注解@Component @ComponentScan @Import @ImportResource 标记的类是配置类,Bean定义信息被标记为lite 类型
//类中的方法别@Bean注解标记,则也是配置类,Bean定义信息被标记为lite 类型
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
//存到候选组件集合中
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
//经过以上筛选,一般候选组件只剩下启动类
if (configCandidates.isEmpty()) {
return;
}
//按照order排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// 获取自定义的Bean名称生产策略
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();
}
//生成解析器解析每一个配置类,实例内部封装了componentScanParser解析器,用来解析@ComponentScan注解
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 {
//解析各种注解成Bean定义信息(核心关注逻辑)
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
//注册所有通过Import方式导入的BeanDefinitions,包含执行Condition的过滤逻辑
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());
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
该方法里面递归调用和嵌套逻辑很多,重点关注方法:
- ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory) 这个方法判断是否是配置类,并且设置配置类是full还是lite类别的属性,这个这两种类别后续再写文章介绍。
- parser.parse(candidates) 这个方法里面有全部的解析逻辑,最为关键的方法
- this.reader.loadBeanDefinitions(configClasses)加载注册BeanDefinition的方法,该方法只注册通过@Import注解导入的Bean,其余的在解析过程中已经注册了。
pase方法的过渡处理逻辑
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<>();
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof 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);
}
}
//处理@Import解析过程城中缓存的ConfigurationClassParser类中的全局变量deferredImportSelectors,该类引导后递归解析spring定义的导入类,Spring自动配置类都由此导入
processDeferredImportSelectors();
}
跟踪解析的流程调用到以下方法:
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
//判断该类是否是@import注解导入的且被解析过
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
//存入ConfigurationClass类的成员变量importedBy中,后续加载BeanDefinition的时候会判断是否需要跳过
existingClass.mergeImportedBy(configClass);
}
return;
}else {
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
SourceClass sourceClass = asSourceClass(configClass);
do {
//ConfigurationClassParser解析的最底层调用的方法,核心方法
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
//存放解析后的配置类
this.configurationClasses.put(configClass, configClass);
}
解析的核心方法doProcessConfigurationClass
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
//先递归地处理任何成员(嵌套内部类)类,必须是一个配置类(full或者lite的模式)
processMemberClasses(configClass, sourceClass);
//处理@PropertySource注解
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.warn("....");
}
}
//处理@ComponentScan注解,什么都不配置则默认从启动类包开始扫描
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
///循环所有的@ComponentScan注解注解的信息
for (AnnotationAttributes componentScan : componentScans) {
//立即扫描,内部最终将信息委托给ClassPathBeanDefinitionScanner进行包扫描,并执行过来过滤和条件筛选,非import类型会被直接注册BeanDefinition
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
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注解,先是getImports(sourceClass)方法收集类上的所有@Import导入的类,递归收集(该注解可能是元注解)
processImports方法循环处理逻辑如下:
4.1 先判断如果候选组件是否ImportSelector接口子类,如果是:
a.判断是DeferredImportSelector类,则收集导入类信息放入集合List<DeferredImportSelectorHolder> deferredImportSelectors中 --->ConfigurationClassParser类中的全局变量
b.不是上述类,则调用ImportSelector接口方法获取导入的BeanNames,然后循环获取到对应类后进行封装,调用processImports方法递归解析
4.2 再判断如果候选组件是否ImportBeanDefinitionRegistrar接口子类,收集导入类信息放入Map importBeanDefinitionRegistrars 中 -->> ConfigurationClass类中的全局变量
4.3 其余是普通配置类放入MultiValueMap<String, AnnotationMetadata> imports中 -->> ConfigurationClass类中的全局变量
4.4 普通配置类递归解析,再次调用processConfigurationClass方法解析
processImports(configClass, sourceClass, getImports(sourceClass), true);
//解析类上的@ImportResource导入资源文件,存放信息再Map<String, Class<? extends BeanDefinitionReader>> importedResources中 -->> ConfigurationClass类中的全局变量
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注解的方法元数据,存储在ConfigurationClass.beanMethods中
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
//递归获取接口中含有@Bean注解的默认方法,解析收集方法元数据存放在ConfigurationClass.beanMethods中
processInterfaces(configClass, sourceClass);
//判断如果有父类,则将父类返回,继续解析父类
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();
}
}
//没有父类则说明解析完成
return null;
}
解析过程总结:
-
先递归地处理任何成员(嵌套内部类)类,必须是一个配置类(full或者lite的模式)
-
解析类上的@PropertySources注解,用来导入properties文件信息,当前的environment应该是ConfigurableEnvironment接口实现类,否则会忽略该注解
-
解析类上的@ComponentScans注解,使用内部封装的componentScanParser解析器收集注解信息,最终将信息委托给ClassPathBeanDefinitionScanner进行包扫描。并执行过来过滤和条件筛选,非import类型会被直接注册BeanDefinition。
3.1 包扫描默认从当前类下的包开始进行扫描,拿到包路径下的所有class类文件,只留下@component注解或该注解为元注解的标记的类。
3.2 循环扫描到的类,先获取类的@Lazy @Primary @DependsOn @Role @Description注解信息存入BeanDefination中,将Bean定义信息和名称封装到BeanDefinitionHolder中,然后注册BeanDefinitionHolder到容器中
3.3 获取到符合条件的类BeanDefinitionHolder组成的集合,循环集合,递归调用parse方法继续解析,解析完成的类缓存到ConfigurationClassParser.configurationClasses中。
-
解析类上的@Import注解,收集类上的所有@Import导入的类,递归收集(该注解可能是元注解),然后循环集合进行处理。
4.1 先判断如果候选组件是否ImportSelector接口子类,如果是:
a.判断是DeferredImportSelector类,则收集导入类信息放入集合List<DeferredImportSelectorHolder> deferredImportSelectors中 --->ConfigurationClassParser类中的全局变量 b.不是上述类,则调用ImportSelector接口方法获取导入的BeanNames,然后循环获取到对应类后进行封装,调用processImports方法递归解析@Import注解
4.2 再判断如果候选组件是否ImportBeanDefinitionRegistrar接口子类,收集导入类信息放入Map importBeanDefinitionRegistrars 中 -->> ConfigurationClass类中的全局变量
4.3 其余是普通配置类放入MultiValueMap<String, AnnotationMetadata> imports中 -->> ConfigurationClass类中的全局变量
4.4 普通配置类递归解析,再次调用processConfigurationClass方法解析
-
解析类上的@ImportResource导入资源文件,存放信息再Map<String, Class<? extends BeanDefinitionReader>> importedResources中 -->> ConfigurationClass类中的全局变量
-
解析类获取所有类中含有@Bean注解的方法元数据,存储在ConfigurationClass.beanMethods中。因为解析是先解析自己@Bean注解方法,再解析父类@Bean方法,所以这个成员变量中包含了所有@Bean注解的方法,但是子类的的是排在前面的,所以循环注册的时候先注册子类的,再注册父类的时候发现Bean名称被使用了,则会跳过,从而达到子类覆盖父类的效果。
-
获取接口中含有@Bean注解的默认方法,解析收集方法元数据存放在ConfigurationClass.beanMethods中
-
获取类的父类,重复以上步骤进行解析,没有父类子结束该类的解析。
-
以上类中解析过的配置类被封装到了ConfigurationClass实例中,该实例又被封装到ConfigurationClassParser的成员变量 Map configurationClasses中
上述整个解析过程解析的都是项目用户自己在项目下通过注解注入自定义的类,或者通过注解提前注入spring中定义的组件。
由Spring自己引导注入的spring自己的组件是通过processDeferredImportSelectors方法开启的,整个调用过程复杂且涉及很多递归调用。
loadBeanDefinitions方法加载BeanDefinition
//循环加载BeanDefinitions,执行各种条件判断逻辑
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
//循环所有的配置类,注册BeanDefinition到容器
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
//判断是否需要跳过,执行@Conditional注解条件
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;
}
//判断该类是否是@import注解导入的
if (configClass.isImported()) {
//从@import的配置类中注册BeanDefinition
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//获取类及其父类中所有@Bean注解的方法(解析的时候收集的),注册BeanDefinition
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
//从导入的资源导入BeanDefinition
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//从实现了ImportBeanDefinitionRegistrar接口的类中导入(import的时候解析了)
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
MethodMetadata metadata = beanMethod.getMetadata();
String methodName = metadata.getMethodName();
// 使用ConditionEvaluator.shouldSkip方法判断@Conditional注解条件进行处理
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
//将需要跳过的类添加到Set集合中,供后续判断使用
configClass.skippedBeanMethods.add(methodName);
return;
}
//判断是否需要跳过的类
if (configClass.skippedBeanMethods.contains(methodName)) {
return;
}
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
Assert.state(bean != null, "No @Bean annotation attributes");
// Consider name and any aliases
List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
//注册别名
for (String alias : names) {
this.registry.registerAlias(beanName, alias);
}
//判断是否有被注册过:解析的时候先解析自己@Bean注解方法,再解析父类@Bean方法,会存在子类重写父类的方法,
//因为存储时有序的,所以子类的@Bean注解的方法会先被注册,这里判断父类的方法时候会跳过注册父类方法
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
"' clashes with bean name for containing configuration class; please make those names unique!");
}
return;
}
//构造配置类的定义信息
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
beanDef.setResource(configClass.getResource()); //设置类资源路径(全类名)
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
//判断是静态方法还是实例方法
if (metadata.isStatic()) {
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
beanDef.setFactoryMethodName(methodName);
}else {
beanDef.setFactoryBeanName(configClass.getBeanName());
beanDef.setUniqueFactoryMethodName(methodName);
}
beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
//解析@Lazy @Primary @DependsOn @Role @Description注解信息放入beanDef中
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
//设置注入模式(通过名称,或者类型,或者不注入)
Autowire autowire = bean.getEnum("autowire");
if (autowire.isAutowire()) {
beanDef.setAutowireMode(autowire.value());
}
//设置初始化和销毁方法
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}
String destroyMethodName = bean.getString("destroyMethod");
beanDef.setDestroyMethodName(destroyMethodName);
//设置代理模式
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
if (attributes != null) {
beanDef.setScope(attributes.getString("value"));
proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = ScopedProxyMode.NO;
}
}
// Replace the original bean definition with the target one, if necessary
BeanDefinition beanDefToRegister = beanDef;
if (proxyMode != ScopedProxyMode.NO) {
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
new BeanDefinitionHolder(beanDef, beanName), this.registry,
proxyMode == ScopedProxyMode.TARGET_CLASS);
beanDefToRegister = new ConfigurationClassBeanDefinition(
(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
}
if (logger.isDebugEnabled()) {
logger.debug(String.format("Registering bean definition for @Bean method %s.%s()",
configClass.getMetadata().getClassName(), beanName));
}
//注册BeanDefinition
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
registerBeanDefinitionForImportedConfigurationClass
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
AnnotationMetadata metadata = configClass.getMetadata();
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
//解析@Lazy @Primary @DependsOn @Role @Description注解信息放入configBeanDef中
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//注册BeanDefinition
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);
if (logger.isDebugEnabled()) {
logger.debug(".....");
}
}
loadBeanDefinitionsForBeanMethod
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
MethodMetadata metadata = beanMethod.getMetadata();
String methodName = metadata.getMethodName();
// 使用ConditionEvaluator.shouldSkip方法判断@Conditional注解条件进行处理
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
//将需要跳过的类添加到Set集合中,供后续判断使用
configClass.skippedBeanMethods.add(methodName);
return;
}
//判断是否需要跳过的类
if (configClass.skippedBeanMethods.contains(methodName)) {
return;
}
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
Assert.state(bean != null, "No @Bean annotation attributes");
// Consider name and any aliases
List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
//注册别名
for (String alias : names) {
this.registry.registerAlias(beanName, alias);
}
//判断是否有被注册过:解析的时候先解析自己@Bean注解方法,再解析父类@Bean方法,会存在子类重写父类的方法,
//因为存储时有序的,所以子类的@Bean注解的方法会先被注册,这里判断父类的方法时候会跳过注册父类方法
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
throw new Exception();
return;
}
//构造配置类的定义信息
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
beanDef.setResource(configClass.getResource()); //设置类资源路径(全类名)
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
//判断是静态方法还是实例方法
if (metadata.isStatic()) {
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
beanDef.setFactoryMethodName(methodName);
}else {
beanDef.setFactoryBeanName(configClass.getBeanName());
beanDef.setUniqueFactoryMethodName(methodName);
}
beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
//解析@Lazy @Primary @DependsOn @Role @Description注解信息放入beanDef中
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
//设置注入模式(通过名称,或者类型,或者不注入)
Autowire autowire = bean.getEnum("autowire");
if (autowire.isAutowire()) {
beanDef.setAutowireMode(autowire.value());
}
//设置初始化和销毁方法
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}
String destroyMethodName = bean.getString("destroyMethod");
beanDef.setDestroyMethodName(destroyMethodName);
//设置代理模式
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
if (attributes != null) {
beanDef.setScope(attributes.getString("value"));
proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = ScopedProxyMode.NO;
}
}
BeanDefinition beanDefToRegister = beanDef;
if (proxyMode != ScopedProxyMode.NO) {
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
new BeanDefinitionHolder(beanDef, beanName), this.registry,
proxyMode == ScopedProxyMode.TARGET_CLASS);
beanDefToRegister = new ConfigurationClassBeanDefinition(
(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
}
if (logger.isDebugEnabled()) {
logger.debug(String.format(".....",
configClass.getMetadata().getClassName(), beanName));
}
//注册BeanDefinition
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
整个解析过程中要记住的一点是:解析总是先从用户自定义的类中开始的,启动类就是入口。而启动类上的@SpringApplication注解就会导入一些类信息。另外启动类作为入口,该类上的所有注解都能够在解析过程中获取到。