@Primary注解 在spring中的作用

本文介绍了在Spring中,当存在多个相同类型的Bean时,@Primary注解的作用是标记默认首选的Bean进行自动装配。通过源码解析和实例展示,解释了如何使用@Primary和@Qualifier解决自动注入冲突的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在spring 中使用注解,常使用@Autowired, 默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种的情况下 @Primary 的作用就出来了。

Primary可以理解为默认优先选择,不可以同时设置多个,内部实质是设置BeanDefinition的primary属性

注解备注
@Primary优先方案,被注解的实现,优先被注入
@Qualifier先声明后使用,相当于多个实现起多个不同的名字,注入时候告诉我你要注入哪个

首先看下源码: 

 
org.springframework.context.annotation
Annotation Type Primary
 
 
@Target(value={TYPE,METHOD})
 @Retention(value=RUNTIME)
 @Inherited
 @Documented
public @interface Primary
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.
This annotation is semantically equivalent to the <bean> element's primary attribute in Spring XML.
May be used on any class directly or indirectly annotated with @Component or on methods annotated with @Bean.
Example
 @Component
 public class FooService {
 
     private FooRepository fooRepository;
 
     @Autowired
     public FooService(FooRepository fooRepository) {
         this.fooRepository = fooRepository;
     }
 }
 
 @Component
 public class JdbcFooRepository {
 
     public JdbcFooService(DataSource dataSource) {
         // ...
     }
 }
 
 @Primary
 @Component
 public class HibernateFooRepository {
 
     public HibernateFooService(SessionFactory sessionFactory) {
         // ...
     }
 }
 
Because HibernateFooRepository is marked with @Primary, it will be injected preferentially over the jdbc-based variant assuming both are present as beans within the same Spring application context, which is often the case when component-scanning is applied liberally.
Note that using @Primary at the class level has no effect unless component-scanning is being used. If a @Primary-annotated class is declared via XML, @Primary annotation metadata is ignored, and <bean primary="true|false"/> is respected instead.
Since:
3.0
Author:
Chris Beams
See Also:
Lazy, Bean, ComponentScan, Component

使用实例 
一:@Qualifier

接口:

public interface EmployeeService {
    public EmployeeDto getEmployeeById(Long id);
}

接口对应的两个实现类:EmployeeServiceImpl和EmployeeServiceImpl1:接口对应的两个实现类:EmployeeServiceImpl和EmployeeServiceImpl1:

@Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService {
    public EmployeeDto getEmployeeById(Long id) {
                return new EmployeeDto();
     }
}
@Service("employeeService1")
public class EmployeeServiceImpl1 implements EmployeeService {
    public EmployeeDto getEmployeeById(Long id) {
         return new EmployeeDto();
    }
}

      这个时候就要用到@Qualifier注解了,qualifier的意思是合格者,通过这个标示,表明了哪个实现类才是我们所需要的,我们修改调用代码,添加@Qualifier注解,需要注意的是@Qualifier的参数名称必须为我们之前定义@Service注解的名称之一! 

@Controller
@RequestMapping("/emplayee.do")
public class EmployeeInfoControl {
    
    @Autowired
    @Qualifier("employeeService")
    EmployeeService employeeService;
    
    @RequestMapping(params = "method=showEmplayeeInfo")
    public void showEmplayeeInfo(HttpServletRequest request, HttpServletResponse response, EmployeeDto dto) {
            //#略
    }
}


二、@Primary:和@Qualifier 一样,@Primary也一样,使用场景经常是:在spring 中使用注解,常使用@Autowired, 默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种的情况下 @Primary 的作用就出来了。

简单例子:

接口:

public interface Singer {
    String sing(String lyrics);
}


有下面的两个实现类: 

@Component // 加注解,让spring识别
public class MetalSinger implements Singer{
 
    @Override
    public String sing(String lyrics) {
        return "I am singing with DIO voice: "+lyrics;
    }
}
@Primary
@Component
public class OperaSinger implements Singer{
 
    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics;
    }
}

故:
在spring容器中,如果同一个类型有多个实例,但我们需要注入一个的时候,我们必须采取措施,不然spring容器会报错:....required a single bean, but 2 were found:.........

有时候我们能保证同一个类型在spring容器中只有一个实例,有时候我们保证不了,此时不讨论by name注入。这个时候要使用@Primary注解。

如有不足望不吝赐教!!!
 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值