@Autowired、@Resource、@Qualifier区别
@Autowired
1、属于spring的注解,如果不想和Spring耦合的太紧,就不推荐使用。
2、默认情况下,要求依赖对象必须存在,不能为null。如果允许为空,那么设置属性值required为false。
情形1:
public interface 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、给方法参数注入时,可以独立使用。