Spring Bean 扫描注册 之 AnnotatedBeanDefinitionReader
Spring Bean 扫描注册 之 AnnotatedBeanDefinitionReader
1、简介
AnnotatedBeanDefinitionReader
是干什么的?
- 从类对象中获取基本注解信息,创建
BeanDefinition
对象。 - 将
BeanDefinition
对象注册到BeanDefinitionRegistry
对象中。
由于BeanFactory
和ApplicationContext
的实现类基本上都会实现BeanDefinitionRegistry
接口。所以AnnotatedBeanDefinitionReader
实际上会将BeanDefinition
对象注册到Spring容器中。
这和我们上篇文章介绍的 ClassPathBeanDefinitionScanner 都是注册Bean到 IOC 容器中, 但 AnnotatedBeanDefinitionReader 是基于具体的类注册,ClassPathBeanDefinitionScanner 基于给定的包扫描注册。
2、 基本使用
现在有ComponentA
:
public class ComponentA { }
需要将ComponentA
注册到Spring容器中:
// 创建registry
BeanDefinitionRegistry registry = new DefaultListableBeanFactory();
// 创建reader,指定registry
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry);
// 注册指定类作为bean
reader.registerBean(ComponentA.class);
// 打印ComponentA的BeanDefinition信息
System.out.println(registry.getBeanDefinition("componentA"));
输出结果如下:
Generic bean: class [ComponentA]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false;
factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
3、源码解读
核心步骤在AnnotatedBeanDefinitionReader#registerBean()
方法。registerBean()
方法有很多重载的实现,最终都会调用AnnotatedBeanDefinitionReader#doRegisterBean()。
我们先大概看一下它的实现:
private <T> void doRegisterBean(
Class<T> beanClass,
@Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers,
@Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
// 根据给定类对象,创建BeanDefinition基本信息
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
// 根据@Conditional判断是否应该跳过
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
// 指定创建bean的方法
abd.setInstanceSupplier(supplier);
// 指定作用域
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
// 生成beanName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 指定类对象标注通用的注解:@Lazy、@Primary、@DependsOn、@Role、@Description
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
// 指定传参的注解:@Primary、@Lazy等
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));
}
}
}
// BeanDefinition自定义处理拦截
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 判断并创建作用域代理
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 注册到Spring容器
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
接下来对每个步骤进行深入讲解。
3.1、创建AnnotatedGenericBeanDefinition
AnnotatedGenericBeanDefinition
是GenericBeanDefinition
的子类。除了GenericBeanDefinition
和AbstractBeanDefinition
中定义的关于bean
的基本信息,AnnotatedGenericBeanDefinition
额外存储了类的注解信息:
public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
setBeanClass(beanClass);
this.metadata = AnnotationMetadata.introspect(beanClass);
}
沿着构造函数继续深入,可以发现会在AnnotationsScanner#getDeclaredAnnotations()
获取注解信息:
static Annotation[] getDeclaredAnnotations(AnnotatedElement source, boolean defensive) {
boolean cached = false;
Annotation[] annotations = declaredAnnotationCache.get(source);
if (annotations != null) {
cached = true;
}
else {
annotations = source.getDeclaredAnnotations();
if (annotations.length != 0) {
boolean allIgnored = true;
for (int i = 0; i < annotations.length; i++) {
Annotation annotation = annotations[i];
if (isIgnorable(annotation.annotationType()) ||
!AttributeMethods.forAnnotationType(annotation.annotationType()).isValid(annotation)) {
annotations[i] = null;
}
else {
allIgnored = false;
}
}
annotations = (allIgnored ? NO_ANNOTATIONS : annotations);
if (source instanceof Class || source instanceof Member) {
declaredAnnotationCache.put(source, annotations);
cached = true;
}
}
}
if (!defensive || annotations.length == 0 || !cached) {
return annotations;
}
return annotations.clone();
}
3.2、 @Conditional校验
获取基本注解信息后,首先会根据@Conditional
注解信息判断是否需要注册这个类对象:
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
校验的核心源码位于ConditionEvaluator#shouldSkip()
方法:
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata,
@Nullable ConfigurationPhase phase) {
// 没有标注@Condition,直接返回
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
return false;
}
if (phase == null) {
// 配置类:类标注@Component/@ComponentScan/@Import/@ImportResource,或方法标注@Bean
if (metadata instanceof AnnotationMetadata &&
ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
}
// 普通类
return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
}
// 获取所有@Conditional注解对应的Condition实现类
List<Condition> conditions = new ArrayList<>();
for (String[] conditionClasses : getConditionClasses(metadata)) {
for (String conditionClass : conditionClasses) {
Condition condition = getCondition(conditionClass, this.context.getClassLoader());
conditions.add(condition);
}
}
// 对Condition实现类排序
AnnotationAwareOrderComparator.sort(conditions);
// 遍历Condition实现类,调用其matches()方法进行校验
for (Condition condition : conditions) {
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
return true;
}
}
return false;
}
总的来说,AnnotatedBeanDefinitionReader
会根据标注的@Conditional
进行校验,具体校验逻辑位于对应Condition
实现类中。
例如@Profile
的对应校验实现类为ProfileCondition
,校验逻辑为:
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 获取@Profile属性
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
// 遍历@Profile属性值
for (Object value : attrs.get("value")) {
// 从environment中获取运行时环境变量进行匹配
if (context.getEnvironment().acceptsProfiles(Profiles.of((String[]) value))) {
return true;
}
}
return false;
}
return true;
}
3.3、 添加instanceSupplier回调
BeanDefinition
的instanceSupplier
属性通常作为创建bean
对象的特殊回调。
在AbstractAutowireCapableBeanFactory#createBeanInstance()
方法中,会根据BeanDefinition
中是否有instanceSupplier
信息来执行回调:
protected BeanWrapper createBeanInstance(String beanName,
RootBeanDefinition mbd,
@Nullable Object[] args) {
// 省略……
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 省略……
}
3.4、生成beanName
如果指定名字,则用对应形参值;如果没有指定名字,会生成名字:
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotatedBeanDefinition
会调用AnnotationBeanNameGenerator#generateBeanName()
方法生成beanName
:
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
if (definition instanceof AnnotatedBeanDefinition) {
// 根据注解生成beanName
String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
if (StringUtils.hasText(beanName)) {
// Explicit bean name found.
return beanName;
}
}
// 根据默认规则生成beanName
return buildDefaultBeanName(definition, registry);
}
AnnotationBeanNameGenerator#determineBeanNameFromAnnotation()
方法会获取@Component
及其子注解、@ManagedBean
和@Named
注解的value
值作为beanName
:
protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
// 获取注解类型
AnnotationMetadata amd = annotatedDef.getMetadata();
Set<String> types = amd.getAnnotationTypes();
// 遍历注解类型,设置beanName
String beanName = null;
for (String type : types) {
// 获取注解信息
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
if (attributes != null) {
// 获取元注解信息
Set<String> metaTypes = this.metaAnnotationTypesCache.computeIfAbsent(type, key -> {
Set<String> result = amd.getMetaAnnotationTypes(key);
return (result.isEmpty() ? Collections.emptySet() : result);
});
// 校验元注解是否是@Component、注解是否是@Component、@ManagedBean或@Named
if (isStereotypeWithNameValue(type, metaTypes, attributes)) {
// 获取value属性作为beanName
Object value = attributes.get("value");
if (value instanceof String) {
String strVal = (String) value;
if (StringUtils.hasLength(strVal)) {
if (beanName != null && !strVal.equals(beanName)) {
throw new IllegalStateException("Stereotype annotations suggest inconsistent " +
"component names: '" + beanName + "' versus '" + strVal + "'");
}
beanName = strVal;
}
}
}
}
}
return beanName;
}
AnnotationBeanNameGenerator#buildDefaultBeanName()
方法会根据类名生成beanName
:
protected String buildDefaultBeanName(BeanDefinition definition) {
// 获取全限定类名
String beanClassName = definition.getBeanClassName();
Assert.state(beanClassName != null, "No bean class name set");
// 获取类名:根据包名分隔符(.)、CGLIB代理类分隔符($$)和内部类分隔符($)进行字符串处理
String shortClassName = ClassUtils.getShortName(beanClassName);
// 类名处理:如果长度大于1且第一二个字母都是大写(或类名为空),直接返回,否则首字母小写返回
return Introspector.decapitalize(shortClassName);
}
3.5、通用注解处理
接下来会对一些通用注解进行解析和设置,这里的通用注解包括:@Lazy
、@Primary
、@DependsOn
、@Role
和@Description
。
// 解析类对象中的注解信息
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
// 解析形参中的注解信息,会进行覆盖
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));
}
}
}
AnnotationConfigUtils#processCommonDefinitionAnnotations()
方法会解析类对象中的通用注解信息:
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(), 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"));
}
}
2.6、BeanDefinition自定义处理拦截
接下来,会根据形参的BeanDefinitionCustomizer
进行自定义处理,可以修改BeanDefinition
的信息:
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
2.7、注册到Spring容器
最后,会将BeanDefinitionHolder
信息添加到Spring容器:
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder,
BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
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);
}
}
}
不同的BeanDefinitionRegistry
实现类会有不同的注册逻辑,这里主要介绍DefaultListableBeanFactory
的实现。
DefaultListableBeanFactory#registerBeanDefinition()
方法
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");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
// 校验
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// 校验beanName是否已存在
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
// 如果beanName已存在
if (existingDefinition != null) {
// 如果Spring容器不允许重载BeanDefinition,抛出异常
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
// 如果Spring容器不允许重载BeanDefinition,会进行覆盖
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
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 (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
// 如果beanName不存在
else {
// 如果Spring容器已经进入创建bean的阶段:加锁进行更新
if (hasBeanCreationStarted()) {
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;
removeManualSingletonName(beanName);
}
}
// 如果Spring容器没有进入创建bean的阶段,即还在注册阶段:直接更新
else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
// 如果beanName对应的BeanDefinition和单例对象已经存在:即发生了覆盖
if (existingDefinition != null || containsSingleton(beanName)) {
// 清除该beanName(以及子bean)的mergedBeanDefinition和单例对象缓存
resetBeanDefinition(beanName);
}
// 否则,如果Spring容器可以缓存BeanDefinition的元数据
else if (isConfigurationFrozen()) {
// 清除所有allBeanNamesByType和singletonBeanNamesByType缓存(类对象-beanNmae映射的缓存)
clearByTypeCache();
}
}