Spring - 对象的自动注入

版权声明:写文章辛苦,请不要复制粘贴,如果要,请注明来处 https://blog.csdn.net/u012627861/article/details/86510194

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;
}

(完)

猜你喜欢

转载自blog.csdn.net/u012627861/article/details/86510194