淘先锋技术网

首页 1 2 3 4 5 6 7

一、@Autowired注解

首先要知道,@Autowired注解可以对类成员变量、方法以及构造函数进行注释,省略通常XML方式注入时繁琐的步骤和大量的代码,完成组件的自动装配。
使用@Autowired注解时,需要了解一些东西:
    @Autowired
    private ColorService colorService;
①:默认优先按照类型去容器中查找对应的组件 — byType
Map<String, ColorService> array = ac.getBeansOfType(ColorService.class)
// map 的key为组件的name,value为组件的实例
②:若按照类型查找的组件只有一个的话,就么就将该组件装配给使用@Autowired注解的属性
③:若按照类型查找出来的组件有多个的话,那么将使用@Autowired注解的属性的名称作为组件的id去容器中查找 — byName
Object ob = ac.getBean("colorService");
④:若最后查询的结果为空的话,就会报异常。不过@Autowired有一个required属性,将之设置为false就可以忽略异常了,只是这样使用@Autowired注解注入的属性会是null。

下面进行一些测试:

首先定义一个ColorService接口:

public interface ColorService {
    void color();
}

再定义一个实现类:WhiteColorServiceImpl

@Service
public class WhiteColorServiceImpl implements ColorService {

    public void color() {
        System.out.println("WhiteColorServiceImpl...I'm White ...");
    }
}

之后定义一个ColorController类,在类中有一个ColorService类型的成员变量

@Controller
public class ColorController {

    @Autowired
    private ColorService colorService;

    public void color(){
        colorService.color();
    }
}

定义一个配置类,使之扫描到上述的service和controller类:

@Configuration
@ComponentScan({"com.baiding.controller","com.baiding.service.impl"})
public class AutowiredConfig {

    // 无代码 单纯配置文件
}

测试类:

    @Test
    void test09(){
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AutowiredConfig.class);

        Map<String, ColorService> array = ac.getBeansOfType(ColorService.class);
        System.out.println(array);

        ColorController ob2 = (ColorController) ac.getBean("colorController");
        ob2.color();
    }

结果:

{whiteColorServiceImpl=com.baiding.service.impl.WhiteColorServiceImpl@291caca8}
WhiteColorServiceImpl...I'm White ...
从结果看出来,以类型查找出来的组件只有一个,Spring直接将这个组件注入到了属性中。

接下来再定义一个BlackColorServiceImpl类,同时实现ColorService接口:

@Service
public class BlackColorServiceImpl implements ColorService {
    public void color() {
        System.out.println("I'm Black ...");
    }
}
使用@Service注解,组件默认id为类名首字母小写:blackColorServiceImpl
之后,改一下WhiteColorServiceImpl实现类的组件名称:colorService
@Service("colorService")
public class WhiteColorServiceImpl implements ColorService {

    public void color() {
        System.out.println("WhiteColorServiceImpl...I'm White ...");
    }
}

之后再进行测试的话结果是:

{blackColorServiceImpl=com.baiding.service.impl.BlackColorServiceImpl@4c39bec8, colorService=com.baiding.service.impl.WhiteColorServiceImpl@f79e}
WhiteColorServiceImpl...I'm White ...
可以看出,ColorService类型的组件有两个,按类型查找出多个组件的话,我们可以按照名称去找,即将colorService(Controller类声明的成员属性名)作为组件的id去容器中查找,上面结果可以看到有一个colorService名称的组件,它的实例是WhiteColorServiceImpl,那么Controller类输出的结果就可知了。

二、@Qualifier注解

​ 在上述的操作流程中,我们提供了一个ColorService接口,它的两个实现类分别是BlackColorServiceImpl以及WhiteColorServiceImpl,其中WhiteColorServiceImpl在使用@Service注解时为了实现@Autowired的自动装配效果,我们给它赋予了一个id为colorService(@Service(“colorService”))。

​ 我们可以实验一下,若我们不赋予这个组件id的话,当我们测试的时候,会发现服务器报错:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'colorController': Unsatisfied dependency expressed through field 'colorService'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.baiding.service.ColorService' available: expected single matching bean but found : blackColorServiceImpl,whiteColorServiceImpl

错误日志提示的很清楚,在容器注入的时候,由于发现了两个ColorService的实现类,系统无法判断注入哪个才是正确的,所以报错。

​ 这种情况下,我们就可以使用@Qualifier注解了,通过这个注解,我们可以实现在组件注入的时候我们自己手动注入哪一个组件。当然,前提是我们得知道要注入的组件的id。

​ 好了,最后修改一下采用@Autowired 注解注入组件的地方:

@Controller
public class ColorController {

    @Qualifier("blackColorServiceImpl")
    @Autowired
    private ColorService colorService;

    public void color(){
        colorService.color();
    }
}

​ 测试类不变,结果是:

{blackColorServiceImpl=com.baiding.service.impl.BlackColorServiceImpl@4c39bec8, whiteColorServiceImpl=com.baiding.service.impl.WhiteColorServiceImpl@f79e}
BlackColorServiceImpl... I'm Black ...
可以看出,我们通过@Qualifier手动将 blackColorServiceImpl这个组件注入了进去。