前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring 中的自动装配,如果遇到多个实例如何处理?

Spring 中的自动装配,如果遇到多个实例如何处理?

作者头像
水货程序员
修改2018-12-03 16:17:24
6.1K0
修改2018-12-03 16:17:24
举报
文章被收录于专栏:javathingsjavathings

Spring 中的自动装配,如果遇到多个实例如何处理?

标记了@Autowired 注解的字段/方法,会由 Spring 容器自动的赋值一个实例化的对象。@Autowired 总是采用 byType 的方式实现自动装配,只要找到需要装配的类型的实例就行了。有时候 Spring 容器中,同一个类型的实例有多个,那么可能会出现异常,这个时候就需要精确的自动装配,需要用到@Qualifier 注解。

示例

有 2 个类,User 和 Company。

Company

代码语言:javascript
复制
package com.learn.entity;
import org.springframework.stereotype.Component;
 
@Component
public class Company {
 
	public Company() {
		System.out.println("init Company...");
	}
 
	private Integer companyCode = this.hashCode();
 
	public Integer getCompanyCode() {
		return companyCode;
	}
 
	public void setCompanyCode(Integer companyCode) {
		this.companyCode = companyCode;
	}
 
	@Override
	public String toString() {
		return "CompanyCode:" + this.companyCode;
	}
}

User

代码语言:javascript
复制
package com.learn.entity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
@Component
public class User {	
	public User()
	{
		System.out.println("init user...");
	}
	
	@Autowired
	private Company company;
	public Company getCompany() {
		return company;
	}
 
	public void setCompany(Company company) {
		this.company = company;
	}
}

上面的代码中,User 类中有一个 company 字段,标注了 Autowired,这就说明 Spring 容器中的 User 对象,company 的自动的值会被自动赋值,不会是 null。

配置类,定义自动扫描的路径。

代码语言:javascript
复制
package com.learn;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
 
@Configuration
@ComponentScan("com.learn")
public class Config {
 
}

Main 入口。

Main类

代码语言:javascript
复制
package com.learn;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.learn.entity.User;
 
public class Main {
	public static void main(String[] args) {
		//使用Config.class这个配置类
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
		//根据类型获取实例
		User user= applicationContext.getBean(User.class);
		System.out.println(user.getCompany());
		applicationContext.close();
	}
}

运行后输出: init Company… init user… CompanyCode:475779800 可以看到 User 类中的 company 字段并未主动初始化,但是却有值。

如果有 2 个 Bean 实例

上面的例子改一下

Config配置类

代码语言:javascript
复制
package com.learn;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.learn.entity.Company;
 
@Configuration
@ComponentScan("com.learn")
public class Config {
	@Bean
	public Company getCompany()
	{
		Company c=new Company();
		c.setCompanyCode(99999);
		return c;
	}
}

这时候,Spring 容器中出现了 2 个 Company 的实例,一个是自动扫描得到的,另一个是配置类中配置的。此时,Autowired 会将属性的名称作为组件的 id 去容器中查找,即用 company 作为实例的 id 去匹配实例,那么就又会匹配到自动扫描后生成的那个实例,因为那个实例的名字就是首字母小写的类名 company。

如果必须要以配置类中的实例为优先实例,那么只要在该实例上标注上@Primary 注解,表示默认首先该实例。

@Primary注解

代码语言:javascript
复制
@Configuration
@ComponentScan("com.learn")
public class Config {
 
	@Bean
	@Primary
	public Company getCompany()
	{
		Company c=new Company();
		c.setCompanyCode(99999);
		return c;
		
	}
}

注意,采用@Primary 后,此实例会优先加载,Main 方法运行后,得到的 companyCode 是 99999: init Company… init user… init Company… CompanyCode:99999

当然,也可以更直接的,指定自动绑定的实例。上面的 User 类,修改如下代码:

@Qualifier

代码语言:javascript
复制
@Autowired
@Qualifier("getCompany")
private Company company;

那么 company 注入的时候,会去找 id 为 getCompany 的实例,也就是会找到配置类中配置的实例。

总结

@Autowired 根据类型自动注入对象的实例,如果同一个类型的实例有多个,则会根据实例的 id 名去匹配,但这种不是最好的方式,建议直接用@Qualifier 注解指定需要注入的实例,或者用@Primary 注解标识出首选 Bean,减少不必要的干扰。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring 中的自动装配,如果遇到多个实例如何处理?
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档