@Autowired@Resource@Qualifier区别

Posted bonniewss

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了@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、给方法参数注入时,可以独立使用。

 

以上是关于@Autowired@Resource@Qualifier区别的主要内容,如果未能解决你的问题,请参考以下文章