共计 7702 个字符,预计需要花费 20 分钟才能阅读完成。
前言
上篇博客 spring 5.0.x 源码学习系列三: AnnotationConfigApplicationContext 类的无参构造方法的作用介绍了 AnnotationConfigApplicationContext 类无参构造方法的作用, 再次回顾下次要有如下几个作用:
- 初始化 spring bean 工厂
DefaultListableBeanFactory
- 通过
AnnotatedBeanDefinitionReader
将 spring6 个内置 bean 以RootBeanDefinition 到 bean
的类型注册到工厂, 其中要记住最重要的ConfigurationClassPostProcessor
- 初始化
ClassPathBeanDefinitionScan
(这个没啥用, 真正的扫描逻辑并不是用到它) - AnnotationConfigApplicationContext 的几个身份:
BeanDefinitionRegistry
和GenericApplicationContext
接下来进入注释: AnnotationConfigApplicationContext 类 register 办法作用
一、我的项目 demo
一、AnnotationConfigApplicationContext 类 register 办法 api
- 从上之下的源码就是它的执行过程, 附带正文
// AnnotationConfigApplicationContext.java
/**
* 顾名思义,传入的是被注解的类,并且在外面做了是否存在注解的校验(能够传多个类)
* 依据代码可知: 又是通过 AnnotatedBeanDefinitionReader 来注册的
*/
public void register(Class<?>... annotatedClasses) {Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
this.reader.register(annotatedClasses);
}
// AnnotationConfigApplicationContext.java
/**
* 因为上述 api 提供的是一个可变参数, 所以此处要遍历注册它
*/
public void register(Class<?>... annotatedClasses) {for (Class<?> annotatedClass : annotatedClasses) {registerBean(annotatedClass);
}
}
// AnnotationConfigApplicationContext.java
/**
* 将代码逻辑委托给另外办法
*/
public void registerBean(Class<?> annotatedClass) {doRegisterBean(annotatedClass, null, null, null);
}
// AnnotationConfigApplicationContext.java
/**
* 由调用链可知,调用此办法时, 只有第一个参数有值,其余的都为 null
* @param annotatedClass
* @param instanceSupplier
* @param name
* @param qualifiers
* @param definitionCustomizers
* @param <T>
*/
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
// 记住这个创立 beanDefinition 的 api, 很罕用。// 在利用 spring 扩大点动静增加一些 beanDefinition 至 bean 工厂时很有用
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {return;}
// set 进去的为 null, 因为传进来的为 null
abd.setInstanceSupplier(instanceSupplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
// 这块用的是以后类默认的 beanNameGenerator => AnnotationBeanNameGenerator
// private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
// 并不会应用到咱们自定义的 beanNameGenerator, 为什么?// 因为咱们压根就还没解析到 @ComponentScan 注解(这里须要有一点自定义 beanNameGenerator 的知识点)
// 大抵能够参考我 Github 中的这个类:
// https://github.com/AvengerEug/spring/blob/develop/ioc/src/main/java/com/eugene/sumarry/ioc/annotationtype/MyBeanNameGenerator.java
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 这里开始解决一些通用的注解: 比方 @Lazy、@Primary、@DependsOn、@Role、@Description
// 获取到这些注解中的值, 并填充至传入的 AnnotatedGenericBeanDefinition
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
// 这块如果依照 spring 的流程来基本上用不上, 因为传入的是 null
if (qualifiers != null) {for (Class<? extends Annotation> qualifier : qualifiers) {if (Primary.class == qualifier) {abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {abd.setLazyInit(true);
}
else {abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
// 传入的也为 null, 依照失常流程来, 先疏忽它
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {customizer.customize(abd);
}
// 不晓得是为了啥, 要 new 这么一个对象, 可能只是为了不便传值吧 - -!BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 这块临时不晓得。。。definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 注册 beanDefinition, 传入的是 registry, 有了上篇博客的根底,// 易知该 registry 就是 AnnotationConfigApplicationContext
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
// BeanDefinitionReaderUtils.java
/**
* 注册 beanDefinition
*/
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
// 它后面封装了一个 definitionHolder, 当初又拆解它......
// 该 register 是一个 AnnotationConfigApplicationContext
// 但此时是调用父类 GenericApplicationContext 的 registerBeanDefinition 办法
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {for (String alias : aliases) {registry.registerAlias(beanName, alias);
}
}
}
// DefaultListableBeanFactory.java
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
// 这里会校验以后的 beanDefinition, 具体校验啥没具体看,
// 但 beanDefinition instanceof AbstractBeanDefinition 条件是成立的
// 因为它 (AnnotatedGenericBeanDefinition) 继承了 AbstractBeanDefinition
if (beanDefinition instanceof AbstractBeanDefinition) {
try {((AbstractBeanDefinition) beanDefinition).validate();}
catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// beanDefinitionMap: 这个属性是 bean 工厂寄存定义的 beanDefinition
// 因为要注册 beanDefinition, 所以先校验它是否存在, 失常流程中
// 这里根本为 null
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {if (!isAllowBeanDefinitionOverriding()) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean'" + beanName +
"': There is already [" + existingDefinition + "] bound.");
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isWarnEnabled()) {
logger.warn("Overriding user-defined bean definition for bean'" + beanName +
"'with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {if (logger.isInfoEnabled()) {
logger.info("Overriding bean definition for bean'" + beanName +
"'with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean'" + beanName +
"'with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// 判断 bean 是否在创立, 失常的 register 流程中, 返回的根本为 false
if (hasBeanCreationStarted()) {// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// 将 beanD 注册到 bean 工厂中,// 1. 增加到 beanDefinitionMap
// 2. 增加到 beanDefinitionNames
// 3. 从 manualSingletonNames 中移除, 这里不分明 manualSingletonNames
// 属性是干啥的, 不过依据名字来猜想: 寄存手动创立的单例 bean 的名字?this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {resetBeanDefinition(beanName);
}
}
二、运行后果
三、小结
- Q1: 下面的代码执行完后(register 办法执行结束),往 bean 工厂中注册了几个 beanDefinition, bean 工厂中一共有几个 beanDefinition?
- A1: 注册了
2
个 beanDefinition, 此时 bean 工厂中一共有6 + 2 = 8
个 beanDefinition。
- Q2: 当初 bean 工厂中存在的 beanDefinition 的类型总共有几种?别离是?
- A2: 两种。别离是
RootBeanDefinition
和AnnotatedGenericBeanDefinition
。
- Q3: 当初有 bean 被创立进去吗?
- A3: 没有, register 办法只是注册 beanDefinition。个别是注册一个配置类 (eg: 蕴含 @ComponentScan 注解的类) 不便 spring 的后续操作(eg: 扫描包解析注解等等)。
- Q4: spring 认为形容 bean 的通用注解有哪些?
- A4: @Lazy、@Primary、@DependsOn、@Role、@Description
- spring 源码学习对应 GitHub 地址 https://github.com/AvengerEug/spring/tree/develop/resourcecode-study
- I am a slow walker, but I never walk backwards.
正文完