Spring中,Service有多个实现类时准确注入方式
定义接口:TestService
public interface TestService {
String say();
}
实现类一:HelloServiceImpl
@Service
public class HelloServiceImpl implements TestService {
@Override
public String say() {
return "Hello";
}
}
实现类二:HiServiceImpl
@Service
public class HiServiceImpl implements TestService {
@Override
public String say() {
return "Hi";
}
}
准确注入指定实现类的方式
-
添加
@Qualifier("首字母小写的实现类类名")
指定//指定HelloServiceImpl的实现类 @Qualifier("helloServiceImpl") @Autowired //或者@Resource private TestService testService;
-
变量名写成对应的首字母小写的实现类类名
@Autowired //或者@Resource private TestService helloServiceImpl;
-
给将要实现的类上@Service注解起名,并在注入时使用这个属性值
@Service("testService") public class HelloServiceImpl implements TestService { ... ----------------- @Autowired //或者@Resource private TestService testService;
-
使用@Resource注解注入,指明name属性值为:首字母小写的实现类类名
@Resource(name = "helloServiceImpl") private TestService testService;
-
使用@Resource注解注入,指明type属性值为:实现类类名.class
@Resource(type = HelloServiceImpl.class) private TestService testService;
拓展:@Resource和@Autowired
1. @Autowired
用来自动装配对象,通过类型(byType)的方式自动装配。有一个属性required,默认值为true,表示注入的bean必须存在,如果注入一个容器中没有的bean,启动服务器时会报错导致无法启动,设置属性值required为false时,表示忽略当前要注入的bean,有则注入,没有则跳过。
当存在多个相同的bean时,比如最常见的接口有多个实现类:
public interface HelloService {
}
@Service
public class HelloService1 implements HelloService{
}
@Service
public class HelloService2 implements HelloService{
}
或者不同的包下有相同的bean:
package com.example.a;
@Component
public class Test{
}
package com.example.b;
@Component
public class Test{
}
这种情况下当使用@Autowire注入时会提示只需要一个bean,但找到了多个,这时有两种解决方案:
- 在@Autowire注解的地方添加
@Qualifier("bean的名称")
。 - 在bean的上面添加@Primary,让默认使用具有@Primary注解的bean。
@Autowire作用范围:构造器、方法、参数、成员变量、注解。
2. @Resource
用来自动装配对象,默认通过byName的方式自动装配。常用属性为name和type,当指定name属性时,会在上下文中找名称匹配的bean进行装配,不存在则抛出异常。当指定type属性时,会在上下文中找类型匹配的bean进行装配。
public interface HelloService {
}
@Service
public class HelloService1 implements HelloService{
}
@Service
public class HelloService2 implements HelloService{
}
当要使用HelloService1的bean时,可以通过以下集中方式实现:
-
通过指定name属性
@Resource(name = "helloService1") private HelloService helloService;
-
通过指定type属性
@Resource(type = HelloService1.class) private HelloService helloService;
-
HelloService1上添加@Primary注解
3. @Autowired和@Resouce的区别
-
@Autowired默认按byType自动装配,@Resource默认byName自动装配。
-
@Autowired只有一个属性:required,表示是否开启自动注入,默认true。而@Resource有多个属性,其中最重要的两个参数是:name 和 type。
-
@Autowired如果要使用byName,需要和@Qualifier一起使用。而@Resource如果指定了name,则用byName自动装配,如果指定了type,则用byType自动装配。
-
@Autowired能够用在:构造器、方法、参数、成员变量和注解上,而@Resource能用在:类、成员变量和方法上。
-
@Autowired是spring定义的注解,而@Resource是JSR-250定义的注解。
举例:
用在变量上:
//当TestService接口没有实现类时,属性值为true时无法启动,为false时可以启动,testService为null
@Autowired(required = true)
private TestService testService;
用在方法上: