zoukankan      html  css  js  c++  java
  • @Autowired、@Resource、@Qualifier区别

     

    @Autowired

    1、属于spring的注解,如果不想和Spring耦合的太紧,就不推荐使用。

    2、默认情况下,要求依赖对象必须存在,不能为null。如果允许为空,那么设置属性值required为false。

    3、默认按照类型装配(byType)。到底什么是类型装配,看下边的例子:

    情形1:

    public interface UserService {
    }

    @Service
    public class UserServiceImpl implements UserService {
    }

    @Service
    public class UserServiceImpl2 implements UserService {
    }

    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class Test {
       @Autowired
       private UserService userService;
    }

    分析:在上边的测试类中使用@Autowired注入时,编辑器会报错:

    Could not autowire. There is more than one bean of 'UserService' type.
    Beans:
    userServiceImpl   (UserServiceImpl.java)
    userServiceImpl2   (UserServiceImpl2.java)

    原因是,@Autowired是默认按照类型注入的,它就告诉代码,我就需要一个UserService类型的类就行,但是代

    码却有两个UserService类型的类。这时,@Autowired还可以按照名称(userService)注入,但是也没有满足的bean,就报错了。

    情形2:

    public interface UserService {
    }

    @Service("userService")
    public class UserServiceImpl implements UserService {
    }

    @Service
    public class UserServiceImpl2 implements UserService {
    }

    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class Test {
      @Autowired
      private UserService userService;
       
      @org.junit.Test
      public void test1(){  
      System.out.println(userService);
      }
    }

    打印:
    demo.springboot.Service.UserServiceImpl@47b11ec7

    分析:这时@Autowired是按照名称注入的。

    情形3:

    public interface UserService {
    }

    @Service("myUserService")
    public class UserServiceImpl implements UserService {
    }

    @Service
    public class UserServiceImpl2 implements UserService {
    }

    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class Test {
      @Autowired
      @Qualifier("myUserService")
      private UserService userService;
       
      @org.junit.Test
      public void test1(){  
      System.out.println(userService);
      }
    }

    打印:
    demo.springboot.Service.UserServiceImpl@47b11ec7

    分析:这时如果UserServiceImpl有个别名”myUserService“,那么@Autowired需要和 @Qualifier配合使用,然后根据@Qualifier中的属性值,按照名称注入。

    情形4:

    public interface UserService {
    }

    @Service
    public class UserServiceImpl implements UserService {
    }

    @Service
    @Primary
    public class UserServiceImpl2 implements UserService {
    }

    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class Test {
      @Autowired
      private UserService userService;
       
      @org.junit.Test
      public void test1(){  
      System.out.println(userService);
      }
    }

    打印:
    demo.springboot.Service.UserServiceImpl2@6a756082

    分析:如果在UserServiceImpl或者UserServiceImpl2上加上@Primary,就有了一个优先的顺序,就会注入加了@Primary注解的类

     

    @Resource

    1、属于J2EE JSR250规范的实现。所以建议使用@Resource注解,以减少代码和Spring之间的耦合。

    2、默认按照名称装配(byName),什么是安装名称装配,看下面的例子:

    情形1:

    public interface UserService {
    }

    @Service
    public class UserServiceImpl implements UserService {
    }

    @Service
    public class UserServiceImpl2 implements UserService {
    }

    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class Test {
      @Resource
      private UserService userService;

      @org.junit.Test
      public void test1() {
          System.out.println(userService);
      }
    }

    分析:执行代码会报错:

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'demo.springboot.Test': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'demo.springboot.Service.iface.UserService' available: expected single matching bean but found 2: userServiceImpl,userServiceImpl2

    这个报错很明显,虽然编译器在起初没有报错,但是由于@Resource是默认按照名称注入的,@Resource想要一个bean的name是userService的,但是却没有,UserServiceImpl和UserServiceImpl2的beanName默认为类名小写。所以这时匹配不上名称,就会按照类型注入,但是却发现两个类型UserService的类,所以报错了(expected single matching bean but found 2)。

    情形2:

    public interface UserService {
    }

    @Service("userService")
    public class UserServiceImpl implements UserService {
    }

    @Service
    public class UserServiceImpl2 implements UserService {
    }

    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class Test {
      @Resource
      private UserService userService;

      @org.junit.Test
      public void test1() {
          System.out.println(userService);
      }
    }

    打印:
    demo.springboot.Service.UserServiceImpl@727320fa

    分析:给UserServiceImpl的beanName写为userService,这时@Resource按照name注入了。

    情形3:

    public interface UserService {
    }

    @Service
    @Primary
    public class UserServiceImpl implements UserService {
    }

    @Service
    public class UserServiceImpl2 implements UserService {
    }

    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class Test {
      @Resource
      private UserService userService;

      @org.junit.Test
      public void test1() {
          System.out.println(userService);
      }
    }

    打印:
    demo.springboot.Service.UserServiceImpl@44784e2f

    分析:加了@Primary,@Resource就可以按照类型注入了。

     

    @Qualifier

    1、在给字段注入时,不能独立使用,必须和@Autowired配合使用。

    2、给方法参数注入时,可以独立使用。

     

  • 相关阅读:
    Java编程之委托代理回调、内部类以及匿名内部类回调(闭包回调)
    JavaEE开发之记事本完整案例(SpringBoot + iOS端)
    JavaEE开发之SpringBoot整合MyBatis以及Thymeleaf模板引擎
    JavaEE开发之SpringBoot工程的创建、运行与配置
    JavaEE开发之SpringMVC中的自定义消息转换器与文件上传
    Scala.js v0.1 发布,在浏览器直接运行 Scala
    如何编写 Cloud9 JavaScript IDE 的功能扩展
    在 Cloud 9 中搭建和运行 Go
    MicroPHP 2.2.0 发布
    StrongSwan 5.1.1 发布,Linux 的 IPsec 项目
  • 原文地址:https://www.cnblogs.com/BonnieWss/p/12207123.html
Copyright © 2011-2022 走看看