【Spring类路径Bean定义信息扫描】

这篇具有很好参考价值的文章主要介绍了【Spring类路径Bean定义信息扫描】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. ClassPathBeanDefinitionScanner作用

扫描类路径下的类注册为bean定义。

2. 类声明

public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider
/**
 类名就是扫描类路径下bena定义。继承自类路径扫描候选组件提供器
 类路径扫描候选组件提供器的作用:
 	扫描类路径下的时候,使用过滤器是否考虑作为候选者,作为待注入的bean定义。
**/

3. 属性

	// beanDefinition注册器
	private final BeanDefinitionRegistry registry;
	
	// 存储默认的BeanDefinition属性值,如作用域(scope)、懒加载(lazy initialization)等设置。
	private BeanDefinitionDefaults beanDefinitionDefaults = new BeanDefinitionDefaults();
	
	// 定义了一组字符串模式,用于决定哪些被扫描到的类应该被认为是自动装配候选者(autowire 	
	// candidates)。如果一个类的全限定名匹配这些模式之一,那么它将被视为可以进行自动装配的bean。
	private String[] autowireCandidatePatterns;

	// Bean名称生成器策略,默认是AnnotationBeanNameGenerator实例,它根据类上的注解或类名来生
	// 成bean的名称.在扫描和注册bean的过程中,会用到这个策略来生成唯一的bean名称。
	private BeanNameGenerator beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
	
	// 指定了作用域元数据解析器,默认使用AnnotationScopeMetadataResolver,它根据类上的注解
	// (如@Component、@Service等)来确定bean的作用域(例如singleton或prototype)。
	private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
	
	// 如果为true,表示在扫描过程中不仅会处理带有特定注解(如@Component、@Repository、@Service、
	// @Controller等)的类,还会处理类上的注解配置信息(如@Autowired、@Value等)。如果设置为
	//	false,则只扫描并注册类本身作为bean,而不处理注解驱动的配置。
	private boolean includeAnnotationConfig = true;

4. 构造器

/*
	单个参数的构造器: 传入注册器
*/
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
	// 调用本地构造器: 注册器,使用默认过滤器
	this(registry, true);
}

/*
	双参数的构造器: 传入注册器, 是否使用默认过滤器
*/
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
	// 调用本地构造器: 注册器, 是否使用默认的过滤器,获取或创建环境
	this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
		Environment environment) {
	// 调用本地构造器:注册器,过滤器,环境,资源加载器(null)
	this(registry, useDefaultFilters, environment,
			(registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
}

// 最终的构造器: 注册器、默认过滤器、环境、资源加载器
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment, @Nullable ResourceLoader resourceLoader) {
	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	this.registry = registry;
	// 设置值
	if (useDefaultFilters) {
		registerDefaultFilters();
	}
	setEnvironment(environment);
	setResourceLoader(resourceLoader);
}

5. 扫描方法

// 扫描指定包的类
public int scan(String... basePackages) {
	// 获取当前注册器中bean定义的数量
	int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
	// 去扫描指定的包
	doScan(basePackages);
	
	// Register annotation config processors, if necessary.
	if (this.includeAnnotationConfig) {
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}
	// 返回注册后-之前已注册数量的差
	return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}

6. 真正扫描方法

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
	Assert.notEmpty(basePackages, "At least one base package must be specified");
	Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
	for (String basePackage : basePackages) {
		// 查找候选组件
		Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
		
		for (BeanDefinition candidate : candidates) {
			// 获取作用域
			ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
			// 设置作用域
			candidate.setScope(scopeMetadata.getScopeName());
			// 按照beanName生成策略获取到bean名称
			String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
			// 如果是抽象BeanDefinition
			if (candidate instanceof AbstractBeanDefinition) {
				postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
			}
			// 如果是注解BeanDefinition
			if (candidate instanceof AnnotatedBeanDefinition) {
				AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
			}
			// 检查给定的候选BeanDefinition,确定相应的BeanDefinition是否需要注册或者是否和
			// 已经存在的定义发生了冲突。
			if (checkCandidate(beanName, candidate)) {
				BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
				definitionHolder =
						AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
				beanDefinitions.add(definitionHolder);
				registerBeanDefinition(definitionHolder, this.registry);
			}
	}
}

补充一下:
AbstractBeanDefinition、AnnotatedBeanDefinition都是spring框架中定义和处理BeanDefinition的类,他们在SpringIOC容器的核心机制中有重要的地位。文章来源地址https://www.toymoban.com/news/detail-795041.html

  • 1. AbstractBeanDefinition:
    • 是个抽象类,实现了 BeanDefinition 接口,为BeanDefinition提供了一些通用的方法和属性。
    • 提供了BeanDefinition的基本结构,如作用域scope,初始化方法,销毁方法、依赖项管理等元数据信息的存储和操作
    • 子类有:RootBeanDefinition、GenericBeanDefinition
  • 2. AnnotatedBeanDefinition:
    • 该类封装了一个被注解标注的类的信息,并能够从类上的注解提取Bean的元数据,如作用域、生命周期回调方法等。
    • 在基于注解的配置环境下,Spring会使用 AnnotatedBeanDefinitionReader 或者 ClassPathBeanDefinitionScanner 等工具将带有注解的类转换为 AnnotatedBeanDefinition 对象并注册到IoC容器中。

7. postProcessBeanDefinition

protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
	beanDefinition.applyDefaults(this.beanDefinitionDefaults);
		if (this.autowireCandidatePatterns != null) {
			beanDefinition.setAutowireCandidate(PatternMatchUtils.
						simpleMatch(this.autowireCandidatePatterns, beanName));
		}
}

8. 注册bean定义

protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
	BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}

到了这里,关于【Spring类路径Bean定义信息扫描】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring中自定义Bean特性

    自定义扩展点 Spring框架提供了许多接口,可以使用它们来定制bean的性质。分组如下: 生命周期回调 ApplicationContextAware 和 BeanNameAware 其他 Aware 接口 为了与容器对bean生命周期的管理进行交互,可以实现Spring InitializingBean和DisposableBean接口。容器对前者调用afterPropertiesSet(),对后

    2024年02月16日
    浏览(38)
  • Spring 非自定义Bean注解

    1.概述 在xml中配置的Bean都是自己定义的, 例如:UserDaolmpl,UserServicelmpl。但是,在实际开发中有些功能类并不是我们自己定义的, 而是使用的第三方jar包中的,那么,这些Bean要想让Spring进行管理,也需要对其进行配置配置非自定义的Bean需要考虑如下两个问题: 被配置的B

    2024年02月13日
    浏览(36)
  • Spring Bean 作用域的定义

            在 Spring 配置中,我们可以通过 scope 属性来定义 Spring Bean 的作用域,可以接受 5 个内建的值,分别代表 5 种作用域类型,下面给大家详细总结一下: 1、singleton,用来定义一个 Bean 为单例,也就是说在 Spring loC 容器中仅有唯一 的一个实例对象,Spring 中的 Bean 默认

    2024年02月12日
    浏览(36)
  • 73.是否可以把我们所需的Bean都放入Spring­mvc子容器里面来管理(springmvc的spring-servlet.xml中配置全局扫描)?

    可以 , 因为父容器的体现无非是为了获取子容器不包含的bean, 如果全部包含在子容器完全用不到父容器了, 所以是可以全部放在springmvc子容器来管理的。 虽然可以这么做不过一般应该是不推荐这么去做的,一般人也不会这么干的。如果你的项目里有用到事物、或者aop记得也

    2024年02月21日
    浏览(46)
  • 解读spring中@Value 如何将配置转自定义的bean

    着急寻求解决方式的猿友先看这块 定义配置转化类 将转化类放入转化工厂 属性注入 spring在bean生命周期的属性赋值中,会根据属性的类型,匹配相应的转化类,执行转化,进而赋值。 不难看出,这些转化类仅执行转化逻辑,不存在线程安全问题,可以将其放入spring的IOC中,

    2024年02月13日
    浏览(40)
  • Spring5学习随笔-生命周期、自定义类型转换器、后置处理Bean

    学习视频:【孙哥说Spring5:从设计模式到基本应用到应用级底层分析,一次深入浅出的Spring全探索。学不会Spring?只因你未遇见孙哥】 指的是一个对象创建、存活、消亡的一个完整过程 由Spring负责对象的创建、存活、销毁,了解生命周期,有利于我们使用好Spring为我们创建

    2024年02月05日
    浏览(68)
  • 【Java Spring】SpringBoot Bean详解

    上一节我们介绍了五大类注解,这一节介绍方法注解@Bean,@Bean作用的对象是方法, 该注解需要搭配五大类注解同时进行使用 ,因为类方法的数量远远大于类的数量,如果使用@Bean注解标记方法的类没有被标记,那么Spring Boot项目在启动时需要遍历所有的类的所有方法,开销无

    2024年04月27日
    浏览(37)
  • Spring boot项目java bean和xml互转

    工作中需要给下游第三方收费系统做数据挡板,由于下游系统使用的是 soap webservice ,里面涉及各种xml跟bean的互转,在此介绍一下使用的方法。 基于springboot搭建webservice的过程将会在下篇博客介绍 这里介绍两种方法. 使用 jackson 进行互转, Spring boot 项目自带的 json 和 bean 的互

    2024年01月19日
    浏览(49)
  • java面试题(23):Spring Bean如何保证并发安全

    1 问题分析 我们知道默认情况下,Spring中的Bean是单例的,所以在多线程并发访问的时候,有可能会出现线程安全问题。 2 解决方案 有几个方面的解决思路: 我们可以设置Bean的作用域设置为原型(prototype),这样每次从容器中获取该 Bean 的时候,都会创建一个新的实例,避免

    2024年01月18日
    浏览(42)
  • springboot扫描不到其他模块下定义的Bean

    springboot默认是不能扫描到其他依赖模块定义的Bean的。(默认扫描的是启动类所在包下的所有Bean)也就是在项目启动的不能将其他模块的Bean加载到spring容器 项目之间要有联系性 admin模块为springboot框架,其他的只是普通的maven项目,admin 默认是无法扫描到 framework模块里面的

    2023年04月26日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包