Spring中,Service有多个实现类时准确注入方式

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

准确注入指定实现类的方式

  1. 添加@Qualifier("首字母小写的实现类类名")指定

    //指定HelloServiceImpl的实现类
    @Qualifier("helloServiceImpl")
    @Autowired	//或者@Resource
    private TestService testService;
    
  2. 变量名写成对应的首字母小写的实现类类名

    @Autowired	//或者@Resource
    private TestService helloServiceImpl;
    
  3. 给将要实现的类上@Service注解起名,并在注入时使用这个属性值

    @Service("testService")
    public class HelloServiceImpl implements TestService {
    ...
        
    -----------------
    
    @Autowired	//或者@Resource
    private TestService testService;
    
  4. 使用@Resource注解注入,指明name属性值为:首字母小写的实现类类名

    @Resource(name = "helloServiceImpl")
    private TestService testService;
    
  5. 使用@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,但找到了多个,这时有两种解决方案:

  1. 在@Autowire注解的地方添加@Qualifier("bean的名称")
  2. 在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时,可以通过以下集中方式实现:

  1. 通过指定name属性

    @Resource(name = "helloService1")
    private HelloService helloService;
    
  2. 通过指定type属性

    @Resource(type = HelloService1.class)
    private HelloService helloService;
    
  3. HelloService1上添加@Primary注解

3. @Autowired和@Resouce的区别

  1. @Autowired默认按byType自动装配,@Resource默认byName自动装配。

  2. @Autowired只有一个属性:required,表示是否开启自动注入,默认true。而@Resource有多个属性,其中最重要的两个参数是:name 和 type。

  3. @Autowired如果要使用byName,需要和@Qualifier一起使用。而@Resource如果指定了name,则用byName自动装配,如果指定了type,则用byType自动装配。

  4. @Autowired能够用在:构造器、方法、参数、成员变量和注解上,而@Resource能用在:类、成员变量和方法上。

  5. @Autowired是spring定义的注解,而@Resource是JSR-250定义的注解。

举例:

用在变量上:

//当TestService接口没有实现类时,属性值为true时无法启动,为false时可以启动,testService为null
@Autowired(required = true)
private TestService testService;

用在方法上:

Spring中,Service有多个实现类时准确注入方式_第1张图片

你可能感兴趣的:(Spring,Boot,spring,java,后端)