精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

兩萬字 + 十張圖剖析Spring依賴注入和SpEL表達式

開發(fā) 架構
你系統的學習過Spring嗎?還是只停留在會用的階段?下面,哪吒將和你一起開啟Spring的系統學習,開啟真正的寂寞高手之路。

一、setter屬性注入

1、使用XML進行setter方法注入

我們在前面的文章中已經使用過XML進行setter方法的屬性注入了,下面讓我們再來回顧一下:

<bean id="userSetter" class="com.example.demo.bean.User">
    <property name="username" value="example-username-setter"/>
    <property name="age" value="25"/>
</bean>

2、使用@Bean注解進行setter方法注入

我們在前面的文章中也學習過如何在bean創(chuàng)建時通過編程方式設置屬性:

@Bean
public User user() {
    User user = new User();
    user.setUsername("example-username-anno-setter");
    user.setAge(25);
    return user;
}

3、setter方法注入完整代碼示例

使用XML進行setter方法注入。

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

public class User {
    private String username;
    private Integer age;

    public User() {}

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

    @Override
    public String toString() {
        return "User{username='" + username + "', age=" + age + "}";
    }
}

對于XML方式的setter注入和構造器注入,我們需要創(chuàng)建一個配置文件,比如叫applicationContext.xml。

<beans xmlns="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方法注入 -->
    <bean id="userSetter" class="com.example.demo.bean.User">
        <property name="username" value="example-username-setter"/>
        <property name="age" value="25"/>
    </bean>

</beans>

然后,我們需要創(chuàng)建一個DemoApplication類,使用ApplicationContext來加載配置文件并獲取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);
    }
}

運行結果如下:

使用@Bean注解進行setter方法注入。

我們需要創(chuàng)建一個配置類,例如叫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注解來定義Bean。每個@Bean方法對應于XML配置中的一個元素。這個方法的名稱就是Bean的id,方法的返回值就是Bean的類型。

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

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);
    }
}

運行結果如下:

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

二、構造器注入

setter注入是一種在對象被實例化之后(通過調用無參構造器創(chuàng)建實例)再通過setter方法注入依賴的方式。構造器注入則是在創(chuàng)建對象實例的時候就通過構造器參數來注入依賴。

為了演示構造器注入,我們需要給User添加一個全參數構造器:

public User(String username, Integer age) {
    this.username = username;
    this.age = age;
}

添加這個構造器后,Java不再提供默認的無參構造器,這會導致我們之前的標簽創(chuàng)建時失敗,因為它找不到默認的構造器。

1、使用XML進行構造器注入

我們可以在標簽內部聲明一個子標簽:constructor-arg。它用于指定構造器的參數,來進行屬性注入。constructor-arg標簽的編寫規(guī)則如下:

<bean id="userConstructor" class="com.example.demo.bean.User">
    <constructor-arg index="0" value="example-username-constructor"/>
    <constructor-arg index="1" value="25"/>
</bean>

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

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

<bean id="userConstructor" class="com.example.demo.bean.User">
    <constructor-arg name="username" value="example-username-constructor"/>
    <constructor-arg name="age" value="25"/>
</bean>

這樣無論參數的順序如何,只要參數名稱不變,就不會出錯。

2、使用@Bean注解進行構造器屬性注入

在注解驅動的bean注冊中,我們也可以直接使用編程方式賦值:

@Bean
public User user() {
    return new User("example-username-anno-constructor", 25);
}

3、構造器注入的完整代碼示例

使用XML進行構造器注入。

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

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 + "}";
    }
}

對于XML方式的構造器注入,我們需要創(chuàng)建一個配置文件,比如叫applicationContext.xml,這里保留setter注入方便大家對比。

<beans xmlns="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>-->

    <!-- 構造器注入 -->
    <bean id="userConstructor" class="com.example.demo.bean.User">
     <constructor-arg name="username" value="example-username-constructor"/>
     <constructor-arg name="age" value="25"/>
 </bean>

</beans>

然后,我們需要創(chuàng)建一個DemoApplication類,使用ApplicationContext來加載配置文件并獲取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);
    }

}

然后,我們需要創(chuàng)建一個DemoApplication類,使用ApplicationContext來加載配置文件并獲取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);
    }
}

運行結果如下:

使用@Bean注解進行構造器屬性注入。

我們需要創(chuàng)建一個配置類,例如叫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);
    }
}

同樣,我們需要創(chuàng)建一個DemoApplication類,使用AnnotationConfigApplicationContext來加載配置類并獲取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);
    }
}

運行結果:

注意:如果在類中同時使用構造器注入和setter注入,需要注意它們注入的順序:先進行構造器注入,然后是setter注入。

三、注解式屬性注入

上面我們已經說過注解式的setter和構造器注入。我們又是如何處理那些通過@Component掃描而注冊的bean的屬性的呢?我們來仔細說說這個問題,同時展示如何在xml中進行相同的操作。

1、@Value注解式屬性注入的應用

首先,讓我們從最簡單的屬性注入方法:@Value開始。創(chuàng)建一個新的White類,并聲明一些字段,但是這次我們不會設置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 + '}';
    }
}

要實現注解式屬性注入,我們可以直接在需要注入的字段上添加@Value注解:

@Value("white-value-annotation")
private String title;

@Value("1")
private Integer rank;

要注意的是,如果使用 @Value 注解來注入一個不存在的屬性,那么應用程序會在啟動時拋出異常。

然后,我們將通過組件掃描方式將這個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);
    }
}

運行main方法會看到White的字段已經成功注入:

Injected value : White{title='white-value-annotation', rank=1}

2、引入外部配置文件@PropertySource

如果我們需要在Spring中使用properties文件,我們應該怎么辦呢?Spring考慮到了這一點,并擴展了一個用于導入外部配置文件的注解:@PropertySource。

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

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

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

引入配置文件

使用@PropertySource注解將properties文件導入到配置類:

@Configuration
@ComponentScan("com.example")
@PropertySource("classpath:blue.properties")
public class InjectValueConfiguration {

}

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

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

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

如果你想通過 @Value 注解來獲取屬性值,如下:

@Component
public class BlueConfig {
    @Value("${blue.title}")
    private String title;

    @Value("${blue.rank}")
    private int rank;

    // getters and setters...
}

在 Spring 應用中使用 @PropertySource 注解來加載一個 .properties 文件時,這個文件中的所有配置項都會被讀取,并存儲在一個內部的 Map 結構中。這個 Map 的鍵是配置項的名稱,值是配置項的值。Spring 中的一些內置配置項也會被添加到這個 Map 中。

當我們使用 {blue.title} 占位符來引用這個配置項的值。

如果想通過 Environment 類的方法來獲取屬性值,可以像下面這樣做:

@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),則需要將獲取的屬性值轉換為適當的類型。

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

application.yml:

appTest:
  name: MyApp
  version: 1.0.0

可以使用@ConfigurationProperties來加載這些屬性:

@Configuration
@ConfigurationProperties(prefix = "appTest")
public class AppConfig {
    private String name;
    private String version;
    // getters and setters...
}

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

這樣,name字段就會被自動綁定到appTest.name配置屬性,version字段就會被自動綁定到appTest.version配置屬性。

默認情況下,Spring Boot會在啟動時自動加載src/main/resources目錄下的application.properties或application.yml文件。我們可以通過設置spring.config.name和spring.config.location屬性來改變默認的配置文件名或位置。

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

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

@Component
public class AppConfig {
    @Value("${appTest.name}")
    private String name;

    @Value("${appTest.version}")
    private String version;
    // getters and setters...
}

Blue類的屬性注入

對于properties類型的屬性,我們這里選擇@Value注解和占位符來注入屬性:

@Value("${blue.title}")
private String title;

@Value("${blue.rank}")
private Integer rank;

如果你熟悉jsp的el表達式,會發(fā)現這和它非常相似!

測試啟動類

修改啟動類,將配置類引入,然后取出并打印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);
}

運行main方法會看到控制臺已經成功打印出了配置文件的屬性:

Properties value : Blue{title='blue-value-properties', rank=2}

3、在XML中引入外部配置文件

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

<?xml versinotallow="1.0" encoding="UTF-8"?>
<beans xmlns="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">
    <!-- 相當于注解中的 @PropertySource("classpath:blue.properties") -->
    <context:property-placeholder location="classpath:blue.properties"/>

    <bean class="com.example.demo.bean.Blue">
        <property name="title" value="${blue.title}"/>
        <property name="rank" value="${blue.rank}"/>
    </bean>
</beans>

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

@Value注解式屬性注入的應用。

創(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)建啟動類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);
    }

}

運行結果如下:

引入外部配置文件@PropertySource。

創(chuàng)建Blue類和配置文件,沒有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 {

}

修改啟動類,引入配置類:

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);
    }
}

運行結果如下:

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

在使用XML配置的情況下,我們需要創(chuàng)建一個XML文件來替代InjectValueConfiguration類,我們可以先注釋掉InjectValueConfiguration類的所有內容。

下面是相應的XML文件內容:

<?xml versinotallow="1.0" encoding="UTF-8"?>
<beans xmlns="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">
    <!-- 相當于注解中的 @PropertySource("classpath:blue.properties") -->
    <context:property-placeholder location="classpath:blue.properties"/>

    <bean class="com.example.demo.bean.Blue">
        <property name="title" value="${blue.title}"/>
        <property name="rank" value="${blue.rank}"/>
    </bean>

</beans>

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

這里還需要修改下Blue類,因為通過XML方法注入屬性需要提供相應的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 + '}';
    }
}

然后,我們需要修改啟動類,使用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);
    }
}

運行結果如下:

四、SpEL表達式

當我們談到屬性注入的時候,我們可能會遇到一些復雜的需求,例如我們需要引用另一個Bean的屬性,或者我們需要動態(tài)處理某個屬性值。這種需求無法通過使用${}的占位符方式實現,我們需要一個更強大的工具:SpEL表達式。

Spring Expression Language(SpEL)是從Spring框架 3.0開始支持的強大工具。SpEL不僅是Spring框架的重要組成部分,也可以獨立使用。它的功能豐富,包括調用屬性值、屬性參數、方法調用、數組存儲以及邏輯計算等。它與開源項目OGNL(Object-Graph Navigation Language)相似,但SpEL是Spring框架推出的,并默認內嵌在Spring框架中。

1、使用@Value注解和SpEL表達式實現屬性注入

SpEL的表達式用#{}表示,花括號中就是我們要編寫的表達式。

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

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

@Component
public class Azure {
    
    @Value("#{'spel-for-azure'}")
    private String name;
    
    @Value("#{10}")
    private Integer priority;
}

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

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

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

我們已經注冊了Azure Bean,現在我們再創(chuàng)建一個Bean,命名為Emerald。我們按照上述方法對字段和方法進行聲明,然后使用@Component注解標注。

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

@Component
public class Emerald {
    
    @Value("#{'copy of ' + azure.name}")
    private String name;
    
    @Value("#{azure.priority + 1}")
    private Integer priority;
}

在Spring的SpEL中可以通過bean的名稱訪問到對應的bean,并通過.操作符訪問bean的屬性。在這個例子中,azure就是一個bean的名稱,它對應的bean就是Azure類的實例。所以,azure.name就是訪問Azure類實例的name屬性。

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

我們修改啟動類,測試運行,可以看到Azure的屬性已經成功被復制:

use spel bean property : Emerald{name='copy of spel-for-azure', priority=11}

SpEL表達式不僅可以引用對象的屬性,還可以直接引用類的常量,以及調用對象的方法。下面我們通過示例進行演示。

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

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

@Component
public class Ivory {
    
    @Value("#{azure.name.substring(0, 3)}")
    private String name;
    
    @Value("#{T(java.lang.Integer).MAX_VALUE}")
    private Integer priority;
}

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

我們修改啟動類,測試運行,可以看到Ivory的屬性已經是處理之后的值:

use spel methods : Ivory{name='spe', priority=2147483647}

2、在XML中使用SpEL表達式實現屬性注入:

<bean id="ivory" class="com.example.demo.bean.Ivory">
    <property name="name" value="#{azure.name.substring(0, 3)}" />
    <property name="priority" value="#{T(java.lang.Integer).MAX_VALUE}" />
</bean>

學習SpEL表達式不需要花費大量的精力,掌握基礎的使用方法即可。

3、SpEL表達式屬性注入完整代碼示例

使用@Value注解和SpEL表達式實現屬性注入。

創(chuàng)建三個SpEL表達式屬性注入的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是一個用于展示如何在Spring中通過SpEL表達式來注入屬性的類,它聚合了三個對象Azure, Emerald和Ivory,并通過Spring的依賴注入機制將這三個對象注入到了MyBean類的實例中。

主程序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();
    }
}

運行結果:

在XML中使用SpEL表達式實現屬性注入。

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

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

<?xml versinotallow="1.0" encoding="UTF-8"?>
<beans xmlns="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-scan base-package="com.example" />

    <bean id="azure" class="com.example.demo.bean.Azure">
        <property name="name" value="#{'spel-for-azure'}" />
        <property name="priority" value="#{10}" />
    </bean>

    <bean id="emerald" class="com.example.demo.bean.Emerald">
        <property name="name" value="#{'copy of ' + azure.name}" />
        <property name="priority" value="#{azure.priority + 1}" />
    </bean>

    <bean id="ivory" class="com.example.demo.bean.Ivory">
        <property name="name" value="#{azure.name.substring(0, 3)}" />
        <property name="priority" value="#{T(java.lang.Integer).MAX_VALUE}" />
    </bean>
</beans>

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

然后修改這3個Bean,如果是使用XML來配置Spring的Bean的話,那么在Java類中就不需要使用@Component注解了。因為XML配置文件已經明確地告訴Spring這些類是Spring Bean。

同樣的,如果在XML文件中定義了Bean的屬性值,那么在Java類中就不需要使用@Value注解來注入這些值了。因為XML配置文件已經明確地為這些屬性賦了值。

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 +
                '}';
    }
}

然后需要在主程序中導入這個XML配置文件,這可以通過在主程序中添加@ImportResource注解實現:

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了。

運行結果如下:

責任編輯:姜華 來源: 哪吒編程
相關推薦

2019-03-13 08:56:07

JavaSpEL表達式注入

2021-05-07 17:11:19

負載均衡運維服務

2022-03-07 17:43:30

注冊微服務架構

2009-09-11 09:48:27

Linq Lambda

2009-09-10 15:35:07

LINQ查詢表達式

2022-09-26 11:32:14

用戶分層服務業(yè)務

2021-03-18 12:16:44

用戶分層業(yè)務

2009-09-07 17:18:33

LINQ查詢表達式

2021-10-22 09:28:15

開發(fā)技能代碼

2020-09-03 09:38:06

ElasticsearES Lucene

2022-07-05 11:18:50

數據分析銷售業(yè)績

2021-01-28 11:39:01

數據分析銷售

2018-05-28 21:17:57

大數據分析軟件

2022-05-07 08:39:37

SQL死鎖InnoDB鎖

2023-11-27 08:28:37

SpEL表達式

2010-08-12 10:35:06

Flex正則表達式

2024-09-14 09:18:14

Python正則表達式

2015-04-01 13:57:49

2017-10-13 12:51:36

語言PHP、Python、差異比較

2022-07-06 10:56:51

數據湖架構
點贊
收藏

51CTO技術棧公眾號

黄色www视频| 北岛玲一区二区| 国产视频在线播放| 国产98色在线|日韩| 午夜精品福利视频| 黄色aaa视频| 日韩毛片免费看| 亚洲国产成人高清精品| 日本在线视频不卡| 国产精品视频a| 亚洲三级观看| 日韩中文有码在线视频| 少妇熟女视频一区二区三区| 伊人久久综合一区二区| 亚洲视频免费在线| 久久精品magnetxturnbtih| 中文字幕在线日亚洲9| 自产国语精品视频| 亚洲视频在线观看| 色欲欲www成人网站| 欧美一区久久久| 一区二区三区.www| 亚洲国产一区二区在线| 国产综合视频在线| 蜜桃一区二区三区在线观看| 亚州精品天堂中文字幕| 91ts人妖另类精品系列| 色男人天堂av| 国产午夜精品无码| 国产一区二区三区天码| 美女视频一区免费观看| 尤物精品国产第一福利三区 | 欧美片第1页综合| 亚洲人成啪啪网站| 国产黑丝在线观看| 国产色99精品9i| 欧美吞精做爰啪啪高潮| 无码 制服 丝袜 国产 另类| 麻豆影视国产在线观看| 久久人人超碰精品| 国内精品久久国产| 超碰免费在线97| 久久99久久99小草精品免视看| 97福利一区二区| 久久精品女人毛片国产| 亚洲欧美综合久久久| 最近2019年中文视频免费在线观看| 国产一级二级在线观看| 超碰成人福利| 精品国产乱码久久久久久牛牛| www.污网站| 日本国产亚洲| 欧美日韩成人综合天天影院| 别急慢慢来1978如如2| 厕沟全景美女厕沟精品| 欧美日韩亚洲视频一区| 日韩在线综合网| 三妻四妾的电影电视剧在线观看| 亚洲成人激情综合网| 国产小视频免费| 日韩经典av| 久久精品综合一区| 多男操一女视频| 欧美电影免费| 色哟哟网站入口亚洲精品| 美女被到爽高潮视频| 美女久久久久| 亚洲天堂第一页| 精品欧美一区二区久久久| 制服丝袜日韩| 亚洲视频在线视频| 欧美成人另类视频| 日本黄色精品| 精品激情国产视频| 在线观看黄网址| 亚洲精品97| 欧美激情视频一区| 国产精品老女人| 久久国产主播| 成人黄色免费网站在线观看| 国产不卡av在线播放| 岛国av在线一区| 乱一区二区三区在线播放| 国产三级在线免费观看| 最新日韩av在线| 欧洲精品在线播放| 在线天堂中文资源最新版| 欧美亚洲国产一区二区三区va| 亚洲36d大奶网| 日韩激情欧美| 亚洲剧情一区二区| 欧美a级片免费看| 国产综合激情| 国产精品成人久久久久| 国产aⅴ爽av久久久久成人| www.欧美亚洲| 五月天色一区| 欧美理论片在线播放| 狠狠色噜噜狠狠狠狠97| 少妇一级淫免费放| 岛国av一区| 色偷偷91综合久久噜噜| 国产精品16p| 麻豆一区二区三区| 国产无套精品一区二区| 日本不卡不卡| 欧美视频一区二区三区…| 在线黄色免费看| 欧美日韩麻豆| 美女性感视频久久久| 无码人妻丰满熟妇区bbbbxxxx| 国产一区91精品张津瑜| 欧美日韩大片一区二区三区| 色图在线观看| 欧美午夜精品久久久久久超碰| 午夜福利三级理论电影| 人人狠狠综合久久亚洲婷| 97精品国产97久久久久久免费| 一区二区三区免费在线| 2020国产精品久久精品美国| 五月天激情图片| 成人免费毛片嘿嘿连载视频…| 亚洲国内精品在线| 五月天丁香激情| 毛片不卡一区二区| 欧美中文娱乐网| 华人av在线| 精品国免费一区二区三区| a一级免费视频| 石原莉奈一区二区三区在线观看| 国产亚洲欧美一区二区三区| 18videosex性欧美麻豆| 欧美日本在线播放| 在线国产视频一区| 亚洲视频播放| 精品欧美一区二区三区久久久| 在线中文字幕电影| 欧美裸体bbwbbwbbw| 无码国产69精品久久久久同性| 亚洲成人直播| 成人免费视频视频在| 麻豆传媒在线观看| 欧美日韩在线亚洲一区蜜芽| 欧美成人国产精品一区二区| 男人的天堂亚洲| 久久偷窥视频| 欧美男人天堂| 日韩av影片在线观看| 日本少妇吞精囗交| 99精品欧美一区二区三区小说| 亚洲国产精品无码观看久久| 中文字幕一区二区三区日韩精品| zzjj国产精品一区二区| 国产精品视频无码| 亚洲人成影院在线观看| 国产人妻精品久久久久野外| 91欧美国产| 91在线高清视频| 在线网址91| 欧美精品一区二区久久婷婷| 国产大片aaa| 91免费视频大全| 亚洲爆乳无码专区| 精品大片一区二区| 国产精品中文字幕在线| 麻豆系列在线观看| 日韩欧美国产麻豆| 日韩成人在线免费视频| 99国产精品视频免费观看| 欧美日韩中文在线视频| 欧美伦理影院| 92福利视频午夜1000合集在线观看 | 偷拍夫妻性生活| 丝袜亚洲另类欧美| 在线看视频不卡| 亚洲日本视频在线| 91精品国产免费久久久久久| 黄色美女网站在线观看| 欧美精品丝袜中出| 国产在线观看99| 久久综合精品国产一区二区三区| 欧美精品性生活| 欧美一区不卡| 久久亚洲综合网| 亚洲一区av| 性欧美亚洲xxxx乳在线观看| 超碰在线国产| 日韩视频免费观看高清在线视频| 精品国产乱码一区二区| 国产精品网曝门| 香蕉在线观看视频| 视频一区二区不卡| 人人妻人人澡人人爽欧美一区| 亚洲第一论坛sis| 91久久久精品| 亚洲美女久久精品| 不卡av在线播放| 国内在线免费高清视频| 宅男在线国产精品| 你懂的国产在线| 亚洲免费观看高清| jizz中文字幕| 岛国精品在线观看| 无尽裸体动漫2d在线观看| 亚洲人成免费| 亚洲精品偷拍视频| 蜜桃国内精品久久久久软件9| 亚洲精品女av网站| 朝桐光一区二区| 久久久免费高清电视剧观看| 在线看黄色av| 亚洲黄色在线看| 99热这里只有精品1| 色婷婷av一区二区三区gif| 青青草原国产视频| 亚洲国产岛国毛片在线| 在线观看亚洲免费视频| 韩国精品久久久| 国产精品无码一本二本三本色| 欧美日韩国产高清| 亚洲国产精品www| 亚洲影院天堂中文av色| 99在线高清视频在线播放| 九九热这里有精品| 国产成人精品在线| 日本不卡免费高清视频在线| 久久97久久97精品免视看| 91涩漫在线观看| 国产亚洲精品91在线| 亚洲av成人精品日韩在线播放| 欧美大片在线观看一区二区| 91精品视频免费在线观看| 色欧美88888久久久久久影院| 国产精品自拍视频一区| 一区二区三区久久久| tube国产麻豆| 中文字幕日韩一区| 亚洲一二三精品| 久久久国产午夜精品| 在线免费观看污视频| 成人做爰69片免费看网站| 亚洲三级在线观看视频| 蜜臀av性久久久久蜜臀av麻豆| 国产av人人夜夜澡人人爽| 视频一区二区国产| 爱情岛论坛vip永久入口| 乱码第一页成人| 日韩网址在线观看| 亚洲欧美日韩在线观看a三区| 欧美a v在线播放| 999亚洲国产精| 逼特逼视频在线| 久久xxxx| 国产又大又黄又粗的视频| 日本不卡123| 成年网站免费在线观看| 麻豆91在线看| 91欧美一区二区三区| 国产精品一二三四区| 国产精品日日摸夜夜爽| 成人精品国产一区二区4080| 波多野结衣有码| 久久夜色精品国产欧美乱极品| 女尊高h男高潮呻吟| 国产日韩亚洲欧美综合| www.com.av| 亚洲另类在线一区| 国产一级中文字幕| 动漫精品一区二区| 无码无套少妇毛多18pxxxx| 欧美亚洲一区二区在线观看| 国产一区二区三区四区视频 | 99热国内精品永久免费观看| 欧美性受黑人性爽| 亚洲视频碰碰| 国产超级av在线| 久久99精品一区二区三区三区| 51自拍视频在线观看| 成人avav在线| 亚洲精品一区二区三区影院忠贞| 国产精品不卡视频| 国模无码国产精品视频| 欧美日韩在线影院| 亚洲天堂avav| 亚洲成人性视频| 成人免费视频| 欧美精品国产精品日韩精品| 成人小电影网站| 成人网在线免费观看| 久久99偷拍| 亚洲一二三区精品| 在线精品一区| 热久久久久久久久| 99久久99久久精品国产片果冻| 男人天堂资源网| 偷拍亚洲欧洲综合| 91麻豆成人精品国产免费网站| 亚洲国产欧美久久| 色网站在线看| 91高清视频在线免费观看| 激情欧美一区二区三区黑长吊| www国产亚洲精品| av中字幕久久| 91九色丨porny丨国产jk| 麻豆成人av在线| 美女100%无挡| 亚洲国产日韩a在线播放性色| 在线视频精品免费| 亚洲国产精品一区二区三区| 大地资源网3页在线观看| 热久久这里只有| 永久免费精品视频| 一本色道久久综合亚洲二区三区| 日韩视频中文| 国产又粗又猛又爽又黄| 中文幕一区二区三区久久蜜桃| 日韩精品视频免费看| 欧美一区二区三区免费在线看| 高清毛片在线看| 国内精品400部情侣激情| 综合久久av| 水蜜桃亚洲一二三四在线| 国产欧美日本| 黑森林av导航| 一区二区三区中文字幕电影 | 国产精品正在播放| 美女100%露胸无遮挡| 欧美性色xo影院| 色偷偷在线观看| 欧美激情亚洲自拍| www.欧美视频| 中文字幕中文字幕在线中一区高清 | 欧美成人激情图片网| 国产精品毛片久久久久久久久久99999999| 国产伦精品一区二区三区四区免费| 91精品一区二区三区综合| 色婷婷狠狠18| 国产精品私房写真福利视频| 久久久久久无码精品大片| 亚洲精品永久免费| 无遮挡爽大片在线观看视频| 精品欧美国产| 男人的天堂成人在线| 色欲av无码一区二区三区| 精品久久久免费| 色视频在线看| 国产成人免费av| 国产探花一区在线观看| 91看片就是不一样| 国产欧美日韩精品在线| 中文字幕乱码一区二区| 中文字幕国内精品| 久久69成人| 黄色录像特级片| 国产成人午夜精品影院观看视频| 欧美三级免费看| 精品三级在线看| 国产乱码精品一区二三赶尸艳谈| 精品国产免费久久久久久尖叫 | 超碰在线人人干| 欧美激情综合亚洲一二区| 999久久久精品一区二区| 久久国产精品网| 91视视频在线直接观看在线看网页在线看| 黄网站免费在线| 日韩精品免费在线视频观看| 色尼玛亚洲综合影院| 视频三区二区一区| 久久99国产精品久久| 国产a免费视频| 亚洲国产另类久久精品| 欧美91看片特黄aaaa| 亚洲一区二区自拍偷拍| 国产黄人亚洲片| 日韩欧美一级视频| 一本色道久久综合亚洲精品小说| 深夜福利亚洲| 日本大片免费看| 久久一区二区三区四区| 伊人久久亚洲综合| 欧美成人免费在线观看| 欧美aaaaaaaa牛牛影院| 日本熟妇人妻中出| 一区二区三区小说| 色视频免费在线观看| 成人黄色片在线| 日韩亚洲国产欧美| 欧美福利第一页| 精品日产卡一卡二卡麻豆| 黑人巨大精品| 欧美精品久久96人妻无码| 99久久国产综合精品色伊| 免费黄色一级大片| 欧美激情一区二区三区成人| 国产一区网站| 中文字幕无码毛片免费看| 色综合色综合色综合色综合色综合 | 一本色道久久88亚洲精品综合| 久久综合色8888| 国产黄色免费大片|