日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

來(lái)源 | OSCHINA 社區(qū)

作者 | 華為云開(kāi)發(fā)者聯(lián)盟-磚業(yè)洋_

在本文中,我們深入探討了 Spring 框架中的屬性注入技術(shù),包括 setter 注入、構(gòu)造器注入、注解式屬性注入,以及使用 SpEL 表達(dá)式進(jìn)行屬性注入。我們通過(guò) XML 和注解兩種方式,詳細(xì)講解了如何進(jìn)行屬性注入,并給出了完整的代碼示例。無(wú)論你是 Spring 新手,還是有一定經(jīng)驗(yàn)的開(kāi)發(fā)者,本文都將幫助你理解并掌握 Spring 中的屬性注入技術(shù)。

1. setter 屬性注入1.1 使用 XML 進(jìn)行 setter 方法注入

我們?cè)谇懊娴奈恼轮幸呀?jīng)使用過(guò) XML 進(jìn)行 setter 方法的屬性注入了,下面讓我們?cè)賮?lái)回顧一下:

<bean id= "userSetter"class= "com.example.demo.bean.User">

< propertyname= "username"value= "example-username-setter"/>

< propertyname= "age"value= "25"/>

</ bean>

1.2 使用 @Bean 注解進(jìn)行 setter 方法注入

我們?cè)谇懊娴奈恼轮幸矊W(xué)習(xí)過(guò)如何在 bean 創(chuàng)建時(shí)通過(guò)編程方式設(shè)置屬性:

@Bean

publicUser user{

User user = newUser;

user.setUsername( "example-username-anno-setter");

user.setAge( 25);

returnuser;

}

1.3 setter 方法注入完整代碼示例

  • 使用 XML 進(jìn)行 setter 方法注入

首先,我們需要?jiǎng)?chuàng)建一個(gè) User 類,并在其中包含 username 和 age 兩個(gè)屬性,以及相應(yīng)的 getter、setter 方法和構(gòu)造器。

publicclassUser{

privateString username;

privateInteger age;

publicUser{

}

// 為了節(jié)省篇幅,getter和setter方法省略......

@Override

publicString toString{

return"User{username='"+ username + "', age="+ age + "}";

}

}

對(duì)于 XML 方式的 setter 注入和構(gòu)造器注入,我們需要?jiǎng)?chuàng)建一個(gè)配置文件,比如叫 ApplicationContext.xml。

< beansxmlns= "http://www.springframework.org/schema/beans"

xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation= "http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd" >

<!-- setter方法注入 -->

< beanid= "userSetter"class= "com.example.demo.bean.User">

< propertyname= "username"value= "example-username-setter"/>

< propertyname= "age"value= "25"/>

</ bean>

</ beans>

然后,我們需要?jiǎng)?chuàng)建一個(gè) DemoApplication 類,使用 ApplicationContext 來(lái)加載配置文件并獲取 Bean:

importcom.example.demo.bean.User;

importorg.springframework.context.ApplicationContext;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

publicclassDemoApplication{

publicstaticvoid mAIn( String[] args) {

ApplicationContextcontext = new ClassPathXmlApplicationContext( "applicationContext.xml");

UseruserSetter = ( User) context.getBean( "userSetter");

System.out. println(userSetter);

}

}

運(yùn)行結(jié)果如下:

  • 使用 @Bean 注解進(jìn)行 setter 方法注入

我們需要?jiǎng)?chuàng)建一個(gè)配置類,例如叫 AppConfig.JAVA:

importorg.springframework.context. annotation.Bean;

importorg.springframework.context. annotation.Configuration;

@Configuration

publicclassAppConfig{

@Bean

publicUser userSetter {

User user = new User;

user.setUsername( "example-username-anno-setter");

user.setAge( 25);

returnuser;

}

}

使用 @Bean 注解來(lái)定義 Bean。每個(gè) @Bean 方法對(duì)應(yīng)于 XML 配置中的一個(gè) <bean> 元素。這個(gè)方法的名稱就是 Bean 的 id,方法的返回值就是 Bean 的類型

然后修改主程序,這里使用 AnnotationConfigApplicationContext 來(lái)創(chuàng)建 Spring 的應(yīng)用上下文,并加載配置類。Spring 會(huì)自動(dòng)從配置類中獲取所有的 Bean 定義,并創(chuàng)建相應(yīng)的 Bean 實(shí)例。

packagecom.example.demo;

importcom.example.demo.bean.User;

importcom.example.demo.configuration.AppConfig;

importorg.springframework.context.ApplicationContext;

importorg.springframework.context.annotation.AnnotationConfigApplicationContext;

publicclassDemoApplication{

publicstaticvoidmain(String[] args){

ApplicationContext context = newAnnotationConfigApplicationContext(AppConfig . class) ;

User userSetter = (User) context.getBean( "userSetter");

System.out.println(userSetter);

}

}

運(yùn)行結(jié)果如下

注意:XML 配置方式已經(jīng)相對(duì)陳舊,而且在 Spring Boot 項(xiàng)目中,主流的做法是使用注解和 Java 配置方式。對(duì)于 setter 注入,有時(shí)會(huì)引發(fā)循環(huán)依賴的問(wèn)題。在 Spring 中,可以使用構(gòu)造器注入來(lái)避免這種情況,這里了解即可。

2. 構(gòu)造器注入

setter 注入是一種在對(duì)象被實(shí)例化之后(通過(guò)調(diào)用無(wú)參構(gòu)造器創(chuàng)建實(shí)例)再通過(guò) setter 方法注入依賴的方式。構(gòu)造器注入則是在創(chuàng)建對(duì)象實(shí)例的時(shí)候就通過(guò)構(gòu)造器參數(shù)來(lái)注入依賴。

為了演示構(gòu)造器注入,我們需要給 User 添加一個(gè)全參數(shù)構(gòu)造器:

publicUser(String username, Integer age) {

this.username = username;

this.age = age;

}

添加這個(gè)構(gòu)造器后,Java 不再提供默認(rèn)的無(wú)參構(gòu)造器,這會(huì)導(dǎo)致我們之前的 <bean> 標(biāo)簽創(chuàng)建時(shí)失敗,因?yàn)樗也坏侥J(rèn)的構(gòu)造器。

2.1 使用 XML 進(jìn)行構(gòu)造器注入

我們可以在 <bean> 標(biāo)簽內(nèi)部聲明一個(gè)子標(biāo)簽:constructor-arg。它用于指定構(gòu)造器的參數(shù),來(lái)進(jìn)行屬性注入。constructor-arg 標(biāo)簽的編寫(xiě)規(guī)則如下:

<bean id= "userConstructor"class= "com.example.demo.bean.User">

< constructor-argindex= "0"value= "example-username-constructor"/>

< constructor-argindex= "1"value= "25"/>

</ bean>

index 屬性表示構(gòu)造函數(shù)參數(shù)的位置,它的值是一個(gè)非負(fù)整數(shù),其中 0 表示第一個(gè)參數(shù),1 表示第二個(gè)參數(shù),以此類推。雖然 value 屬性的值總是一個(gè)字符串,但是 Spring 會(huì)嘗試將它轉(zhuǎn)換為構(gòu)造函數(shù)參數(shù)所需的類型。例如構(gòu)造函數(shù)的第二個(gè)參數(shù)是 int 類型,那么 Spring 會(huì)嘗試將字符串 "25" 轉(zhuǎn)換為整數(shù) 25。

使用 index 屬性來(lái)指定構(gòu)造函數(shù)參數(shù)的位置在大多數(shù)情況下是可以的,但是如果構(gòu)造函數(shù)的參數(shù)數(shù)量或者順序發(fā)生了改變,就可能會(huì)出錯(cuò)。另外一種更為可靠的方式是使用 name 屬性來(lái)指定參數(shù)的名稱,如:

<bean id= "userConstructor"class= "com.example.demo.bean.User">

< constructor-argname= "username"value= "example-username-constructor"/>

< constructor-argname= "age"value= "25"/>

</ bean>

這樣無(wú)論參數(shù)的順序如何,只要參數(shù)名稱不變,就不會(huì)出錯(cuò)。

2.2 使用 @Bean 注解進(jìn)行構(gòu)造器屬性注入

在注解驅(qū)動(dòng)的 bean 注冊(cè)中,我們也可以直接使用編程方式賦值:

@Bean

publicUser user{

returnnewUser( "example-username-anno-constructor", 25);

}

2.3 構(gòu)造器注入的完整代碼示例

  • 使用 XML 進(jìn)行構(gòu)造器注入

首先,我們需要?jiǎng)?chuàng)建一個(gè) User 類,并在其中包含 username 和 age 兩個(gè)屬性,以及相應(yīng)的 getter、setter 方法和構(gòu)造器。

publicclassUser{

privateString username;

privateInteger age;

publicUser{

}

publicUser(String username, Integer age){

this.username = username;

this.age = age;

}

// 為了節(jié)省篇幅,getter和setter方法省略......

@Override

publicString toString{

return"User{username='"+ username + "', age="+ age + "}";

}

}

對(duì)于 XML 方式的構(gòu)造器注入,我們需要?jiǎng)?chuàng)建一個(gè)配置文件,比如叫 applicationContext.xml,這里保留 setter 注入方便大家對(duì)比

< beansxmlns= "http://www.springframework.org/schema/beans"

xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation= "http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd" >

<!-- setter方法注入 -->

<!-- setter方法注入 -->

<!-- <bean id="userSetter" class="com.example.demo.bean.User">-->

<!-- <property name="username" value="example-username-setter"/>-->

<!-- <property name="age" value="25"/>-->

<!-- </bean>-->

<!-- 構(gòu)造器注入 -->

< beanid= "userConstructor"class= "com.example.demo.bean.User">

< constructor-argname= "username"value= "example-username-constructor"/>

< constructor-argname= "age"value= "25"/>

</ bean>

</ beans>

然后,我們需要?jiǎng)?chuàng)建一個(gè) DemoApplication 類,使用 ApplicationContext 來(lái)加載配置文件并獲取 Bean:

packagecom.example.demo;

importcom.example.demo.bean.User;

importorg.springframework.context.ApplicationContext;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

publicclassDemoApplication{

publicstaticvoidmain(String[] args){

ApplicationContext context = newClassPathXmlApplicationContext( "applicationContext.xml");

// User userSetter = (User) context.getBean("userSetter");

// System.out.println(userSetter);

User userConstructor = (User) context.getBean( "userConstructor");

System.out.println(userConstructor);

}

}

運(yùn)行結(jié)果如下:

  • 使用 @Bean 注解進(jìn)行構(gòu)造器屬性注入

我們需要?jiǎng)?chuàng)建一個(gè)配置類,例如叫 AppConfig.java:

importcom.example.demo.bean.User;

importorg.springframework.context. annotation.Bean;

importorg.springframework.context. annotation.Configuration;

@Configuration

publicclassAppConfig{

// @Bean

// public User userSetter {

// User user = new User;

// user.setUsername("example-username-anno-setter");

// user.setAge(25);

// return user;

// }

@Bean

publicUser userConstructor {

returnnew User( "example-username-anno-constructor", 25);

}

}

同樣,我們需要?jiǎng)?chuàng)建一個(gè) DemoApplication 類,使用 AnnotationConfigApplicationContext 來(lái)加載配置類并獲取 Bean:

importcom.example.demo.bean.User;

importcom.example.demo.configuration.AppConfig;

importorg.springframework.context.ApplicationContext;

importorg.springframework.context.annotation.AnnotationConfigApplicationContext;

publicclassDemoApplication{

publicstaticvoidmain(String[] args){

ApplicationContext context = newAnnotationConfigApplicationContext(AppConfig . class) ;

// User userSetter = (User) context.getBean("userSetter");

// System.out.println(userSetter);

User userConstructor = (User) context.getBean( "userConstructor");

System.out.println(userConstructor);

}

}

運(yùn)行結(jié)果:

注意:如果在類中同時(shí)使用構(gòu)造器注入和 setter 注入,需要注意它們注入的順序:先進(jìn)行構(gòu)造器注入,然后是 setter 注入。

3. 注解式屬性注入

上面我們已經(jīng)說(shuō)過(guò)注解式的 setter 和構(gòu)造器注入。我們又是如何處理那些通過(guò) @Component 掃描而注冊(cè)的 bean 的屬性的呢?我們來(lái)仔細(xì)說(shuō)說(shuō)這個(gè)問(wèn)題,同時(shí)展示如何在 xml 中進(jìn)行相同的操作。

3.1 @Value 注解式屬性注入的應(yīng)用

首先,讓我們從最簡(jiǎn)單的屬性注入方法:@Value 開(kāi)始。創(chuàng)建一個(gè)新的 White 類,并聲明一些字段,但是這次我們不會(huì)設(shè)置 setter 方法:

@Component

publicclassWhite{

@Value( "white-value-annotation")

privateString title;

@Value( "1")

privateInteger rank;

@Override

publicString toString {

return"White{"+ "title='"+ title + '''+ ", rank="+ rank + '}';

}

}

要實(shí)現(xiàn)注解式屬性注入,我們可以直接在需要注入的字段上添加 @Value 注解:

@ Value(" white- value- annotation")

private String title;

@ Value(" 1")

private Integer rank;

要注意的是,如果使用 @Value 注解來(lái)注入一個(gè)不存在的屬性,那么應(yīng)用程序會(huì)在啟動(dòng)時(shí)拋出異常。

然后,我們將通過(guò)組件掃描方式將這個(gè) White 類掃描到 IOC 容器中,并將其取出并打印:

publicclassDemoApplication{

publicstaticvoidmain(String[] args)throwsException {

ApplicationContext ctx = newAnnotationConfigApplicationContext(White . class) ;

White white = ctx.getBean(White . class) ;

System.out.println( "Injected value : "+ white);

}

}

運(yùn)行 main 方法會(huì)看到 White 的字段已經(jīng)成功注入:

Injectedvalue : White{

title= 'white-value-annotation', rank=1}

3.2 引入外部配置文件 @PropertySource

如果我們需要在 Spring 中使用 properties 文件,我們應(yīng)該怎么辦呢?Spring 考慮到了這一點(diǎn),并擴(kuò)展了一個(gè)用于導(dǎo)入外部配置文件的注解:@PropertySource。

  • 創(chuàng)建 Bean 和配置文件

創(chuàng)建一個(gè)新的 Blue 類,其結(jié)構(gòu)與 White 類完全相同。然后在項(xiàng)目的 resources 目錄下創(chuàng)建一個(gè)新的 blue.properties 文件,用于存儲(chǔ) Blue 類的屬性配置:

blue.title=blue-value-properties

blue.rank= 2

  • 引入配置文件

使用 @PropertySource 注解將 properties 文件導(dǎo)入到配置類:

@Configuration

@ComponentScan( "com.example")

@PropertySource( "classpath:blue.properties")

public class InjectValueConfiguration {

}

這個(gè) blue.properties 文件是一個(gè)鍵值對(duì)的列表,Spring 將這些鍵值對(duì)加載到 Environment 中,我們可以通過(guò) @Value 注解或者 Environment 類的方法來(lái)獲取這些屬性值。

@Value 注解和 Environment 類都可以用于讀取 Spring 上下文中的屬性值。這些屬性值可能來(lái)自于多個(gè)不同的源,包括但不限于:

  • Spring Boot 的默認(rèn)配置文件(application.properties 或 application.yml)。
  • 通過(guò) @PropertySource 注解加載的屬性文件。
  • 系統(tǒng)環(huán)境變量。
  • Java 系統(tǒng)屬性(可以通過(guò) -D 命令行參數(shù)設(shè)置)。

如果你想通過(guò) @Value 注解來(lái)獲取屬性值,如下:

@Component

publicclassBlueConfig{

@Value( " ${blue.title}" )

privateString title;

@Value( " ${blue.rank}" )

privateint rank;

// getters and setters...

}

在 Spring 應(yīng)用中使用 @PropertySource 注解來(lái)加載一個(gè) .properties 文件時(shí),這個(gè)文件中的所有配置項(xiàng)都會(huì)被讀取,并存儲(chǔ)在一個(gè)內(nèi)部的 Map 結(jié)構(gòu)中。這個(gè) Map 的鍵是配置項(xiàng)的名稱,值是配置項(xiàng)的值。Spring 中的一些內(nèi)置配置項(xiàng)也會(huì)被添加到這個(gè) Map 中。

當(dāng)我們使用 ${...}`占位符語(yǔ)法來(lái)引用一個(gè)配置項(xiàng)時(shí),`Spring`會(huì)查找這個(gè)`Map`,取出與占位符名稱相應(yīng)的配置項(xiàng)的值。例如有一個(gè)配置項(xiàng)`blue.title=blue-value-properties`,我們可以在代碼中使用`${blue.title} 占位符來(lái)引用這個(gè)配置項(xiàng)的值。

如果想通過(guò) Environment 類的方法來(lái)獲取屬性值,可以像下面這樣做:

@Component

publicclassSomeComponent{

@Autowired

privateEnvironment env;

publicvoidsomeMethod{

String title = env.getProperty( "blue.title");

intrank = Integer.parseInt(env.getProperty( "blue.rank"));

// ...

}

}

在上述代碼中,Environment 類的 getProperty 方法用于獲取屬性值。注意,getProperty 方法返回的是 String,所以如果屬性是非字符串類型(如 int),則需要將獲取的屬性值轉(zhuǎn)換為適當(dāng)?shù)念愋汀?/p>

注意: @PropertySource無(wú)法加載YAML格式的文件,只能加載 properties 格式的文件。如果需要加載 YAML 格式的文件,而且使用的是 Spring Boot 框架,那么可以使用 @ConfigurationProperties 或 @Value 注解。例如以下的 YAML 文件:

application.yml

appTest:

name:MyApp

version:1.0.0

可以使用 @ConfigurationProperties 來(lái)加載這些屬性:

@Configuration

@ConfigurationProperties(prefix = "appTest")

public class AppConfig {

privateStringname;

privateStringversion;

// getters and setters...

}

@ConfigurationProperties 注解主要用于指定配置屬性的前綴,@ConfigurationProperties 注解本身并不直接指定配置文件的位置, 而是由 Spring Boot 的自動(dòng)配置機(jī)制處理的。

這樣,name 字段就會(huì)被自動(dòng)綁定到 appTest.name 配置屬性,version 字段就會(huì)被自動(dòng)綁定到 appTest.version 配置屬性。

默認(rèn)情況下,Spring Boot 會(huì)在啟動(dòng)時(shí)自動(dòng)加載 src/main/resources 目錄下的 application.properties 或 application.yml 文件。我們可以通過(guò)設(shè)置 spring.config.name 和 spring.config.location 屬性來(lái)改變默認(rèn)的配置文件名或位置。

注意:@ConfigurationProperties 注解需要配合 @EnableConfigurationProperties 注解或 @Configuration 注解使用,以確保 Spring 能夠發(fā)現(xiàn)并處理這些注解。

或者,你也可以使用 @Value 注解來(lái)加載這些屬性:

@Component

publicclassAppConfig{

@Value( " ${appTest.name}" )

privateString name;

@Value( " ${appTest.version}" )

privateString version;

// getters and setters...

}

  • Blue 類的屬性注入

對(duì)于 properties 類型的屬性,我們這里選擇 @Value 注解和占位符來(lái)注入屬性:

@Value( " ${blue.title}" )

privateString title;

@Value( " ${blue.rank}" )

privateInteger rank;

如果你熟悉 jsp 的 el 表達(dá)式,會(huì)發(fā)現(xiàn)這和它非常相似!

  • 測(cè)試啟動(dòng)類

修改啟動(dòng)類,將配置類引入,然后取出并打印 Blue:

publicstaticvoidmain(String[] args)throwsException {

ApplicationContext ctx = newAnnotationConfigApplicationContext(InjectValueConfiguration . class) ;

Blue blue = ctx.getBean(Blue . class) ;

System.out.println( "Properties value : "+ blue);

}

運(yùn)行 main 方法會(huì)看到控制臺(tái)已經(jīng)成功打印出了配置文件的屬性:

Propertiesvalue : Blue{

title= 'blue-value-properties', rank=2}

3.3 在 XML 中引入外部配置文件

在 xml 中,我們可以和 @Value 相同的方式使用占位符:

<?xml version="1.0" encoding="UTF-8"?>

< beansxmlns= "http://www.springframework.org/schema/beans"

xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation= "http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd"

xmlns:context= "http://www.springframework.org/schema/context">

<!-- 相當(dāng)于注解中的 @PropertySource("classpath:blue.properties") -->

< context:property-placeholderlocation= "classpath:blue.properties"/>

< beanclass= "com.example.demo.bean.Blue">

< propertyname= "title"value= "${blue.title}"/>

< propertyname= "rank"value= "${blue.rank}"/>

</ bean>

</ beans>

3.4 注解式屬性注入完整代碼示例

  • @Value 注解式屬性注入的應(yīng)用

創(chuàng)建 White 類:

packagecom.example.demo.bean;

importorg.springframework.beans.factory. annotation.Value;

importorg.springframework.stereotype.Component;

@Component

publicclassWhite{

@Value( "white-value-annotation")

privateString title;

@Value( "1")

privateInteger rank;

@Override

publicString toString {

return"White{"+ "title='"+ title + '''+ ", rank="+ rank + '}';

}

}

創(chuàng)建啟動(dòng)類 InjectValueAnnotationApplication:

packagecom.example.demo;

importcom.example.demo.bean.White;

importorg.springframework.context.ApplicationContext;

importorg.springframework.context.annotation.AnnotationConfigApplicationContext;

publicclassDemoApplication{

publicstaticvoidmain(String[] args)throwsException {

ApplicationContext ctx = newAnnotationConfigApplicationContext(White . class) ;

White white = ctx.getBean(White . class) ;

System.out.println( "Injected value : "+ white);

}

}

運(yùn)行結(jié)果如下:

  • 引入外部配置文件 @PropertySource

創(chuàng)建 Blue 類和配置文件,沒(méi)有 setter 和 getter 方法:

packagecom.example.demo.bean;

importorg.springframework.beans.factory. annotation.Value;

importorg.springframework.stereotype.Component;

@Component

publicclassBlue{

@Value( " ${blue.title}" )

privateString title;

@Value( " ${blue.rank}" )

privateInteger rank;

@Override

publicString toString {

return"Blue{"+ "title='"+ title + '''+ ", rank="+ rank + '}';

}

}

resources 目錄下的 blue.properties 文件:

blue.title=blue-value-properties

blue.rank= 2

創(chuàng)建配置類 InjectValueConfiguration:

packagecom.example.demo.configuration;

importorg.springframework.context.annotation.ComponentScan;

importorg.springframework.context.annotation.Configuration;

importorg.springframework.context.annotation.PropertySource;

@ Configuration

@ComponentScan( "com.example")

@PropertySource( "classpath:blue.properties")

public class InjectValueConfiguration {

}

修改啟動(dòng)類,引入配置類:

packagecom.example.demo;

importcom.example.demo.bean.Blue;

importcom.example.demo.configuration.InjectValueConfiguration;

importorg.springframework.context.ApplicationContext;

importorg.springframework.context.annotation.AnnotationConfigApplicationContext;

publicclassDemoApplication{

publicstaticvoidmain(String[] args)throwsException {

ApplicationContext ctx = newAnnotationConfigApplicationContext(InjectValueConfiguration . class) ;

Blue blue = ctx.getBean(Blue . class) ;

System.out.println( "Properties value : "+ blue);

}

}

運(yùn)行結(jié)果如下:

  • 在 xml 中引入外部配置文件

在使用 XML 配置的情況下,我們需要?jiǎng)?chuàng)建一個(gè) XML 文件來(lái)替代 InjectValueConfiguration 類,我們可以先注釋掉 InjectValueConfiguration 類的所有內(nèi)容

下面是相應(yīng)的 XML 文件內(nèi)容:

<?xml version="1.0" encoding="UTF-8"?>

< beansxmlns= "http://www.springframework.org/schema/beans"

xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation= "http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd"

xmlns:context= "http://www.springframework.org/schema/context">

<!-- 相當(dāng)于注解中的 @PropertySource("classpath:blue.properties") -->

< context:property-placeholderlocation= "classpath:blue.properties"/>

< beanclass= "com.example.demo.bean.Blue">

< propertyname= "title"value= "${blue.title}"/>

< propertyname= "rank"value= "${blue.rank}"/>

</ bean>

</ beans>

在這里我們使用了 context:property-placeholder 標(biāo)簽來(lái)導(dǎo)入外部的 properties 文件,然后使用 ${...} 占位符語(yǔ)法來(lái)引用配置文件中的屬性值。這樣無(wú)論是選擇用注解方式還是 XML 方式,都可以方便地在 Spring 中使用外部配置文件。

這里還需要修改下 Blue 類,因?yàn)橥ㄟ^(guò) XML 方法注入屬性需要提供相應(yīng)的 setter 方法,修改后的 Blue 類如下:

packagecom.example.demo.bean;

importorg.springframework.beans.factory. annotation.Value;

importorg.springframework.stereotype.Component;

@Component

publicclassBlue{

@Value( " ${blue.title}" )

privateString title;

@Value( " ${blue.rank}" )

privateInteger rank;

publicString getTitle {

returntitle;

}

publicvoid setTitle(String title) {

this.title = title;

}

publicInteger getRank {

returnrank;

}

publicvoid setRank(Integer rank) {

this.rank = rank;

}

@Override

publicString toString {

return"Blue{"+ "title='"+ title + '''+ ", rank="+ rank + '}';

}

}

然后,我們需要修改啟動(dòng)類,使用 XmlApplicationContext 代替 AnnotationConfigApplicationContext:

packagecom.example.demo;

importcom.example.demo.bean.Blue;

importorg.springframework.context.ApplicationContext;

importorg.springframework.context.annotation.ComponentScan;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

@ComponentScan( "com.example")

publicclassDemoApplication{

publicstaticvoidmain(String[] args)throwsException {

ApplicationContext ctx = newClassPathXmlApplicationContext( "classpath:injectValueContext.xml");

Blue blue = ctx.getBean(Blue . class) ;

System.out.println( "Properties value : "+ blue);

}

}

運(yùn)行結(jié)果如下:

4. SpEL 表達(dá)式

當(dāng)我們談到屬性注入的時(shí)候,我們可能會(huì)遇到一些復(fù)雜的需求,例如我們需要引用另一個(gè) Bean 的屬性,或者我們需要?jiǎng)討B(tài)處理某個(gè)屬性值。這種需求無(wú)法通過(guò)使用 ${} 的占位符方式實(shí)現(xiàn),我們需要一個(gè)更強(qiáng)大的工具:SpEL 表達(dá)式。

Spring Expression Language(SpEL)是從 Spring 框架 3.0 開(kāi)始支持的強(qiáng)大工具。SpEL 不僅是 Spring 框架的重要組成部分,也可以獨(dú)立使用。它的功能豐富,包括調(diào)用屬性值、屬性參數(shù)、方法調(diào)用、數(shù)組存儲(chǔ)以及邏輯計(jì)算等。它與開(kāi)源項(xiàng)目 OGNL(Object-Graph Navigation Language)相似,但 SpEL 是 Spring 框架推出的,并默認(rèn)內(nèi)嵌在 Spring 框架中。

4.1 使用 @Value 注解和 SpEL 表達(dá)式實(shí)現(xiàn)屬性注入

SpEL 的表達(dá)式用 #{} 表示,花括號(hào)中就是我們要編寫(xiě)的表達(dá)式。

我們創(chuàng)建一個(gè) Bean,命名為 Azure,同樣地,我們聲明屬性 name 和 priority,并提供 getter 和 setter 方法以及 toString 方法。然后我們使用 @Component 注解標(biāo)注它。

使用 @Value 配合 SpEL 完成屬性注入,如下:

@Component

publicclassAzure{

@Value( "#{'spel-for-azure'}")

privateString name;

@Value( "#{10}")

privateInteger priority;

}

我們修改啟動(dòng)類,從 IOC 容器中獲取 Azure 并打印,可以看到屬性被成功注入:

Azure{

name= 'spel-for-azure', priority=10}

SpEL 的功能遠(yuǎn)不止這些,它還可以獲取 IOC 容器中其他 Bean 的屬性,讓我們來(lái)展示一下。

我們已經(jīng)注冊(cè)了 Azure Bean,現(xiàn)在我們?cè)賱?chuàng)建一個(gè) Bean,命名為 Emerald。我們按照上述方法對(duì)字段和方法進(jìn)行聲明,然后使用 @Component 注解標(biāo)注。

我們希望 name 屬性直接復(fù)制 Azure 的 name 屬性,而 priority 屬性則希望比 Azure 的 priority 屬性大 1,我們可以這樣編寫(xiě):

@Component

publicclassEmerald{

@Value( "#{'copy of ' + azure.name}")

privateString name;

@Value( "#{azure.priority + 1}")

privateInteger priority;

}

在 Spring 的 SpEL 中可以通過(guò) bean 的名稱訪問(wèn)到對(duì)應(yīng)的 bean,并通過(guò)。操作符訪問(wèn) bean 的屬性。在這個(gè)例子中,azure 就是一個(gè) bean 的名稱,它對(duì)應(yīng)的 bean 就是 Azure 類的實(shí)例。所以,azure.name 就是訪問(wèn) Azure 類實(shí)例的 name 屬性。

如果你在一個(gè)不涉及 Spring 的環(huán)境中使用 SpEL,這個(gè)特性是不會(huì)生效的。這是因?yàn)檫@個(gè)特性依賴于 Spring 的 IoC 容器。

我們修改啟動(dòng)類,測(cè)試運(yùn)行,可以看到 Azure 的屬性已經(jīng)成功被復(fù)制:

usespel bean property : Emerald{

name= 'copy of spel-for-azure', priority= 11}

SpEL 表達(dá)式不僅可以引用對(duì)象的屬性,還可以直接引用類的常量,以及調(diào)用對(duì)象的方法。下面我們通過(guò)示例進(jìn)行演示。

我們新建一個(gè) Bean,命名為 Ivory。我們按照上述方法初始化屬性、toString 方法、注解。

假設(shè)我們有一個(gè)需求,讓 name 取 azure 屬性的前 3 個(gè)字符,priority 取 Integer 的最大值。那么我們可以使用 SpEL 這樣寫(xiě):

@Component

publicclassIvory{

@Value( "#{azure.name.substring(0, 3)}")

privateString name;

@Value( "#{T(java.lang.Integer).MAX_VALUE}")

privateInteger priority;

}

注意,直接引用類的屬性,需要在類的全限定名外面使用 T 包圍。

我們修改啟動(dòng)類,測(cè)試運(yùn)行,可以看到 Ivory 的屬性已經(jīng)是處理之后的值:

usespel methods : Ivory{

name= 'spe', priority= 2147483647}

4.2 在 XML 中使用 SpEL 表達(dá)式實(shí)現(xiàn)屬性注入:

<bean id= "ivory"class= "com.example.demo.bean.Ivory">

< propertyname= "name"value= "#{azure.name.substring(0, 3)}"/>

< propertyname= "priority"value= "#{T(java.lang.Integer).MAX_VALUE}"/>

</ bean>

學(xué)習(xí) SpEL 表達(dá)式不需要花費(fèi)大量的精力,掌握基礎(chǔ)的使用方法即可。

4.3 SpEL 表達(dá)式屬性注入完整代碼示例

  • 使用 @Value 注解和 SpEL 表達(dá)式實(shí)現(xiàn)屬性注入

創(chuàng)建三個(gè) SpEL 表達(dá)式屬性注入的 Bean:Azure.java、Emerald.java 和 Ivory.java。

Azure.java:

packagecom.example.demo.bean;

importorg.springframework.beans.factory. annotation.Value;

importorg.springframework.stereotype.Component;

@Component

publicclassAzure{

@Value( "#{'spel-for-azure'}")

privateString name;

@Value( "#{10}")

privateInteger priority;

publicString getName {

returnname;

}

publicvoid setName(String name) {

this.name = name;

}

publicInteger getPriority {

returnpriority;

}

publicvoid setPriority(Integer priority) {

this.priority = priority;

}

@Override

publicString toString {

return"Azure{"+

"name='"+ name + '''+

", priority="+ priority +

'}';

}

}

Emerald.java:

packagecom.example.demo.bean;

importorg.springframework.beans.factory. annotation.Value;

importorg.springframework.stereotype.Component;

@Component

publicclassEmerald{

@Value( "#{'copy of ' + azure.name}")

privateString name;

@Value( "#{azure.priority + 1}")

privateInteger priority;

publicString getName {

returnname;

}

publicvoid setName(String name) {

this.name = name;

}

publicInteger getPriority {

returnpriority;

}

publicvoid setPriority(Integer priority) {

this.priority = priority;

}

@Override

publicString toString {

return"Emerald{"+

"name='"+ name + '''+

", priority="+ priority +

'}';

}

}

Ivory.java:

packagecom.example.demo.bean;

importorg.springframework.beans.factory. annotation.Value;

importorg.springframework.stereotype.Component;

@Component

publicclassIvory{

@Value( "#{azure.name.substring(0, 3)}")

privateString name;

@Value( "#{T(java.lang.Integer).MAX_VALUE}")

privateInteger priority;

publicString getName {

returnname;

}

publicvoid setName(String name) {

this.name = name;

}

publicInteger getPriority {

returnpriority;

}

publicvoid setPriority(Integer priority) {

this.priority = priority;

}

@Override

publicString toString {

return"Ivory{"+

"name='"+ name + '''+

", priority="+ priority +

'}';

}

}

MyBean.java

@Component

publicclassMyBean{

@Autowired

privateAzure azure;

@Autowired

privateEmerald emerald;

@Autowired

privateIvory ivory;

publicvoid init{

System. out.println(azure);

System. out.println(emerald);

System. out.println(ivory);

}

}

MyBean 是一個(gè)用于展示如何在 Spring 中通過(guò) SpEL 表達(dá)式來(lái)注入屬性的類,它聚合了三個(gè)對(duì)象 Azure, Emerald 和 Ivory,并通過(guò) Spring 的依賴注入機(jī)制將這三個(gè)對(duì)象注入到了 MyBean 類的實(shí)例中

主程序 DemoApplication

@SpringBootApplication

publicclassDemoApplication{

publicstaticvoidmain(String[] args){

ApplicationContext applicationContext = SpringApplication.run(DemoApplication . class, args) ;

MyBean myBean = applicationContext.getBean(MyBean . class) ;

myBean.init;

}

}

運(yùn)行結(jié)果:

  • 在 XML 中使用 SpEL 表達(dá)式實(shí)現(xiàn)屬性注入

對(duì)于 XML 配置,Spring 還支持在 bean 定義中使用 SpEL。

首先,需要?jiǎng)?chuàng)建一個(gè) Spring XML 配置文件,我們將其命名為 app-config.xml:

<?xml version="1.0" encoding="UTF-8"?>

< beansxmlns= "http://www.springframework.org/schema/beans"

xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"

xmlns:context= "http://www.springframework.org/schema/context"

xsi:schemaLocation= "http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd" >

< context:component-scanbase-package= "com.example"/>

< beanid= "azure"class= "com.example.demo.bean.Azure">

< propertyname= "name"value= "#{

'spel-for-azure'}" />

< propertyname= "priority"value= "#{10}"/>

</ bean>

< beanid= "emerald"class= "com.example.demo.bean.Emerald">

< propertyname= "name"value= "#{

'copy of ' + azure.name}" />

< propertyname= "priority"value= "#{azure.priority + 1}"/>

</ bean>

< beanid= "ivory"class= "com.example.demo.bean.Ivory">

< propertyname= "name"value= "#{azure.name.substring(0, 3)}"/>

< propertyname= "priority"value= "#{T(java.lang.Integer).MAX_VALUE}"/>

</ bean>

</ beans>

注意:在 XML 中使用 SpEL 需要使用 #{},而不是 ${}。

然后修改這 3 個(gè) Bean,如果是使用 XML 來(lái)配置 Spring 的 Bean 的話,那么在 Java 類中就不需要使用 @Component 注解了。因?yàn)?XML 配置文件已經(jīng)明確地告訴 Spring 這些類是 Spring Bean。

同樣的,如果在 XML 文件中定義了 Bean 的屬性值,那么在 Java 類中就不需要使用 @Value 注解來(lái)注入這些值了。因?yàn)?XML 配置文件已經(jīng)明確地為這些屬性賦了值。

Azure.java

packagecom.example.demo.bean;

publicclassAzure{

privateString name;

privateInteger priority;

publicString getName{

returnname;

}

publicvoidsetName(String name){

this.name = name;

}

publicInteger getPriority{

returnpriority;

}

publicvoidsetPriority(Integer priority){

this.priority = priority;

}

@Override

publicString toString{

return"Azure{"+

"name='"+ name + '''+

", priority="+ priority +

'}';

}

}

Emerald.java

packagecom.example.demo.bean;

publicclassEmerald{

privateString name;

privateInteger priority;

publicString getName{

returnname;

}

publicvoidsetName(String name){

this.name = name;

}

publicInteger getPriority{

returnpriority;

}

publicvoidsetPriority(Integer priority){

this.priority = priority;

}

@Override

publicString toString{

return"Emerald{"+

"name='"+ name + '''+

", priority="+ priority +

'}';

}

}

Ivory.java

packagecom.example.demo.bean;

publicclassIvory{

privateString name;

privateInteger priority;

publicString getName{

returnname;

}

publicvoidsetName(String name){

this.name = name;

}

publicInteger getPriority{

returnpriority;

}

publicvoidsetPriority(Integer priority){

this.priority = priority;

}

@Override

publicString toString{

return"Ivory{"+

"name='"+ name + '''+

", priority="+ priority +

'}';

}

}

然后需要在主程序中導(dǎo)入這個(gè) XML 配置文件,這可以通過(guò)在主程序中添加 @ImportResource 注解實(shí)現(xiàn):

packagecom.example.demo;

importcom.example.demo.bean.MyBean;

importorg.springframework.boot.SpringApplication;

importorg.springframework.boot.autoconfigure.SpringBootApplication;

importorg.springframework.context.ApplicationContext;

importorg.springframework.context. annotation.ImportResource;

@SpringBootApplication

@ImportResource( "classpath:app-config.xml")

publicclassDemoApplication{

publicstatic void main(String[] args) {

ApplicationContext applicationContext = SpringApplication.run(DemoApplication . class, args);

MyBean myBean = applicationContext.getBean(MyBean . class);

myBean. init;

}

}

這樣就可以在 Spring 的 XML 配置文件中使用 SpEL 了。

運(yùn)行結(jié)果如下:

END

分享到:
標(biāo)簽:Spring
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定