本文內容
@Resource實作依賴注入@Value詳細使用@PostConstruct@PreDestroy的使用
@Resource實作依賴注入
前面章節介紹了使用@Autowired注入依賴的詳細用法,感興趣的可以翻看前面的文章,Spring 還支持通過在欄位或 bean 的Setter方法上使用 JSR-250 @Resource 注解進行注入,
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource {
// 指定名稱
String name() default "";
}
基本使用
依賴組件定義
@Component
public class RepositoryA implements RepositoryBase {
}
@Component
public class RepositoryB implements RepositoryBase {
}
使用@Resource注入依賴
@Component
public class Service1 {
// 欄位
@Resource
private RepositoryA repositoryA;
private RepositoryB repositoryB;
// Setter方法
@Resource
public void setRepositoryB(RepositoryB repositoryB) {
this.repositoryB = repositoryB;
}
// ...
}
運行測驗
@org.junit.Test
public void test() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
Service1 service1 = context.getBean(Service1.class);
System.out.println(service1);
context.close();
}
// 結果
Service1{repositoryA=com.crab.spring.ioc.demo09.RepositoryA@1622f1b, repositoryB=com.crab.spring.ioc.demo09.RepositoryB@72a7c7e0}
@Resource和@Autowired的區別
- 使用范圍不同:
@Resource使用范圍是類欄位和Setter方法,@Autowired范圍更廣:類欄位、Setter方法、構造方法、方法引數, - 當依賴缺失時,
@Resource注入會報錯,@Autowired(required=false)可以避免報錯, @Resource有屬性可以指定依賴的bean名稱,@Autowired和@Qulifier也可以達到該效果,
@Value詳細使用
@Value 通常用于注入外部化屬性,在欄位或方法建構式引數級別使用的注釋,指示注解元素的默認值運算式,
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
// 實際值運算式如 #{systemProperties.myProp}
// 或屬性占位符如${my.app.myProp}
String value();
}
案例1
使用@Value注入配置屬性值
@Component
public class MovieRecommender {
private final String catalog;
public MovieRecommender(@Value("${catalog.name}") String catalog) {
this.catalog = catalog;
}
// ...
}
外部組態檔demo10/application.properties
catalog.name=MovieCatalog
容器中通過@PropertySource組態黨澩
@Configuration
@ComponentScan(basePackages = "com.crab.spring.ioc.demo10")
@PropertySource("classpath:demo10/application.properties")
public class AppConfig {
}
運行測驗
@org.junit.Test
public void test() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
MovieRecommender recommender = context.getBean(MovieRecommender.class);
System.out.println(recommender);
context.close();
}
// 結果
MovieRecommender{catalog='MovieCatalog'}
從結果看,外部組態檔中的屬性值成功注入,
案例2:無法決議屬性值
Spring 提供了一個默認的寬松嵌入式值決議器,它將嘗試決議屬性值,如果無法決議,屬性名稱(例如 ${catalog.name})將作為值注入,
將組態檔內容修改如下
xxx.catalog.name=MovieCatalog
運行同樣上一個案例的測驗,可以發現無法決議到屬性值則將屬性名稱注入了,
MovieRecommender{catalog='${catalog.name}'}
如果需要嚴格控制不存在的值,可以宣告一個 PropertySourcesPlaceholderConfigurer并注入到Spring中
@Configuration
@ComponentScan(basePackages = "com.crab.spring.ioc.demo10")
@PropertySource("classpath:demo10/application.properties")
public class AppConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
運行同樣的測驗程式,此時嚴格模式下會拋出例外
java.lang.IllegalArgumentException: Could not resolve placeholder 'catalog.name' in value "${catalog.name}"
擴展: Spring Boot 默認配置一個 PropertySourcesPlaceholderConfigurer bean,它將從 application.properties 和 application.yml 檔案中獲取屬性,
案例3: 提供默認值
可以提供默認值在無法決議屬性值作為屬性值注入,
@Component
public class MovieRecommender {
private final String catalog;
public MovieRecommender(@Value("${catalog.name:defaultCatalog}") String catalog) {
this.catalog = catalog;
}
}
此時組態檔如下
xxx.catalog.name=MovieCatalog
運行同樣的測驗程式,注入的是默認值
MovieRecommender{catalog='defaultCatalog'}
案例4:支持SpEL運算式
SpEL運算式后續專門講,此處不展開,
@PostConstruct @PreDestroy的使用
Spring支持生命周期回呼介面注解,@PostConstruct @PreDestroy是JSR 250提供的,
@PostConstruct 注解的方法在容器初始化化bean的階段回呼,
@PostConstruct 注解的方法在容器銷毀bean的階段回呼,
直接來看案例
@Component
public class FoodRecommender {
@PostConstruct
public void onInit() {
System.out.println("FoodRecommender onInit");
}
@PreDestroy
public void onDestroy() {
System.out.println("FoodRecommender onDestroy");
}
}
注解的配置相當于下面的xml組態檔
<bean id="foodRecommender"
init-method="onInit"
destroy-method="onInit"></bean>
運行下測驗程式并觀察結果
@org.junit.Test
public void test1() {
System.out.println("開始初始化容器");
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
FoodRecommender bean = context.getBean(FoodRecommender.class);
System.out.println("使用容器中");
System.out.println("銷毀容器");
context.close();
}
// 結果
開始初始化容器
FoodRecommender onInit
使用容器中
銷毀容器
FoodRecommender onDestroy
總結
本文介紹@Resource實作依賴注入,@Value詳細使用和@PostConstruct @PreDestroy的使用,
本篇原始碼地址: https://github.com/kongxubihai/pdf-spring-series/tree/main/spring-series-ioc/src/main/java/com/crab/spring/ioc/demo09
知識分享,轉載請注明出處,學無先后,達者為先!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/423925.html
標籤:其他
上一篇:Python實作多功能音樂播放器
下一篇:Keycloak 團隊宣布他們正在棄用大多數 Keycloak 配接器,包括Spring Security和Spring Boot
