色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

探討Spring框架中的屬性注入技術(shù)

OSC開(kāi)源社區(qū) ? 來(lái)源:OSCHINA 社區(qū) ? 2023-06-14 09:37 ? 次閱讀

在本文中,我們深入探討了 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)回顧一下:


 
 
1.2 使用 @Bean 注解進(jìn)行 setter 方法注入 我們?cè)谇懊娴奈恼轮幸矊W(xué)習(xí)過(guò)如何在 bean 創(chuàng)建時(shí)通過(guò)編程方式設(shè)置屬性:
@Bean
public User user() {
    User user = new User();
 user.setUsername("example-username-anno-setter");
 user.setAge(25);
 return user;
}
1.3 setter 方法注入完整代碼示例

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

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

public class User {
 private String username;
 private Integer age;
 public User() {
 }
 // 為了節(jié)省篇幅,getter和setter方法省略......
    @Override
 public String toString() {
 return "User{username='" + username + "', age=" + age + "}";
 }
}

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


  
 
 
 
 

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

import com.example.demo.bean.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DemoApplication {
 public static void main(String[] args) {
 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User userSetter = (User) context.getBean("userSetter");
 System.out.println(userSetter);
 }
}
運(yùn)行結(jié)果如下:

1541745e-09dd-11ee-962d-dac502259ad0.png

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

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

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
    @Bean
 public User userSetter() {
        User user = new User();
 user.setUsername("example-username-anno-setter");
 user.setAge(25);
 return user;
 }
}
使用 @Bean 注解來(lái)定義 Bean。每個(gè) @Bean 方法對(duì)應(yīng)于 XML 配置中的一個(gè) 元素。這個(gè)方法的名稱就是 Bean 的 id,方法的返回值就是 Bean 的類型 然后修改主程序,這里使用 AnnotationConfigApplicationContext 來(lái)創(chuàng)建 Spring 的應(yīng)用上下文,并加載配置類。Spring 會(huì)自動(dòng)從配置類中獲取所有的 Bean 定義,并創(chuàng)建相應(yīng)的 Bean 實(shí)例。
package com.example.demo;
import com.example.demo.bean.User;
import com.example.demo.configuration.AppConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class DemoApplication {
 public static void main(String[] args) {
 ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        User userSetter = (User) context.getBean("userSetter");
 System.out.println(userSetter);
 }
}
運(yùn)行結(jié)果如下

154f01dc-09dd-11ee-962d-dac502259ad0.png

注意: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)造器:

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

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

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


 
 
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ù)的名稱,如:

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

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

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

@Bean
public User user() {
 return new User("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)造器。

public class User {
 private String username;
 private Integer age;
 public User() {
 }
 public User(String username, Integer age) {
 this.username = username;
 this.age = age;
 }
 // 為了節(jié)省篇幅,getter和setter方法省略......
    @Override
 public String toString() {
 return "User{username='" + username + "', age=" + age + "}";
 }
}

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


  
  
 
 
 
 
  
 
 
 
 

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

package com.example.demo;
import com.example.demo.bean.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DemoApplication {
 public static void main(String[] args) {
 ApplicationContext context = new ClassPathXmlApplicationContext("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é)果如下:

15621bdc-09dd-11ee-962d-dac502259ad0.png

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

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

import com.example.demo.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
//    @Bean
//    public User userSetter() {
//        User user = new User();
//        user.setUsername("example-username-anno-setter");
//        user.setAge(25);
//        return user;
//    }
    @Bean
 public User userConstructor() {
 return new User("example-username-anno-constructor", 25);
 }
}

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

import com.example.demo.bean.User;
import com.example.demo.configuration.AppConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class DemoApplication {
 public static void main(String[] args) {
 ApplicationContext context = new AnnotationConfigApplicationContext(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é)果:

156b97b6-09dd-11ee-962d-dac502259ad0.png

注意:如果在類中同時(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
public class White {
    @Value("white-value-annotation")
 private String title;
    @Value("1")
 private Integer rank;
    @Override
 public String 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 容器中,并將其取出并打印:

public class DemoApplication {
 public static void main(String[] args) throws Exception {
 ApplicationContext ctx = new AnnotationConfigApplicationContext(White.class);
        White white = ctx.getBean(White.class);
 System.out.println("Injected value : " + white);
 }
}

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

Injected value : 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
public class BlueConfig {
    @Value("${blue.title}")
 private String title;
    @Value("${blue.rank}")
 private int 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
public class SomeComponent {
    @Autowired
 private Environment env;
 public void someMethod() {
        String title = env.getProperty("blue.title");
        int rank = Integer.parseInt(env.getProperty("blue.rank"));
 // ...
 }
}
在上述代碼中,Environment 類的 getProperty 方法用于獲取屬性值。注意,getProperty 方法返回的是 String,所以如果屬性是非字符串類型(如 int),則需要將獲取的屬性值轉(zhuǎn)換為適當(dāng)?shù)念愋汀?注意:@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 {
 private String name;
 private String version;
 // 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
public class AppConfig {
    @Value("${appTest.name}")
 private String name;
    @Value("${appTest.version}")
 private String version;
 // getters and setters...
}

Blue 類的屬性注入

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

@Value("${blue.title}")
private String title;
@Value("${blue.rank}")
private Integer rank;
如果你熟悉 jsp 的 el 表達(dá)式,會(huì)發(fā)現(xiàn)這和它非常相似!

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

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

public static void main(String[] args) throws Exception {
 ApplicationContext ctx = new AnnotationConfigApplicationContext(InjectValueConfiguration.class);
    Blue blue = ctx.getBean(Blue.class);
 System.out.println("Properties value : " + blue);
}

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

Properties value : Blue{
   title='blue-value-properties', rank=2}
3.3 在 XML 中引入外部配置文件 在 xml 中,我們可以和 @Value 相同的方式使用占位符:


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

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

創(chuàng)建 White 類:

package com.example.demo.bean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class White {
    @Value("white-value-annotation")
 private String title;
    @Value("1")
 private Integer rank;
    @Override
 public String toString() {
 return "White{" + "title='" + title + ''' + ", rank=" + rank + '}';
 }
}

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

package com.example.demo;
import com.example.demo.bean.White;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class DemoApplication {
 public static void main(String[] args) throws Exception {
 ApplicationContext ctx = new AnnotationConfigApplicationContext(White.class);
        White white = ctx.getBean(White.class);
 System.out.println("Injected value : " + white);
 }
}
運(yùn)行結(jié)果如下:

1576c848-09dd-11ee-962d-dac502259ad0.png

引入外部配置文件 @PropertySource

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

package com.example.demo.bean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Blue {
    @Value("${blue.title}")
 private String title;
    @Value("${blue.rank}")
 private Integer rank;
    @Override
 public String toString() {
 return "Blue{" + "title='" + title + ''' + ", rank=" + rank + '}';
 }
}

resources 目錄下的 blue.properties 文件:

blue.title=blue-value-properties
blue.rank=2

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

package com.example.demo.configuration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@ComponentScan("com.example")
@PropertySource("classpath:blue.properties")
public class InjectValueConfiguration {
}

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

package com.example.demo;
import com.example.demo.bean.Blue;
import com.example.demo.configuration.InjectValueConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class DemoApplication {
 public static void main(String[] args) throws Exception {
 ApplicationContext ctx = new AnnotationConfigApplicationContext(InjectValueConfiguration.class);
        Blue blue = ctx.getBean(Blue.class);
 System.out.println("Properties value : " + blue);
 }
}
運(yùn)行結(jié)果如下:

158ce966-09dd-11ee-962d-dac502259ad0.png

在 xml 中引入外部配置文件

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



  
 
 
 
 
 
在這里我們使用了 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 類如下:
package com.example.demo.bean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Blue {
    @Value("${blue.title}")
 private String title;
    @Value("${blue.rank}")
 private Integer rank;
 public String getTitle() {
 return title;
 }
 public void setTitle(String title) {
 this.title = title;
 }
 public Integer getRank() {
 return rank;
 }
 public void setRank(Integer rank) {
 this.rank = rank;
 }
    @Override
 public String toString() {
 return "Blue{" + "title='" + title + ''' + ", rank=" + rank + '}';
 }
}

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

package com.example.demo;
import com.example.demo.bean.Blue;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@ComponentScan("com.example")
public class DemoApplication {
 public static void main(String[] args) throws Exception {
 ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:injectValueContext.xml");
        Blue blue = ctx.getBean(Blue.class);
 System.out.println("Properties value : " + blue);
 }
}
運(yùn)行結(jié)果如下:

1596286e-09dd-11ee-962d-dac502259ad0.png

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
public class Azure {
    @Value("#{'spel-for-azure'}")
 private String name;
    @Value("#{10}")
 private Integer 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
public class Emerald {
    @Value("#{'copy of ' + azure.name}")
 private String name;
    @Value("#{azure.priority + 1}")
 private Integer 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ù)制:
use spel 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
public class Ivory {
    @Value("#{azure.name.substring(0, 3)}")
 private String name;
    @Value("#{T(java.lang.Integer).MAX_VALUE}")
 private Integer priority;
}

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

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

use spel methods : Ivory{
   name='spe', priority=2147483647}
4.2 在 XML 中使用 SpEL 表達(dá)式實(shí)現(xiàn)屬性注入:

 
 
學(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:

package com.example.demo.bean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Azure {
    @Value("#{'spel-for-azure'}")
 private String name;
    @Value("#{10}")
 private Integer priority;
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
 public Integer getPriority() {
 return priority;
 }
 public void setPriority(Integer priority) {
 this.priority = priority;
 }
    @Override
 public String toString() {
 return "Azure{" +
 "name='" + name + ''' +
 ", priority=" + priority +
 '}';
 }
}
Emerald.java:
package com.example.demo.bean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Emerald {
    @Value("#{'copy of ' + azure.name}")
 private String name;
    @Value("#{azure.priority + 1}")
 private Integer priority;
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
 public Integer getPriority() {
 return priority;
 }
 public void setPriority(Integer priority) {
 this.priority = priority;
 }
    @Override
 public String toString() {
 return "Emerald{" +
 "name='" + name + ''' +
 ", priority=" + priority +
 '}';
 }
}

Ivory.java:

package com.example.demo.bean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Ivory {
    @Value("#{azure.name.substring(0, 3)}")
 private String name;
    @Value("#{T(java.lang.Integer).MAX_VALUE}")
 private Integer priority;
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
 public Integer getPriority() {
 return priority;
 }
 public void setPriority(Integer priority) {
 this.priority = priority;
 }
    @Override
 public String toString() {
 return "Ivory{" +
 "name='" + name + ''' +
 ", priority=" + priority +
 '}';
 }
}

MyBean.java

@Component
public class MyBean {
    @Autowired
 private Azure azure;
    @Autowired
 private Emerald emerald;
    @Autowired
 private Ivory ivory;
 public void 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
public class DemoApplication {
 public static void main(String[] args) {
 ApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);
 MyBean myBean = applicationContext.getBean(MyBean.class);
 myBean.init();
 }
}
運(yùn)行結(jié)果:

15a2419e-09dd-11ee-962d-dac502259ad0.png

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

對(duì)于 XML 配置,Spring 還支持在 bean 定義中使用 SpEL。 首先,需要?jiǎng)?chuàng)建一個(gè) Spring XML 配置文件,我們將其命名為 app-config.xml:



 
 
 
 
 
 
 
 
 
 
 
 
 
注意:在 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
package com.example.demo.bean;
public class Azure {
 private String name;
 private Integer priority;
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
 public Integer getPriority() {
 return priority;
 }
 public void setPriority(Integer priority) {
 this.priority = priority;
 }
    @Override
 public String toString() {
 return "Azure{" +
 "name='" + name + ''' +
 ", priority=" + priority +
 '}';
 }
}
Emerald.java
package com.example.demo.bean;
public class Emerald {
 private String name;
 private Integer priority;
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
 public Integer getPriority() {
 return priority;
 }
 public void setPriority(Integer priority) {
 this.priority = priority;
 }
    @Override
 public String toString() {
 return "Emerald{" +
 "name='" + name + ''' +
 ", priority=" + priority +
 '}';
 }
}

Ivory.java

package com.example.demo.bean;
public class Ivory {
 private String name;
 private Integer priority;
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
 public Integer getPriority() {
 return priority;
 }
 public void setPriority(Integer priority) {
 this.priority = priority;
 }
    @Override
 public String toString() {
 return "Ivory{" +
 "name='" + name + ''' +
 ", priority=" + priority +
 '}';
 }
}
然后需要在主程序中導(dǎo)入這個(gè) XML 配置文件,這可以通過(guò)在主程序中添加 @ImportResource 注解實(shí)現(xiàn):
package com.example.demo;
import com.example.demo.bean.MyBean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource("classpath:app-config.xml")
public class DemoApplication {
 public static 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é)果如下:

15b9389a-09dd-11ee-962d-dac502259ad0.png






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 存儲(chǔ)器
    +關(guān)注

    關(guān)注

    38

    文章

    7484

    瀏覽量

    163763
  • JAVA語(yǔ)言
    +關(guān)注

    關(guān)注

    0

    文章

    138

    瀏覽量

    20090
  • XML技術(shù)
    +關(guān)注

    關(guān)注

    0

    文章

    15

    瀏覽量

    6011
  • YAML
    +關(guān)注

    關(guān)注

    0

    文章

    21

    瀏覽量

    2322

原文標(biāo)題:揭秘Spring依賴注入和SpEL表達(dá)式

文章出處:【微信號(hào):OSC開(kāi)源社區(qū),微信公眾號(hào):OSC開(kāi)源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    java spring教程

    Spring核心概念介紹控制反轉(zhuǎn)(IOC)依賴注入(DI)集合對(duì)象注入等Bean的管理BeanFactoryApplicationContextSpring 在web的使用
    發(fā)表于 09-11 11:09

    什么是java spring

    。在SSH項(xiàng)目中管理事務(wù)以及對(duì)象的注入Spring是非侵入式的:基于Spring開(kāi)發(fā)的系統(tǒng)的對(duì)象一般不依賴于Spring的類。組成
    發(fā)表于 09-11 11:16

    怎么閱讀Spring源碼

    封裝,很有可能在讀源碼的過(guò)程掉到各種細(xì)節(jié)里出不來(lái),所以讀這種源碼要事無(wú)巨細(xì),理解原理即可。基本原理其實(shí)就是通過(guò)反射解析類及其類的各種信息,包括構(gòu)造器、方法及其參數(shù),屬性。然后將其封裝成bean定義
    發(fā)表于 05-04 15:21

    三大框架Spring

    ;出現(xiàn)了Spring,可以自動(dòng)創(chuàng)建需要被調(diào)用的對(duì)象以及進(jìn)行屬性注入,也可以維護(hù)這些bean(具體的java類)之間的關(guān)系;
    發(fā)表于 05-27 07:21

    Spring框架的設(shè)計(jì)理念

    Spring作為現(xiàn)在最優(yōu)秀的框架之一,已被廣泛的使用,51CTO也曾經(jīng)針對(duì)Spring框架的hqC應(yīng)用做過(guò)報(bào)道。本文將從另外一個(gè)視角試圖剖
    發(fā)表于 07-15 08:17

    一文解析Spring框架

    Spring框架詳解 - 03
    發(fā)表于 06-17 17:15

    Spring筆記分享

    ; 可以管理所有的組件(類)Spring的優(yōu)良特性1) 非侵入式:基于Spring開(kāi)發(fā)的應(yīng)用的對(duì)象可以不依賴于Spring的API2) 依賴注入
    發(fā)表于 11-04 07:51

    MVC框架實(shí)例—Spring MVC配置

    本文旨在讓您在使用Spring MVC框架配置完成日常工作的時(shí)候更加輕松。根據(jù)Spring MVC框架配置,為基于本技術(shù)開(kāi)發(fā)的項(xiàng)目提供一系列
    發(fā)表于 12-14 17:37 ?3173次閱讀

    Spring集成Acegi安全框架在J2EE的應(yīng)用

    Acegi是一個(gè)基于Spring的安全框架探討Spring框架集成Acegi的方法,即在Spring
    發(fā)表于 05-07 14:11 ?19次下載

    spring mvc框架介紹

    。使用 Spring 可插入的 MVC 架構(gòu),可以選擇是使用內(nèi)置的 Spring Web 框架還是 Struts 這樣的 Web 框架。通過(guò)策略接口,
    發(fā)表于 11-17 16:28 ?2343次閱讀
    <b class='flag-5'>spring</b> mvc<b class='flag-5'>框架</b>介紹

    spring框架定時(shí)器使用與配置

    Spring是于2003 年興起的一個(gè)輕量級(jí)的Java 開(kāi)發(fā)框架,由Rod Johnson創(chuàng)建。簡(jiǎn)單來(lái)說(shuō),Spring是一個(gè)分層的JavaSE/EEfull-stack(一站式)輕量級(jí)開(kāi)源框架
    發(fā)表于 01-26 17:11 ?1766次閱讀

    Spring認(rèn)證」Spring 框架概述

    Spring 框架是一個(gè)開(kāi)源的 Java 平臺(tái)。它最初由 Rod Johnson 編寫(xiě),并于 2003 年 6 月在 Apache 2.0 許可下首次發(fā)布。 Spring Framework 的核心
    的頭像 發(fā)表于 08-12 15:07 ?669次閱讀
    「<b class='flag-5'>Spring</b>認(rèn)證」<b class='flag-5'>Spring</b> <b class='flag-5'>框架</b>概述

    Spring依賴注入的方式

    Spring 是一個(gè)開(kāi)源的輕量級(jí)框架,可以用于構(gòu)建企業(yè)級(jí)應(yīng)用程序。其最重要的特性之一是依賴注入(Dependency Injection,DI),這是一種設(shè)計(jì)模式,它可以幫助我們解耦代碼、提高
    的頭像 發(fā)表于 11-22 15:12 ?487次閱讀

    Spring依賴注入的四種方式

    Spring框架,依賴注入是一種核心的概念和機(jī)制。通過(guò)依賴注入,我們可以讓對(duì)象之間的依賴關(guān)系更加松散,并且能夠方便地進(jìn)行單元測(cè)試和模塊化
    的頭像 發(fā)表于 12-03 15:11 ?1964次閱讀

    Spring Cloud Gateway網(wǎng)關(guān)框架

    Spring Cloud Gateway網(wǎng)關(guān)框架 本軟件微服務(wù)架構(gòu)采用Spring Cloud Gateway網(wǎng)關(guān)控制框架
    的頭像 發(fā)表于 08-22 09:58 ?483次閱讀
    <b class='flag-5'>Spring</b> Cloud Gateway網(wǎng)關(guān)<b class='flag-5'>框架</b>
    主站蜘蛛池模板: 2021全国精品卡一卡二| 国产精品久久久久久久久免费下载 | 伊人久久综合热青草| 成人麻豆日韩在无码视频| 久久操韩国自偷拍| 天堂网久久| xxx免费观看| 看全色黄大色大片免费久黄久| 无人区乱码1区2区3区网站| 99热久久视频只有精品6国产| 黄色片网站下载| 十九岁韩国电影在线观看| 8X拨牐拨牐X8免费视频8| 精品国产精品人妻久久无码五月天 | 国产亚洲精品久久久久久久软件 | 午夜理论片日本中文在线| jijzzizz中国版| 麻豆AV久久AV盛宴AV| 亚洲欧美自拍明星换脸| 国产成人精品久久久久婷婷| 嫩草AV久久伊人妇女| 在线播放毛片| 精品无人区麻豆乱码1区2| 性一交一无一伦一精一品| 国产不卡视频在线| 女的把腿张开男的往里面插| 中文字幕日本在线mv视频精品| 国产真实女人一级毛片| 无遮18禁在线永久免费观看挡| 成年人视频免费在线观看| 女警被黑人20厘米强交| 2021国产在线视频| 久久受www免费人成_看片中文| 亚洲精品免费在线视频| 国产亚洲精品久久久久久一区二区 | 国产传媒在线播放| 日本最新在线不卡免费视频| chinese国语露脸videos| 女仆乖H调教跪趴| 9位美女厕所撒尿11分| 男人插女人动态图|