Spring中 @Primary注解的作用
下面是Primary注解的源码:
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates that a bean should be given preference when multiple candidates
* are qualified to autowire a single-valued dependency. If exactly one
* primary bean exists among the candidates, it will be the autowired value.
* ...
*/
@Target({
ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Primary {
}
上面注释大致含义是:当我们使用自动配置的方式注入Bean时,如果这个Bean有多个候选者,如果其中一个候选者具有@Primary注解修饰,该候选者会被选中,作为自动配置的值。
我们可以做一下实验:
我们创建一个CarController,在里面使用@Autowird自动注入一个ICarService的对象。
package com.lbb.controller;
import com.lbb.service.ICarService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/car")
public class CarController {
@Autowired
private ICarService carService;
@GetMapping(value = "/drive")
public void drive() {
this.carService.drive();
}
}
下面是ICarService接口,以及其两个实现类BMWCarService、AudiCarService。
package com.lbb.service;
public interface ICarService {
void drive();
}
package com.lbb.service.impl;
import com.lbb.service.ICarService;
import org.springframework.stereotype.Service;
@Service
public class BMWCarService implements ICarService {
@Override
public void drive() {
System.out.println("bmw drive");
}
}
package com.lbb.service.impl;
import com.lbb.service.ICarService;
import org.springframework.stereotype.Service;
@Service
public class AudiCarService implements ICarService {
@Override
public void drive() {
System.out.println("audi drive");
}
}
我们启动项目,由于存在两个ICarService的实现类,Spring不知道为我们注入哪一个,就会报如下的异常:
*************************** APPLICATION FAILED TO START *************************** Description: Field carService in com.lbb.controller.CarController required a single bean, but 2 were found: - audiCarService: defined in file [D:ideaprojects est argetclassescomlbbserviceimplAudiCarService.class] - BMWCarService: defined in file [D:ideaprojects est argetclassescomlbbserviceimplBMWCarService.class] Action: Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed Process finished with exit code 1
在打印出的信息中,它会提示推荐我们使用@Primary注解或@Qualifier注解来解决该问题。
下面我们就使用@Primary注解来进行处理,如下所示:
package com.lbb.service.impl;
import com.lbb.service.ICarService;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
@Primary
@Service
public class AudiCarService implements ICarService {
@Override
public void drive() {
System.out.println("audi drive");
}
}
此时启动项目,发现项目启动正常,说明Spring已经帮我们自动装配完成,我们请求一下CarController来看一下到底自动注入的是哪一个实现类。
通过控制台打印,我们可以看到是AudiCarService中的drive方法被触发了,说明Spring为我们自动注入的是经过@Primary注解修饰的AudiCarService。
所以@Primary注解的作用就是当一个接口存在多个实现类时,我们就可以通过@Primary注解来指明哪个实现类作为首选进行自动装配注入。
下一篇:
建立备份域控服务器,备份域控制器
