环境版本:java8,spring5.2.x,maven3.6
@Configuration注册类的全过程,话不多说,上代码,我这里是从关键的方法人手了
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
//1, 为我们传入的class创建bean的定义
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
// 2. 判断当前类是否应当跳过(根据 @Conditional 判断)
if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
abd.setInstanceSupplier(supplier);
// 3. 从类元数据中解析获取 scope 作用范围信息(默认为 singleton)
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
//4,为改bean定义设置作用范围
abd.setScope(scopeMetadata.getScopeName());
String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
//5. 处理通用注解(例如 @Lazy 等)
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
int var10;
int var11;
if (qualifiers != null) {
Class[] var9 = qualifiers;
var10 = qualifiers.length;
for(var11 = 0; var11 < var10; ++var11) {
Class<? extends Annotation> qualifier = var9[var11];
if (Primary.class == qualifier) {
abd.setPrimary(true);
} else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
} else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
BeanDefinitionCustomizer[] var13 = customizers;
var10 = customizers.length;
for(var11 = 0; var11 < var10; ++var11) {
BeanDefinitionCustomizer customizer = var13[var11];
customizer.customize(abd);
}
}
//6. 创建 BeanDefinition 的 BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 7. 应用 ScopedProxyMode
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 8. 注册 BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
说明:
doRegisterBean方法很复杂,我们的主题是@Configuration,所以省略一些不重要的代码。
- 为我们传入的 class 创建对应的 BeanDefinition 并进行相关默认值的初始化,这里的 BeanDefinition 指的是 AnnotatedGenericBeanDefinition,它是 GenericBeanDefinition 的子类,主要添加了对注解元数据的支持(这点通过下面的构造器代码也能够看出来,它将类元数据 metadata 单独进行保存,这个 StandardAnnotationMetadata 中有一个属性 annotations 就是用来专门保存类的注解信息的)。
public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
this.setBeanClass(beanClass);
this.metadata = AnnotationMetadata.introspect(beanClass);
}
- 根据 @Conditional 注解来判断当前 Bean 实例化是否需要跳过(即当前不满足 @Conditional 注解条件)。
public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
return this.shouldSkip(metadata, (ConfigurationPhase)null);
}
将获取到的 scope 赋值给 BeanDefinition(这步完成后刚刚创建的 AnnotatedGenericBeanDefinition 对象的 scope 属性为 scope 值)。
获取并处理类的通用注解(@Lazy、@Primary、@DependsOn、@Role 和 @Description)信息,这里调用的是 processCommonDefinitionAnnotations 方法,这个方法没有什么太大营养,就是把你的类元数据中的注解信息取出来,然后依次检查是否设置了对应的注解,并将值赋给刚刚创建的 BeanDefinition 对象
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
} else if (abd.getMetadata() != metadata) {
lazy = attributesFor(abd.getMetadata(), (Class)Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
}
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
if (dependsOn != null) {
abd.setDependsOn(dependsOn.getStringArray("value"));
}
AnnotationAttributes role = attributesFor(metadata, Role.class);
if (role != null) {
abd.setRole(role.getNumber("value").intValue());
}
AnnotationAttributes description = attributesFor(metadata, Description.class);
if (description != null) {
abd.setDescription(description.getString("value"));
}
}
创建 BeanDefinition 对应的 BeanDefinitionHolder 对象,这个对象没什么太多特殊的作用,就是持有一个 BeanDefinition 对象。
接下里调用 applyScopedProxyMode 方法来应用(创建)一个 ScopedProxyMode 对象(跟 @Configuration 无关,所以不去过细分析)。
最后一步,也就是最重要的注册 BeanDefinition 到 BeanDefinitionMap 中,这里直接进方法看代码。
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
//9,注册bean的定义
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length;
for(int var6 = 0; var6 < var5; ++var6) {
String alias = var4[var6];
registry.registerAlias(beanName, alias);
}
}
}
- 这里首先使用 Bean 的主名称进行注册,这个主名称其实就是我们的 Bean 名称(当前的名称就是我们刚刚传入的配置类的类名 SpringConfig),然后又使用了标签进行注册,这里我们先不考虑标签,所以直接使用 Bean 名称进行注册,继续跟进 registry.registerBeanDefinition 方法。
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
//10,验证名称和定义不能为空
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
// 11. 如果当前的 BeanDefinition 是 AbstractBeanDefinition 子类则验证对象信息
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var8) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
}
}
BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
//两个分支-> 如果容器中已经存在了该 BeanName 所对应的 BeanDefinition
if (existingDefinition != null) {
// 如果不允许重写(替换)原始的 BeanDefinition直接抛异常
if (!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
// 如果允许替换则比较两个 BeanDefinition 的 @Role 值
if (existingDefinition.getRole() < beanDefinition.getRole()) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (!beanDefinition.equals(existingDefinition)) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (this.logger.isTraceEnabled()) {
this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
// 将新的 BeanDefinition 对象添加到 Map 中
this.beanDefinitionMap.put(beanName, beanDefinition);
}
// 12. 如果 Map 中不存在 BeanName 所对应的的 BeanDefinition
else {
//13. 判断当前工厂是否已经开始创建 Bean 对象
if (this.hasBeanCreationStarted()) {
synchronized(this.beanDefinitionMap) {
// 将该 BeanDefinition 添加到 Map 中
this.beanDefinitionMap.put(beanName, beanDefinition);
//// 按照原始 BeanName List 大小 +1 创建新 BeanName List
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
// 将原始 BeanName List 内容复制到新 BeanName List 中 updatedDefinitions.addAll(this.beanDefinitionNames);
// 将新添加的 BeanName 添加到新的 BeanName List 中
updatedDefinitions.add(beanName);
// 让原始的 BeanName List 指向新 BeanName List
this.beanDefinitionNames = updatedDefinitions;
// 移除工厂内部的手动单例名称集
this.removeManualSingletonName(beanName);
}
} else {
// 14. 没有正在创建bean,将 BeanDefinition 直接添加到 Map 中
this.beanDefinitionMap.put(beanName, beanDefinition);
// 15. 如果非正在创建则直接将 BeanName 添加到 BeanName List 中
this.beanDefinitionNames.add(beanName);
// 从 manualSingletonNames 移除 BeanName
this.removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
// 如果 Map 中已存在 BeanName 对应的 BeanDefinition 或者 BeanName 为单例模式
if (existingDefinition == null && !this.containsSingleton(beanName)) {
if (this.isConfigurationFrozen()) {
this.clearByTypeCache();
}
} else {
// 重置 BeanName 在容器中对应的 BeanDefinition
this.resetBeanDefinition(beanName);
}
}
验证 BeanName 和 BeanDefinition 不为空。
然后判断当前的 BeanDefinition 是否是 AbstractBeanDefinition 的子类,如果是的话就调用 prepareMethodOverrides 方法就对其抽象方法进行验证,判断这个 BeanDefinition 是否正确重写了它的抽象方法。
接着判断当前容器中是否已经存在 BeanName 所对应的 BeanDefinition(BeanDefinition 存储于 BeanDefinitionMap 中,键为 BeanName,值为 BeanDefinition),如果已经存在就判断是否可以进行替换等一系列逻辑,如果不存在就进入 else 语句块。
接着调用 hasBeanCreationStarted 判断当前工厂是否已经开始创建 Bean(这个方法里面主要是通过判断 alreadyCreated 容器内是否为空,因为当工厂将要实例化创建一个 Bean 对象的时候都会先将其存放在这个 alreadyCreated 容器中),如果此时工厂还未开始创建 Bean 对象,那么我们就可以直接将当前的 BeanName 和 BeanDefinition 直接添加到容器中。但是如果此时工厂已经开始创建 Bean 对象了(根据 BeanDefinition),那么正如它注释中所讲这个时候再对 BeanDefinitionMap 和 BeanDefinitionNames 来进行操作就是不安全的了,因此这个时候我们就需要通过加锁来保证整个的添加操作线程安全。但是在什么情况下会出现这个问题呢,显然如果我们按照正常的代码逻辑到目前为止还没有进行任何的 Bean 的创建工作,但是假如在我们自己的业务代码中,在另一个线程中,当容器开始创建 Bean 对象时,我们直接获取到容器中的这个 DefaultListableBeanFactory,并调用这个 registerBeanDefinition 方法对其当中的 BeanDefinitionMap 进行添加或删除等修改操作,那么就会造成非线程安全的问题(这里的安全问题主要是指虽然 BeanDefinitionMap 是 concurrentHashMap 的线程安全 Map,对于将 BeanDefinition 添加到其中的操作时线程安全的,但是我们无法保证 BeanDefinitionName 和 BeanDefinition 能够同时被分别添加到两个容器中(非原子操作),即整个操作流程是非线程安全的)。并且还可以注意到在下面的 BeanDefinitionNames 这个 List 当中顺序保存了所有的 BeanName,在锁的过程中我们锁的是 BeanDefinitionMap 这个对象,并没有锁住这个 BeanDefinitionNames,因此跟上面一样的道理,假如有其他的线程正在容器中遍历读取 BeanDefinitionNames List 当中的信息对 List 当中的 Bean 进行实例化,那么此时我们在当前线程对 BeanDefinitionNames List 直接进行添加操作会引发快速失败(抛出 ConcurrentModificationException 异常),所以这里我们是采用了类似于安全失败的机制,即先创建一个新的 List,将原 List 内的元素拷贝过来,再添加新的元素,最后再将原 List 指向新 List 即可。
如果此时容器未开始创建 Bean 对象,也就是正常启动流程的话,那么就会进入到第二个语句块,直接将 BeanDefinition 添加到 BeanDefinitionMap 中。
将 BeanName 添加到 BeanDefinitionNames List 当中,注册流程完成。
refresh方法
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
//通过debugger可知,方法执行到这里,原始的configuration类被替换成了cglib的代理类 this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
一直一步一步debugger,重点来到了 因为这个方法实在实在是太长了太复杂了,我自己 Debug 跟了几次,发现上下的许多代码跟当前分析的这个 @Configuration 都是没有什么关系的,因此我就都省略掉了,我们只关注重点的实现代码,在这里最重要的两个方法一个是 invokeBeanDefinitionRegistryPostProcessors,另一个就是 invokeBeanFactoryPostProcessors。
invokeBeanDefinitionRegistryPostProcessors 方法中对于 @Configuration 主要的作用就是将其 @Configuration 注解信息解析到它的 BeanDefinition 的 Attributes 当中。
invokeBeanFactoryPostProcessors 方法的作用主要是对 BeanDefinition 中的 Attitudes 进行判断,选取全注解(Attributes 当中的 configurationClass 所对应的值为 full)类,将其 BeanDefinition 中的 beanClass 替换为 CGLIB 的代理类。
invokeBeanDefinitionRegistryPostProcessors
因此下面我来以此介绍这两个方法,首先是跟进 invokeBeanDefinitionRegistryPostProcessors 方法,然后再跟进它所调用的 postProcessBeanDefinitionRegistry 方法。我们一步一步找到,最终定位到ConfigurationClassPostProcessor#processConfigBeanDefinitions
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList();
String[] candidateNames = registry.getBeanDefinitionNames();
String[] var4 = candidateNames;
int var5 = candidateNames.length;
for(int var6 = 0; var6 < var5; ++var6) {
String beanName = var4[var6];
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
} else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
if (!configCandidates.isEmpty()) {
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry)registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator)sbr.getSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator");
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates);
HashSet alreadyParsed = new HashSet(configCandidates.size());
do {
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());
}
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();
Iterator var12 = alreadyParsed.iterator();
while(var12.hasNext()) {
ConfigurationClass configurationClass = (ConfigurationClass)var12.next();
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
String[] var23 = newCandidateNames;
int var24 = newCandidateNames.length;
for(int var14 = 0; var14 < var24; ++var14) {
String candidateName = var23[var14];
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();
}
}
}
invokeBeanFactoryPostProcessors
另一个比较重要的方法就是这个PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors 方法,因此我们直接跟进去。
private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
Iterator var2 = postProcessors.iterator();
while(var2.hasNext()) {
BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var2.next();
postProcessor.postProcessBeanFactory(beanFactory);
}
}
然后调用ConfigurationClassPostProcessor#postProcessBeanFactory的方法,在这个方法内部,调用this.enhanceConfigurationClasses(beanFactory);
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap();
String[] var3 = beanFactory.getBeanDefinitionNames();
int var4 = var3.length;
for(int var5 = 0; var5 < var4; ++var5) {
String beanName = var3[var5];
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
AnnotationMetadata annotationMetadata = null;
MethodMetadata methodMetadata = null;
if (beanDef instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition)beanDef;
annotationMetadata = annotatedBeanDefinition.getMetadata();
methodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
}
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
AbstractBeanDefinition abd = (AbstractBeanDefinition)beanDef;
if (!abd.hasBeanClass()) {
boolean liteConfigurationCandidateWithoutBeanMethods = "lite".equals(configClassAttr) && annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata);
if (!liteConfigurationCandidateWithoutBeanMethods) {
try {
abd.resolveBeanClass(this.beanClassLoader);
} catch (Throwable var14) {
throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), var14);
}
}
}
}
if ("full".equals(configClassAttr)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" + beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
}
if (this.logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
this.logger.info("Cannot enhance @Configuration bean definition '" + beanName + "' since its singleton instance has been created too early. The typical cause is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'.");
}
configBeanDefs.put(beanName, (AbstractBeanDefinition)beanDef);
}
}
if (!configBeanDefs.isEmpty()) {
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
Iterator var16 = configBeanDefs.entrySet().iterator();
while(var16.hasNext()) {
Entry<String, AbstractBeanDefinition> entry = (Entry)var16.next();
AbstractBeanDefinition beanDef = (AbstractBeanDefinition)entry.getValue();
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
Class<?> configClass = beanDef.getBeanClass();
//这里就是生产代理class了
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (this.logger.isTraceEnabled()) {
this.logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
//替换掉之前的beanclass
beanDef.setBeanClass(enhancedClass);
}
}
}
}
在这个方法中主要就执行了获取 BeanDefinition 的 Attributes 中键为 ConfigurationClass 值为 full 的全注解类,并对其使用 CGLIB 进行代理的过程。
(1)遍历获取所有的 BeanDefinition,获取全注解类,并将其添加到全注解类容器(configBeanDefs)中;
(2)遍历 configBeanDefs 容器,取出全注解类,并使用 CGLIB 进行代理;
(3)使用代理后的类来替换原始类(替换 BeanDefinition 中的 BeanClass);
到这里我们就已经完成了对于 @Configuration 注解处理的大致代码流程分析。