Spring - 对象的自动注入

spring版本:4.1.6.RELEASE

示例代码

接口

public interface UserService{}

实现类1

@Service("myUserService")
public class UserServiceImpl implements UserService{}

实现类2

@Service("wxUserService")
public class WxUserServiceImpl implements UserService{}

实现类3

@Service
public class ComUserServiceImpl implements UserService{}

Bean name

以上代码通过@Service指定Bean name,也可以通过bean标签的id属性指定Bean name。Bean name的规则是即使实现类实现了不同的接口,也不允许重复。否则将抛出异常如下
org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'xxxService' for bean class [com.xxx.service.Xxx1ServiceImpl] conflicts with existing, non-compatible bean definition of same name and class [com.xxx.service.Xxx2ServiceImpl]
这表示Xxx1ServiceImpl和Xxx2ServiceImpl实现类的Bean name是一样的,这是不允许的。
Bean name的默认值
实现类Bean name的默认值为实现类名称(首字母将自动转换为小些),如以上ComUserServiceImpl的Bean name则为comUserServiceImpl

@Autowired注入

通过@Autowird注解注入有以下两种情况

  1. 如果为接口仅找到一个实现类,则注入该实现类
  2. 如果为接口找到多个实现类,则根据注入的变量名称来匹配bean的名称,如果成功匹配则注入对应的bean。

根据以上规则,以下变量均能成功注入

@Controller
public class UserController {
	
	// 发现多个实现类,将变量名称wsUserService作为Bean name跟所有实现类的Bean name进行匹配,最终得到WsUserSeriviceImpl实例
	@Autowired
	private UserService wsUserService;

	// 发现多个实现类,将变量名称comUserServiceImpl作为Bean name跟所有实现类的Bean name进行匹配,最终得到ComUserServiceImpl实例
	@Autowired
	private UserService comUserServiceImpl;

	// 如果只有UserServiceImpl实现类,那么直接根据类型注入,该变量也会被成功注入值
	@Autowired
	private UserService us;
}

如果存在多个实现类,且变量名称没有跟任何实现类定义的名称匹配,则会抛出如下异常
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.xxx.service.XxxService] is defined: expected single matching bean but found 2

@Autowired(required=false)
@Autowired注解并不是表示不注入当前变量,或者说在多个实现类的情况下找不到对应Bean时则不注入(如果找不到依然会抛出异常),而是表示如果当前变量类型没有实现类则可以不注入,同样的情况如果required为true则会报错。

@Resource注入

@Resource注解有如下几种情况

  1. 什么都不指定,采用Bean name注入方式,在这里将变量名称作为Bean name进行匹配注入。
  2. 仅指定Bean name,采用Bean name注入方式
  3. 仅指定Bean type,采用Bean type注入方式
  4. 同时指定Bean name和Bean type,则进行双重校验,即指定的Bean type的Bean name恰好等于指定的Bean name。

根据以上规则,以下变量均能注入成功

@Controller
public class UserController {
	
	// 将变量名称wsUserService作为Bean name跟所有实现类的Bean name进行匹配,最终得到WsUserServiceImpl
	@Resource
	private UserService wsUserService;
	
	// 将name属性值wsUserService作为Bean name跟所有实现类进行匹配,最终得到WsUserServiceImpl
	@Resource(name="wsUserService")
	private UserService wsUserService2;

	// 将type属性值作为实例类符号引用跟所有实现类进行匹配,最终得到ComUserServiceImpl
	@Resource(type=ComUserServiceImpl.class)
	private UserService userService;

	// 同时指定name和type,先根据name找到对应的Bean,然后比对Bean的符号引用是否和指定的type相同,最终得到WsUserServiceImpl,如果不同则会抛出异常
	@Resource(name="wsUserService",type=WxUserServiceImpl.class)
	private UserService us;
	
	// 注入失败,Bean name为wsUserService的类为WsUserServiceImpl,与指定的type不一致,抛出异常
	@Resource(name="wsUserService",type=ComUserServiceImpl.class)
	private UserService us;

}

@Qualifier

Qualifier的中文意思是“形容”,这也就不难理解@Qualifier只是一个辅助注解,用于辅助@Autowired和@Resource进一步确定Bean,当通过@Autowired或@Resouce发现多个Bean或没有发现Bean时,@Qualifier对Bean的描述就成了Bean的唯一标识。所以@Qualifier需要和@Autowired或@Resource结合使用
根据@Qualifier的特性,可以用以下代码来进一步诠释

@Controller
public class UserController {

	// 通过@Autowired发现有多个实现类,通过us没有匹配到任何实现类,此时获取到到@Qualifier对实现类有其他形容,得到实现类的Bean name为wsUserService,最终可确认实现类为WsUserServiceImpl
	@Autowired
	@Qualifier("wsUserService")
	private UserService us;
	
	// @Resource通过us2没有发现实现类,此时获取到@Qualifier对实现类有其他描述,得到实现类的Bean name为comUserServiceImpl,最终可确认实现类为comUserServiceImpl
	@Resource
	@Qualifier("comUserServiceImpl")
	private UserService us2;
}

(完)

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值