0
点赞
收藏
分享

微信扫一扫

@Autowired/@Resource 彻底搞明白

jjt二向箔 2022-03-30 阅读 23
java
//1、 直接获取实现类serviceImpl的bean也是可以的;
//2、 至于加一层接口的原因:一是AOP程序设置思想指导,给别人调用的接口,调用者只想知道方法和功能,而对于这个方法内部逻辑怎么实现的并不关心;二是可以降低各个模块间的关联,实现松耦合、程序分层、高扩展性,使程序更加灵活,他除了在规范上有卓越贡献外,最精髓的是在多态上的运用;继承只能单一继承,接口却可以多实现
//3、 当业务逻辑简单,变更较少,项目自用时,省略掉接口直接使用实现类更简单明了;反之则推荐使用接口;
public interface TestService {

    public String test();
}
@Service("testServiceImpl1")
public class TestServiceImpl1 implements TestService{

    @Override
    public String test() {
        return "TestServiceImpl1";
    }
}

@Service("testServiceImpl2")
public class TestServiceImpl2 implements TestService{

    @Override
    public String test() {
        return "TestServiceImpl2";
    }
}

//2、 通过在实现类上添加@Primary注解来指定默认加载类
//这样如果在使用@Autowired/@Resource获取实例时如果不指定bean的名字,
// 就会默认获取TestServiceImpl3的bean,如果指定了bean的名字则以指定的为准。

@Service("testServiceImpl3")
@Primary
public class TestServiceImpl3 implements TestService{

    @Override
    public String test() {
        return "TestServiceImpl3";
    }
}

public class AutowareAndResourceTestController {



//    后来才知道,并没有注入接口的bean,只注入了实现类serviceImpl的bean,接口只是用来接收的,这里就要说到@Autowired/@Resource的注入原理了:@Autowired是Spring的注解,Autowired默认先按byType,如果发现找到多个bean,则,又按照byName方式比对,如果还有多个,则报出异常;@Resource 是JDK1.6支持的注解,默认按照名称(Byname)进行装配, 如果没有指定name属性,当注解写在字段上时,默认取字段名,按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
//    再来说Controller获取实例的过程:使用@Autowired,程序在spring的容器中查找类型是TestService的bean,刚好找到有且只有一个此类型的bean,即testServiceImpl,所以就把testServiceImpl自动装配到了controller的实例testService中,testService其实就是TestServiceImpl实现类;
//    如果使用的是@Resource,则是先在容器中查找名字为testService的bean,但并没有找到,因为容器中的bean名字是TestServiceImpl(如果@Service没指定bean的value属性,则注入bean的名字就是类名,如果指定了则是指定的名字),然后再通过类型查找TestService类型的bean,找到唯一的了个TestService类型bean(即TestServiceImpl),所以就自动装配实例成功了。
//    注:
//    byName 通过参数名 自动装配,如果一个bean的name 和另外一个bean的 property 相同,就自动装配。
//    byType 通过参数的数据类型自动自动装配,如果一个bean的数据类型和另外一个bean的property属性的数据类型兼容,就自动装配
//    效率上来说@Autowired/@Resource差不多,不过推荐使用@Resource一点,因为当接口有多个实现时@Resource直接就能通过name属性来指定实现类,而@Autowired还要结合@Qualifier注解来使用,且@Resource是jdk的注释,可与Spring解耦。


    //1、 通过指定bean的名字来明确到底要实例哪一个类

    @Autowired
    @Qualifier("testServiceImpl1")
    private TestService testService1;

    @Autowired
    @Qualifier("testServiceImpl2")
    private TestService testService2;

    @Autowired
    @Qualifier("testServiceImpl3")
    private TestService testService3;


    //2、@Resource可直接通过指定name属性的值即可,不过也可以使用@Qualifier(有点多此一举了...)
//    @Resource(name = "testServiceImpl")
//    private TestService testService;
    //3、@Resource如果不显示的指定name值,就会自动把实例变量的名称作为name的值的,所以也可以直接这样写:

    @Resource
    private TestService testServiceImpl1;

    @Resource
    private TestService testServiceImpl2;

    @Resource
    private TestService testServiceImpl3;

    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index() {
        System.out.println("testService1:"+testService1.test());
        System.out.println("testService2:"+testService2.test());
        System.out.println("testService3:"+testService3.test());
        System.out.println("testServiceImpl1:"+testServiceImpl1.test());
        System.out.println("testServiceImpl2:"+testServiceImpl2.test());
        System.out.println("testServiceImpl3:"+testServiceImpl3.test());

//         运行结果
//        testService1:TestServiceImpl1
//        testService2:TestServiceImpl2
//        testService3:TestServiceImpl3
//        testServiceImpl1:TestServiceImpl1
//        testServiceImpl2:TestServiceImpl2
//        testServiceImpl3:TestServiceImpl3

        return null;
    }
举报

相关推荐

0 条评论