注入的controller属于内部类,并继承了某个类,一开始以为其名字也是类名首字母小写的字符串,结果错了,实际是父类首字母小写 + "." + 当前类名,下面我们一起探究一下,spring的bean名字生成规则。
spring属性注入查找属性值是在org.springframework.beans.factory.support.DefaultListableBeanFactory#findAutowireCandidates方法。
其中生成属性名称调用的代码是
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
该方法如下
public static String[] beanNamesForTypeIncludingAncestors(
ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
Assert.notNull(lbf, "ListableBeanFactory must not be null");
String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
if (lbf instanceof HierarchicalBeanFactory hbf) {
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory pbf) {
String[] parentResult = beanNamesForTypeIncludingAncestors(
pbf, type, includeNonSingletons, allowEagerInit);
result = mergeNamesWithParent(result, parentResult, hbf);
}
}
return result;
}
- 可以发现最终还是调用的org.springframework.beans.factory.support.DefaultListableBeanFactory#getBeanNamesForType(java.lang.Class<?>, boolean, boolean)方法生成的属性名称
- 该方法又调用了org.springframework.beans.factory.support.DefaultListableBeanFactory#doGetBeanNamesForType
- doGetBeanNamesForType方法直接遍历beanDefinitionNames和manualSingletonNames两个缓存查找的
那么beanDefinitionNames又是什么时候初始化的呢?查找可以发现在org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition方法初始化了该缓存。
该缓存是在容器初始化的时候通过AnnotatedBeanDefinitionReader或者XmlBeanDefinitionReader,GroovyBeanDefinitionReader,PropertiesBeanDefinitionReader等注入进去的。
这里我们直接看AnnotatedBeanDefinitionReader。其核心注册逻辑如下
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
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));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
bean名称最终是通过AnnotationBeanNameGenerator生成的。步骤如下
- 先查看注解是否指定了bean名称,有指定的话用指定的
- 在生成默认的bean名称(因为这儿是默认生成的,为了唯一,会把父类名这些都加上)
总结
标签:abd,String,spring,探讨,springframework,bean,Class,qualifier From: https://blog.51cto.com/u_11404173/8250440spring里面通过大量设计良好,职责清晰的接口,保证了代码解耦和扩展性。