首页 > 其他分享 >探讨一下spring中bean名字的生成规则

探讨一下spring中bean名字的生成规则

时间:2023-11-08 14:01:19浏览次数:34  
标签:abd String spring 探讨 springframework bean Class qualifier

注入的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生成的。步骤如下

  1. 先查看注解是否指定了bean名称,有指定的话用指定的
  2. 在生成默认的bean名称(因为这儿是默认生成的,为了唯一,会把父类名这些都加上)

总结

spring里面通过大量设计良好,职责清晰的接口,保证了代码解耦和扩展性。

标签:abd,String,spring,探讨,springframework,bean,Class,qualifier
From: https://blog.51cto.com/u_11404173/8250440

相关文章

  • springboot高版本(2.5以上)解决跨域问题
    版本说明springboot2.7.17原来代码importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.CorsRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration......
  • 关于spring-boot-starter-parent 3.1.2和3.1.5版本的区别导致的错误
    1.问题在学习黑马程序员SpringBoot3+Vue3全套视频教程时,手动配置springboot项目时,由于之前spring-boot-starter-parent安装的版本是3.1.5,视频要求的是3.1.2,但是之前怎么弄也无法下载到3.1.2(后面已解决,可参考手动配置Maven依赖项),索性就是用了3.1.5版本。但是随即就遇到了问题,在......
  • 运行Springboot测试类查询数据库数据显示白网页
    问题运行Springboot测试类时,查询数据库里面数据显示如下白网页程序报如下错误 解决方案 SpringBoot应用未能启动的原因是它没有找到合适的数据库配置具体来说,它需要一个数据源(DataSource),但未能在你的配置中找出,也没有找到任何嵌入式数据库(H2,HSQL或Derby)以下是几个......
  • SpringBoot集成文件 - 大文件的上传(异步,分片,断点续传和秒传)
    1.知识准备大文件的上传技术手段和普通文件上传是有差异的,主要通过基于分片的断点续传和秒传和异步上传解决。#1.1大文件面临的问题上传速度慢--应对: 分块上传上传文件到一半中断后,继续上传却只能重头开始上传--应对: 断点续传相同文件未修改再次上传,却只能重......
  • Spring系列:基于XML的方式构建IOC
    目录一、搭建模块spring6-ioc-xml二、获取bean的三种方式三、基于setter注入四、基于构造器注入五、特殊值处理六、为对象类型属性赋值七、引入外部属性文件八、基于XML自动装配一、搭建模块spring6-ioc-xml①引入配置文件引入spring6-ioc-xml模块配置文件:beans.xml、log4j2.xm......
  • 基于springboot+vue开发的教师工作量管理系
    教师工作量管理系springboot31摘要随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了教师工作量管理系统的开发全过程。通过分析教师工作量管理系统管理的不足,创建了一个计算机管理教师工作量管理系统的方案。文章介绍了教师工作量......
  • springboot项目基于pom.xml中的maven实现多环境配置
    在SpringBoot项目中,我们可以通过在pom.xml中配置Maven插件,结合Spring的Profile实现多环境配置。下面是一种可能的实现方式:首先,在pom.xml中添加Maven插件,该插件可以用于编译、测试和打包项目。为了能够支持多环境配置,我们可以在profiles标签内定义不同的profile,然后在build标签内的......
  • idea系列---【上一次打开springboot项目还好好的,现在打开突然无法启动了】
    问题昨天走的时候项目还能正常启动,今天来了之后突然报下面的错误:Error:Kotlin:ModulewascompiledwithanincompatibleversionofKotlin.Thebinaryversionofitsmetadatais1.7.1,expectedversionis1.1.16.解决方案点击idea:Build>RebuildProject重新编译即可......
  • springboot nacos使用yaml配置list方式
    方式一配置项:app:demo:list1:xiaohong,xiaominglist2:>xiaohong,xiaominglist1和list2看起来是2种风格,其实都是同一种写法,以逗号分隔java代码:@Data@ComponentpublicclassAppConfig1{@Value("${app.demo.list1}")privateList<Strin......
  • SpringBoot获取配置文件-@Value、@ConfigurationProperties方式
    配置文件yml#phantomjs的位置地址phantomjs:binPath:windows:binPath-winlinux:binPath-linuxjsPath:windows:jsPath-winlinux:jsPath-linuximagePath:windows:imagePath-winlinux:imagePath-linuxphantomjs2:binPath2:I‘......