@Autowired
在使用spring開發過程中,我們基本上都是使用 @Autowired 這個注解,用來注入已有的 bean。當 spring 中管理兩個類型一樣的 bean 時,再進行注入時會報錯:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.pb.spring.Spring5AutowiredQualifierApplicationTests': Unsatisfied dependency expressed through field 'user3'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.pb.spring.domain.User' available: expected single matching bean but found 2: user1,getUser2
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
required 屬性
@Autowired(required=true):當使用 @Autowired 注解的時候,其實默認就是@Autowired(required=true),表示注入的時候,該 bean 必須存在,否則就會注入失敗。
@Autowired(required=false):表示忽略當前要注入的 bean,如果有直接注入,沒有跳過,不會報錯。
@Primary
看下面代碼,@Primary 表示當遇到系統中有兩個User類型時,優先使用 @Primary 注解的這個進行注入。
import com.pb.spring.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class UserConfig {
@Bean(name = "user1")
public User getUser1(){
return new User("theodore",25);
}
@Primary
@Bean(name = "user2")
public User user2(){
return new User("james",25);
}
}
import com.pb.spring.domain.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class Spring5AutowiredQualifierApplicationTests {
@Autowired(required = false) //一般在開發環境,不確定是否能注入時用
private User user1;
@Autowired
@Qualifier(value = "user1")
private User user2;
@Autowired
private User user3;
@Test
public void testAuto() {
System.out.println(user2.getName());
System.out.println(user1.getName());
System.out.println(user3.getName());
}
}
@Autowired:spring 中有兩種注入方式,by type/by name,@Autowired 使用 byType 注入,當出現兩個類型一樣的時候,可以顯示的用 @Qualifier 指定名稱,表明用 by name 方式進行注入。否則會注入 @Primary 那個類。如果沒有指定則會報錯。 當不確定系統中是否能注入時,可以使用 required=false,不會強制注入。
@Resource
spring 不但支持自己定義的 @Autowired 注解,還支持幾個由 JSR-250 規范定義的注解,它們分別是 @Resource、@PostConstruct 以及 @PreDestroy。
@Resource 的作用相當于 @Autowired,只不過 @Autowired 按 byType 自動注入,而 @Resource 默認按 byName 自動注入罷了。@Resource 有兩個屬性是比較重要的,分是 name 和 type,Spring 將 @Resource 注解的name屬性解析為 bean 的名字,而 type 屬性則解析為 bean 的類型。所以如果使用 name 屬性,則使用 byName 的自動注入策略,而使用 type 屬性時則使用 byType 自動注入策略。如果既不指定 name 也不指定 type 屬性,這時將通過反射機制使用 byName 自動注入策略。
@Resource 裝配順序
1. 如果同時指定了 name 和 type,則從 Spring 上下文中找到唯一匹配的 bean 進行裝配,找不到則拋出異常
2. 如果指定了 name,則從上下文中查找名稱(id)匹配的 bean 進行裝配,找不到則拋出異常
3. 如果指定了 type,則從上下文中找到類型匹配的唯一 bean 進行裝配,找不到或者找到多個,都會拋出異常
4. 如果既沒有指定 name,又沒有指定 type,則自動按照 byName 方式進行裝配;如果沒有匹配,則回退為一個原始類型進行匹配,如果匹配則自動裝配;
@Autowired 與 @Resource的區別:
1、 @Autowired 與 @Resource 都可以用來裝配 bean. 都可以寫在字段上,或寫在setter方法上。
2、 @Autowired 默認按類型裝配(這個注解是屬于 spring 的),默認情況下必須要求依賴對象必須存在,如果要允許 null 值,可以設置它的 required 屬性為 false,如:@Autowired(required=false) ,如果我們想使用名稱裝配可以結合 @Qualifier 注解進行使用,如下:
@Autowired()@Qualifier("baseDao")
private BaseDao baseDao;
3、@Resource(這個注解屬于 J2EE 的),默認按照名稱進行裝配,名稱可以通過 name 屬性進行指定,如果沒有指定 name 屬性,當注解寫在字段上時,默認取字段名進行安裝名稱查找,如果注解寫在 setter 方法上默認取屬性名進行裝配。當找不到與名稱匹配的 bean 時才按照類型進行裝配。但是需要注意的是,如果 name 屬性一旦指定,就只會按照名稱進行裝配。
@Resource(name="baseDao")
private BaseDao baseDao;
推薦使用:@Resource 注解在字段上,這樣就不用寫 setter 方法了,并且這個注解是屬于 J2EE 的,減少了與 spring 的耦合。這樣代碼看起就比較優雅。