快捷搜索: 王者荣耀 脱发

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注解来指明哪个实现类作为首选进行自动装配注入。

经验分享 程序员 微信小程序 职场和发展