目錄
-
-
- 基于注解的容器配置
-
-
- 1. 使用@Autowired
- 2.使用@Order
- 3. 使用@Primary
- 4. 使用@Qualifier
- 5. 使用@Resource
- 6. 使用@Value
- 7. 使用@PostConstruct和@PreDestroy
-
-
基于注解的容器配置
注解配置和XML配置實作的功能是一樣的,隻是實作方式不同而已。并且,注解配置在XML配置之前執行。
首先通過在XML中通過配置可以隐式的注冊一些元件,當然你也可以顯式的定義bean。(注意引入context命名空間)
隐式注冊包含的元件有:
AutowiredAnnotationBeanPostProcessor
、
CommonAnnotationBeanPostProcessor
、
PersistenceAnnotationBeanPostProcessor
和
RequiredAnnotationBeanPostProcessor
。
1. 使用@Autowired
使用
@Autowired
實作注解式自動裝配。
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
//指定此依賴性是否為非必須,預設true。
boolean required() default true;
}
通常作用在變量上或方法上,首先按照byType注入,隻要容器中有唯一的bean對象類型相比對,則注入成功,若無比對,則報錯,若比對多個,則在其中再按照byName注入,若無比對,則報錯。此時set方法不是必須的了,見上文可知。
四種形式案例:
作用在構造方法上
public class UserServie {
private UserDao userDao;
@Autowired
public UserServie(UserDao userDao) {
this.userDao = userDao;
}
}
- 在單一構造方法場景下,即使不使用@Autowired注解,也會被用來進行自動裝配。
- 在單一構造方法場景下,使用@Autowired注入存在着特殊規則,如多元素注入(數組、集合、Map等),在沒有比對bean時允許為空解析。
- 在多個構造方法場景下,所有構造方法的@Autowired必須設定required為false,以便其都作為自動裝配的候選,自動裝配會選擇Spring容器比對bean可以滿足最大數量依賴項的構造方法,若無比對,則選擇主選項或預設項構造方法。
作用在set方法上
public class UserServie {
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
作用在多個參數方法上
public class UserServie {
private UserDao userDao;
private ClubDao clubDao;
@Autowired
public void prepare(UserDao userDao, ClubDao clubDao) {
this.userDao = userDao;
this.clubDao = clubDao;
}
}
作用在字段上
public class UserServie {
@Autowired
private UserDao userDao;
//@Autowired 也可以和構造方法混用
public UserServie(UserDao userDao) {
this.userDao = userDao;
}
}
- 在XML配置的自動裝配中,屬性是通過set方法進行set注入的,而在注解注入中注解作用在字段上則可以不需要set方法。其原因是:@autowired注解關閉了通路控制權限,不再需要通過set注入了,直接通過已開放的屬性通過Java反射機制進行注入(即使它是私有的)。
- 你還可以為複雜/集合類型進行注解注入,前提該類型bean以配置在容器中(建議在注入集合類型bean時,使用XML配置方式和注解配置方式混用)
Spring5版本中,你還可以在方法形參上使用
@Nullable
注解來使這個參數允許為空。
你也可以使用
@Autowired
注入一些可解析的依賴項:
BeanFactory
,
ApplicationContext
,
Environment
,
ResourceLoader
,
ApplicationEventPublisher
和
MessageSource
,或是其擴充接口
ConfigurableApplicationContext
、
ResourcePatternResolver
。
2.使用@Order
通過
@Order
注解使用在不同地方擁有不同的功能,數字越小優先級越高:
- 使用在@Bean方法或元件類上時,可以在注入時調整其優先級順序。(如對數組/集合類型進行注入時,集合項中的順序由
決定)@Order
- 使用在配置類中,可以調整這些配置類容器的初始化順序。
注意: @Order
并不會影響Bean的單例啟動順序(加載順序)。
3. 使用@Primary
由于byType方式自動裝配可能會比對多個候選對象,是以我們通常對于選擇需要更多的控制,我們可以使用
@Primary
實作候選優先權,當多個bean成為候選對象時,應優先考慮
@Primary
标記的bean。
//這是基于Java的容器配置方式
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... }
@Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
//這是基于注解的容器配置方式
@Primary
@Component
public class FirstMovieCatalog implements MovieCatalog{
// ...
}
當然,你也可以在XML中進行配置,見上文。
4. 使用@Qualifier
通過
@Qualifier
搭配
@Autowired
組合實作byName方式自動裝配。(不能單獨使用)
作用在字段上:
public class UserServie {
@Autowired
@Qualifier("userDao")
private ParentDao parentDao;
}
作用在方法參數上:
public class UserServie {
private ParentDao parentDao;
@Autowired
public void setUserDao(@Qualifier("userDao") ParentDao parentDao) {
this.parentDao = parentDao;
}
}
- 使用
并不意味着與byType無關,自動裝配其實還是先通過byType篩選出候選對象,再通過指定的限定符(@Qualifier值)找出指定對象的。如果要避開類型比對的過程,可以使用
@Qualifier
注解,後續會講解。
@Resource
- 如果你嘗試将來自@Bean方法的傳回結果注入到同一配置類中,建議将要注入bean的@Bean方法設定為靜态方法,将其與配置類執行個體和生命周期解耦合。原因是自動裝配會優先選擇其他配置類的候選對象,而本配置類的候選對象會放在最後選擇。
同時,你還可以通過泛型作為隐式的限定符來代替
@Qualifier
。
@Autowired
private Store<String> s1;
@Autowired
private Store<Integer> s2;
此外,你還可以自定義
@Qualifier
注解,詳見官方文檔
5. 使用@Resource
Spring也支援JSR-250中的
@Resource
注解進行自動裝配。它可以看作是byName形式的自動裝配,通過其屬性name來指定限定符。與
@Autowired
相比,它并沒有類型比對的過程,完全通過限定符進行比對。
public class UserServie {
@Resource(name="userDao")
private ParentDao parentDao;
public void setUserDao(ParentDao parentDao) {
this.parentDao = parentDao;
}
}
若你沒有寫name屬性,它預設的會按照字段名或set方法名進行比對。
6. 使用@Value
你可以通過
@Value
注解進行基本類型、String類型的注入。此外,它還支援${}和SpEL表達式。
注入字面量:
public class User{
@Value("張三")
private String name;
@Value("aa,bb,cc,dd")
private String[] alias;
//...
}
Spring提供的内置轉換器支援簡單類型和String類型的類型轉換,多個逗号分隔可以自動轉換為數組。
注入屬性檔案的屬性值:
public class User{
@Value("${userconfig.name}")
private String name;
//...
}
注入SpEL表達式:
public class User{
@Value("#{10+2}")
private int age;
//...
}
7. 使用@PostConstruct和@PreDestroy
你可以通過JSR-250生命周期的
@PostConstruct
和
@PreDestroy
來實作建立和銷毀時的回調方法。
@Resource、@PostConstruct和@PreDestroy注解都是由Bean識别的,而這個Bean一般通過隐式的注冊,也就是
CommonAnnotationBeanPostProcessor
<context:annotation-config/>
完成的。
需要注意的是,在JDK9中,整個javax.annotation注解包從Java源碼子產品分離出來,而在JDK11中完全移除,需要Maven進行依賴加入才能使用(wdnmd),同時JSR-330也是需要依賴加入才能使用的。