@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、給方法參數注入時,可以獨立使用。