Spring容器启动之注册类bean的注入

Spring AOT编译与GraalVM原生镜像:Java应用启动性能优化实战 即时编译(JIT)作为Java性能优化的核心机制,通过在运行时将字节码动态编译为本地机器码,实现了长期运行服务的高峰值性能。然而,其解释执行与动态优化模式也带来了显著的启动预热成本,这在云原生时代对快速启动和弹性伸缩提出了挑战。提前编译(AOT)技术通过将大量运行时工作前移至编译期,结合静态分析与字节码生成,为Java应用带来了启动速度和内存占用的革命性提升。Spring 6与Spring Boot 3将AOT支持提升到新高度,通过Bean定义推断、反射元数据收集等静态分析,生成高度优化的预编译蓝图。结合G 阅读详情

前言

本文旨在分析在Spring容器启动之时,如何将注册类bean注入IOC容器中,意义重大,详细看以下源码:

(1)BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
(2)definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
(3)BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

----该段代码位于org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean内

1.1 BeanDifinitionHolder的意义与作用

(1)这行代码是BeanDifinitionHolder类的构造器,其内部结构为:

public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName) {
		this(beanDefinition, beanName, null);
	}

很明显,这是调用了本类的另一个重载的构造器,源码为:

public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName, @Nullable String[] aliases) {
        //beanDefinition的非空判断,为空抛出一个运行时异常
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");
        //beanName的非空判断,为空抛出一个运行时异常
		Assert.notNull(beanName, "Bean name must not be null");
		this.beanDefinition = beanDefinition;
		this.beanName = beanName;
		this.aliases = aliases;
	}

说了这么多,不禁想问BeanDifinitionHolder类到底是用来干嘛的呢?下面这段英文应该会给你答案。

Holder for a BeanDefinition with name and aliases.
Can be registered as a placeholder for an inner bean

Can also be used for programmatic registration of inner bean
definitions. If you don't care about BeanNameAware and the like,
registering RootBeanDefinition or ChildBeanDefinition is good enough.

粗略翻译一下:BeanDifinitionHolder这个类是一个包含name和aliases(别名)的BeanDifinition的拥有者。
它可以注册为一个内部bean的占位符,也可以用来对内部bean定义的编程注册。
另外,如果你不关心BeanNameAware,则注册为RootBeanDefinition或ChildBeanDefinition就足够了。

1.2 

对代码(2)进行分析,下沉底层:

//scopeMetadata来自于之前对Scope标签处理中产生的数据
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

--->

static BeanDefinitionHolder applyScopedProxyMode(
			ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
        //获得在前面处理@Scope注释代码块中写入的proxyMode值,也就是获取其代理模式
		ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
        // 如果是没有代理的模式,直接返回definition
		if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
			return definition;
		}
        //proxyTargetClass是用来判断是不是使用了CGLIB这种代理方式
		boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
        //下面这个方法将会进入Spring-AOP包中,应用相应的代理,其实这个地方可以判断出待注入的
        //bean中到底使用了哪种代理方式,因为这个时候可以排除三个,只能剩下一种方式。详见1.3
        //该方法返回一个BeanDefinitionHolder实例对象,而且该对象包装了待注入的bean
		return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
	}

注释:ScopedProxyMode为一个枚举,定义如下:
    public enum ScopedProxyMode {

	/**
	 * Default typically equals {@link #NO}, unless a different default
	 * has been configured at the component-scan instruction level.
	 */
	DEFAULT,  //默认方式,同没代理的方式

	/**
	 * Do not create a scoped proxy.
	 * <p>This proxy-mode is not typically useful when used with a
	 * non-singleton scoped instance, which should favor the use of the
	 * {@link #INTERFACES} or {@link #TARGET_CLASS} proxy-modes instead if it
	 * is to be used as a dependency.
	 */
	NO,  //没有代理

	/**
	 * Create a JDK dynamic proxy implementing <i>all</i> interfaces exposed by
	 * the class of the target object.
	 */
	INTERFACES,  //java自带的jdk提供的动态代理方式

	/**
	 * Create a class-based proxy (uses CGLIB).  
	 */
	TARGET_CLASS;  //CGLIB代理

}

1.3

org.springframework.aop.scope.ScopedProxyUtils#createScopedProxy源码:

	/**
	 * Generate a scoped proxy for the supplied target bean, registering the target
	 * bean with an internal name and setting 'targetBeanName' on the scoped proxy.
	 * @param definition the original bean definition
	 * @param registry the bean definition registry
	 * @param proxyTargetClass whether to create a target class proxy
	 * @return the scoped proxy definition
	 */
	public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
			BeanDefinitionRegistry registry, boolean proxyTargetClass) {
        //获取待注册bean的名称,比如我这边是MyConfig这样的注册类,则名字为:MyConfig
		String originalBeanName = definition.getBeanName();
        //获得包装bean的BeanDifinition
		BeanDefinition targetDefinition = definition.getBeanDefinition();
        //获取目标bean的名称,规则是:“scopedTarget.”+originalBeanName 
		String targetBeanName = getTargetBeanName(originalBeanName);

		// Create a scoped proxy definition for the original bean name,
		// "hiding" the target bean in an internal target definition.
        // 生成一个代理工厂bean,并把它包装进RootBeanDefinition中
		RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
       // 为proxyDefinition添加设置属性
		proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
		proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
		proxyDefinition.setSource(definition.getSource());
		proxyDefinition.setRole(targetDefinition.getRole());

		proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
		if (proxyTargetClass) {
			targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
			// ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
		}
		else {
			proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
		}

		// Copy autowire settings from original bean definition.
		proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
		proxyDefinition.setPrimary(targetDefinition.isPrimary());
		if (targetDefinition instanceof AbstractBeanDefinition) {
			proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
		}

		// The target bean should be ignored in favor of the scoped proxy.
		targetDefinition.setAutowireCandidate(false);
		targetDefinition.setPrimary(false);

		// Register the target bean as separate bean in the factory.
		registry.registerBeanDefinition(targetBeanName, targetDefinition);

		// Return the scoped proxy definition as primary bean definition
		// (potentially an inner bean).

        //返回一个BeanDefinitionHolder实例对象,这个实例对象包装了proxyDefinition、originalBeanName
        //等信息
		return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
	}

1.4

对代码(3)进行分析,下沉底层:

/**
	 * Register the given bean definition with the given bean factory.
      //将给定的bean definition 注册进入给定的bean工厂中
	 * @param definitionHolder the bean definition including name and aliases
	 * @param registry the bean factory to register with
	 * @throws BeanDefinitionStoreException if registration failed
	 */
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
        //获取待注册bean的名称,比如注册类为MyConfig.class,则beanName为MyConfig
		String beanName = definitionHolder.getBeanName();
       //下面这行代码总得来说,逻辑为:
       //(1)先判断beanDefinitionMap的key为beanName的value为空?
       //(2)不为空,进行一些检查即可 
       //(3)为空,则需要插入beanName与beanDifinition这条数据
       //经过上述(1)(2)(3)完成了将待注入bean注入Spring容器的工作
       //该段逻辑详细分析见1.5
		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);
			}
		}
	}

1.5

registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
---->

void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException;

---->
查看其实现:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException 

源码如下:
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);
			}
		}
        //获取beanDefinitionMap中的beanNanme的key对象的vaule
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
        //不为空,则说明容器中已经存在了待注入的bean
		if (existingDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			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);
		}
		else {
            //不存在,则需要进行插入
             //注意,在维护beanDefinitionMap这样的Map结构同时,
             //还会维护beanDefinitionNames这样一个List结构,其中存放的是bean的名字
			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 {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				this.manualSingletonNames.remove(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}

	@Override
	public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		Assert.hasText(beanName, "'beanName' must not be empty");

		BeanDefinition bd = this.beanDefinitionMap.remove(beanName);
		if (bd == null) {
			if (logger.isTraceEnabled()) {
				logger.trace("No bean named '" + beanName + "' found in " + this);
			}
			throw new NoSuchBeanDefinitionException(beanName);
		}

		if (hasBeanCreationStarted()) {
			// Cannot modify startup-time collection elements anymore (for stable iteration)
			synchronized (this.beanDefinitionMap) {
				List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames);
				updatedDefinitions.remove(beanName);
				this.beanDefinitionNames = updatedDefinitions;
			}
		}
		else {
			// Still in startup registration phase
			this.beanDefinitionNames.remove(beanName);
		}
		this.frozenBeanDefinitionNames = null;

		resetBeanDefinition(beanName);
	}

需要特别注意的是,到此仅仅是完成了待注入bean的注入工作,并没有对bean进行实例化,所以到现在为止我们还不能获取实实在在的bean实例,该工作将在org.springframework.context.support.AbstractApplicationContext#refresh方法中完成。另,spring源码过于复杂,本人能力有限,不足之处,还望指正,在此谢过。

1.6 参考文献

【1】https://segmentfault.com/a/1190000017413393?utm_source=tag-newest

【2】https://www.bilibili.com/video/BV1tx411o77Z?p=5

【3】《Spring源码解析》

Spring源码-容器初始化与刷新 Spring容器启动 简单理解spring框架,首先就是一个框架,直白点讲就是提高效率的工具,好比工厂干活,以前是人机械式的工作,现在用上了机器,人只用去操作机器就行了。那么spring工具提供了一个大容器,每次工作前把需要的东西全放进去,用的时候去容器拿,不用像之前用的时候还要跑回去拿。框架终究只是一个工具,如果如何使用都不熟练,什么工具都不好上手,所以最重要的是基础。 大多数的框架都是一种套路,利用资源加载和反射,不断的加载配置文件,比如factories,handlers等等,value值往往就是对应 阅读详情

相关推荐

智能汽车竞赛摄像头处理(4)——摄像头循迹思路讲解

智能汽车竞赛摄像头处理(4)对摄像头循迹思路进行讲解。

weixin_62261692的博客 7057

Bean 'shiroFilter'; nested exception is java.lang.IllegalArgumentException: Bean name must not be em

SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener org.springframework.beans.factory.parsing.BeanDefinitionParsing

月光秦城 4762

PP生产订单的BADI增强 WORKORDER_UPDATE

我们的项目需求是: 1、 保存时检查工单BOM是否存在物料号相同的行项目,如果有则提示“物料& 重复,请检查工单BOM” 系统增强出口:PPCO0001,检查组件行项目是否有重复物料项 开始以为的增强增强看一下是用PPCO0001还是PPCO0007 后来找到了badi WORKORDER_UPDATE IF_EX_WORKORDER_UPDATE~BEFORE_UPDATE

ERP运维咨询(目标和成功) 4635

Spring中配置id或name相同的Bean可能引发的问题及解决方案

一、背景 如果再xml中配置了相同的<Bean>的ID或name可能会造成一些问题,今天我们来探讨一下并解决。 二、问题 1、在同一个xml中配置了相同的bean的id。EX: <?xml version="1.0" encoding="UTF-8"?> &...

chengwei0708的博客 1320

无人车路径规划方法汇总

无人车路径规划方法汇总

weixin_44380244的博客 2558

ABAP Secure Storage 在事务码 SM59 中的应用

系统管理人员在进行维护时,应关注相关日志信息,及时发现可能出现的安全异常,并针对不同安全等级的操作制定相应的备份与恢复策略,以降低潜在风险。该区域在设计上具备高度隔离性,仅允许经过授权的组件访问。保存后,系统会将密码存储在 Secure Storage 中,这种处理方式充分体现了 SAP 标准程序在安全设计上的考量。对于系统管理员而言,这种机制在日常维护与审计中提供了有力的支持,可以通过比对存储数据的哈希值或其他完整性校验手段,及时发现异常变动,保障系统长期稳定运行。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 673

maven 项目使用tomcat启动时报no bean named 'ordeServiceImpl' availabe

注:错误提示相同,但产生这个错误的原因有各种各样的,只供参考 出现这个问题时,我首先想到的是不是编译没有通过,查看target下是不是有编译成功的报错显示的那个类和配置文件是不是都编译成功,这一步排出掉后,在配置文件中是不是有些配置不正确 我的问题是pom.xml文件中有配置失误 ...

weixin_45454224的博客 264

RK3568平台(USB篇)USB HUB集线器

hub,集线器,连接在host与device之间的一种用于usb接口扩展的usb设备。可以将一个usb上行接口扩展为多个下行接口,使得一个host可以同时与多个device连接。一般来说,一块hub桥接芯片可扩展4个usb接口,而市面上的一拖七hub,其实使用了两块hub桥接芯片,其中一块hub桥接芯片的上行端口连接到另一块hub桥接芯片的下行端口。hub的上行端口面向host,下行端口面向device。在下行端口上,hub提供了设备接入检测和设备移除检测的能力,并给下行端口供电。

weixin_49303682的博客 964

eclipse tomcat启动失败个人解决方法

通过svn检出的项目由于已有.project文件,在检出时只能作为工作空间中的项目检出,导致在添加到Tomcat后报错启动失败报错信息未保留 在网上长时间查找资料后,终于解决,方案如下: 首先新建一个空服务器,双击会发现我们的Server Locations默认选中第一项 Use workspace metadata (dose not modify Tomcat installation)...

weixin_42238474的博客 6893

CVPR 2026 即插即用 | 注意力篇 | MSEF:超轻注意力,空间-通道双分支并行融合,既增强特征又抑制噪声!

Multinex提出了一种超轻量级微光图像增强框架,其核心创新是MSEF模块。MSEF采用双分支并行架构,结合空间局部特征(深度可分离卷积)和全局通道注意力(改进SE),通过Tanh激活实现特征增强与抑制。相比传统注意力模块,MSEF在几乎不增加计算量的情况下显著提升性能,特别适合轻量级网络和边缘设备部署。实验表明,该模块能有效提升PSNR约3dB,同时保持极低的参数量(0.7K-45K)。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 603

A-Frame引擎开发:A-Frame基础入门_(11).A-Frame物理引擎集成

在上一节中,我们学习了如何在A-Frame中创建基本的3D场景和交互元素。然而,为了使虚拟现实游戏更具真实感和互动性,物理引擎的集成是必不可少的。物理引擎可以模拟现实世界中的物理行为,如重力、碰撞、摩擦等,从而增强用户的沉浸感。物理引擎在虚拟现实游戏中的重要性不言而喻。它不仅能够模拟物体的运动和相互作用,还能为游戏提供更真实的反馈和体验。例如,当玩家在虚拟世界中推动一个物体时,物理引擎可以确保物体按照预期的方式移动,而不是简单地穿墙而过或突然消失。重力是物理引擎中最基本的特性之一。在A-Frame中,我们可

chenlz2007的博客 797

【SpringBoot】ioc容器生动解释

IOC容器是Spring框架的核心组件,相当于一个自动化管理的"对象仓库"。它通过控制反转(IOC)和依赖注入实现对象管理的自动化 - 开发者只需声明需要的组件(如用@Component标注),容器就会自动创建并维护这些对象及其依赖关系。这种机制将对象创建与使用的控制权交给框架,实现组件间的解耦,提高代码的可测试性和灵活性。比如餐厅系统中,厨师(Chef)和厨房(Kitchen)的依赖关系无需手动建立,通过@Autowired注解即可自动装配。IOC容器简化了对象生命周期管理,让开发者能

Z_W_H_的博客 953

金融行业大数据可视化:实时监控与风险预警系统构建

随着金融业务数字化转型,日均产生的交易数据、市场数据、客户行为数据呈指数级增长(单家银行日交易数据量可达TB级)。数据实时性不足(分钟级延迟难以应对高频交易风险)风险特征挖掘浅层(仅基于规则引擎,漏报率高达30%+)可视化分析能力薄弱(静态报表无法支持动态决策)本文聚焦构建具备毫秒级数据响应智能风险建模交互式可视化决策能力的新一代系统,覆盖数据采集、实时处理、多维可视化、智能预警四大核心模块,适用于银行、证券、保险等金融细分领域。章节核心内容技术亮点核心概念可视化系统架构/数据流模型。

AI天才研究院 1522

Spring之@Import注册组件

除了bean响容器中注册组件之外,还可以使用@Import注册 创建一个注册类 package spring; public class Color { } 在配置类中使用注解@Import注册 @Configuration @Import(Color.class)//@Import导入组件,容器中就会自动注册这个组件,id就是类名 public class MainConfig2 { } 写一个测试类测试一下 @Test public void Test3() { String[] nam

chd_sun的博客 167

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Spring注入Bean的四种方式,看这一篇就够了

1.通过xml配置注入bean

Harrison 2955

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

spring根据条件注入Bean

一、常用的注入spring Bean的几种方式: 1.常用的@controller、@Service、@Repository、@Configuration、@Component等注解,默认都会注入单例的Bean,如果这些类在启动类的同级包或同级包下面则会被自动注入,若不在,则需要加上@ComponentScan或者@ComponentScans将包名加入扫描才起作用 2.@Bean,也比较常用,一般通过构造方式返回一个类实例,然后会被spring加入IOC 3.@Import注解,可以直接将需要注入的

u010737670的博客 5119

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

3.2.11.Spring注入Bean到IOC的方式

在Spring中,有七种。

浩瀚银河 314

spring注册bean方式总结

spring注册bean的方式

weixin_43241706的博客 2328

【自定义注解】自定义注解实现Spring容器注入Bean(类似于mybatis的@MapperScans)

本文通过自定义注解@MyService和@,将SpringBoot项目中带有@MyService或包内的类注入到Spring容器中。@MyService注解@InheritedMyServiceScans注解这个注解有一个数组参数可以存放一个或者多个包的全路径。@Inherited作用就是在Spring启动时自动扫描项目中的类,并创建并注册它的bean定义,使得我们能在需要时从Spring上下文中取得所需的bean。

God_WZH的博客 1925

springboot复制bean_springboot注入bean有几种方式?

向springboot注册Bean有多种方式@ComponentScan@Bean@Import通过@ComponentScan注册BeanSpring容器会扫描@ComponentScan配置的包路径,找到标记@Component注解的类加入到Spring容器。效果等同于XML配置文件中的java8之后一个类可以标记多个@ComponentScan扫描规则@Component说明常见继承:- @...

weixin_39899691的博客 546

spring给容器中注入组件的几种方式

目录 环境搭建 <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>sprin...

weixin_46577306的博客 520

spring依赖注入

spring依赖注入 注册Bean @Configuration //告诉spring这是一个注册类 @Bean 给容器中注册一个bean,类型为返回值类型,id默认是用方法名作为id;可以指定value设置bean名称; @ComponentScan //自动扫描,value指定扫描的路径, @Scope //限制bean的作用域范围 singleton单实例,启动是创建容器 proto...

我爱吃果冻的博客 199

运行java显示没有注册类_java相关:Spring运行时动态注册bean的方法

java相关:Spring运行时动态注册bean的方法发布于 2020-3-17|复制链接摘记: 在spring运行时,动态的添加bean,dapeng框架在解析xml的字段时,使用到了动态注册,注册了一个实现了FactoryBean类!定义一个没有被Spring管理的Controller```javapublic class UserController implements Initializ...

weixin_30585729的博客 547

spring bean的注册讨论

注册spring bean的方法总结 在类上加@Component、@Service、@Named等注解。 在类上加@Configuration注解,类成员方法上加@Bean。 在spring.factories里配置EnableAutoConfiguration对应的类,在类方法上定义@Bean。应该算是@Configuration+@Bean的特化处理吧。EnableAutoConfiguration能根据应用程序的依赖和类路径自动配置所需的bean 。 在BeanFactoryPostProcess

tlxamulet的博客 243

SpringBoot —— Bean的注入方式

文章目录1、组件注解2、@Component + @Bean3、@Import(PlaceHolderClass)快速导入一个组件4、使用Spring提供的FactoryBean注入 1、组件注解 注解 描述 @Component 组件定义不清晰时候的注解 @Controller 控制器层 @Service 服务层 @Repository 数据层 注:添加注解的类需要与启动类在同一个包路径下,如果在别的包下,需要在 启动类 或 启动类所在包下的存在以上注解的类 中添加 @Co

Davis 5836
上一篇: Spring启动之CommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) 解析
下一篇: Spring源码分析之FactoryBean方式注入bean
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值