国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring高手之路3——揭秘Spring依賴注入和SpEL表達(dá)式

這篇具有很好參考價(jià)值的文章主要介紹了Spring高手之路3——揭秘Spring依賴注入和SpEL表達(dá)式。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

本篇會(huì)給大家舉出各種Spring屬性依賴注入的例子,方便大家理解。

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">
    <property name="username" value="example-username-setter"/>
    <property name="age" value="25"/>
</bean>

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類,并在其中包含usernameage兩個(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。

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

然后,我們需要?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é)果如下:

Spring高手之路3——揭秘Spring依賴注入和SpEL表達(dá)式

  • 使用@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è)<bean>元素。這個(gè)方法的名稱就是Beanid,方法的返回值就是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é)果如下
Spring高手之路3——揭秘Spring依賴注入和SpEL表達(dá)式

??注意: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)致我們之前的<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)簽的編寫規(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屬性表示構(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-arg name="username" value="example-username-constructor"/>
    <constructor-arg name="age" value="25"/>
</bean>

這樣無(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類,并在其中包含usernameage兩個(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ì)比

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

    <!-- 構(gòu)造器注入 -->
    <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>

然后,我們需要?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é)果如下:

Spring高手之路3——揭秘Spring依賴注入和SpEL表達(dá)式

  • 使用@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é)果:
Spring高手之路3——揭秘Spring依賴注入和SpEL表達(dá)式

注意:如果在類中同時(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開始。創(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容器中,并將其取出并打?。?/p>

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

  1. 創(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
  1. 引入配置文件

使用@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.propertiesapplication.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ù)念愋汀?/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 {
    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.propertiesapplication.yml文件。我們可以通過(guò)設(shè)置spring.config.namespring.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...
}
  1. Blue類的屬性注入

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

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

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

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

  1. 測(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相同的方式使用占位符:

<?xml version="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">
    <!-- 相當(dāng)于注解中的 @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>

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é)果如下:

Spring高手之路3——揭秘Spring依賴注入和SpEL表達(dá)式

  • 引入外部配置文件@PropertySource

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

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é)果如下:

Spring高手之路3——揭秘Spring依賴注入和SpEL表達(dá)式

  • 在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"?>
<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">
    <!-- 相當(dāng)于注解中的 @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標(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é)果如下:

Spring高手之路3——揭秘Spring依賴注入和SpEL表達(dá)式

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

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

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

??我們創(chuàng)建一個(gè)Bean,命名為Azure,同樣地,我們聲明屬性namepriority,并提供gettersetter方法以及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ù)制Azurename屬性,而priority屬性則希望比Azurepriority屬性大1,我們可以這樣編寫:

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

??在SpringSpEL中可以通過(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è)特性依賴于SpringIoC容器。

我們修改啟動(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è)需求,讓nameazure屬性的前3個(gè)字符,priorityInteger的最大值。那么我們可以使用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()包圍。

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

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

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

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

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

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

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

創(chuàng)建三個(gè)SpEL表達(dá)式屬性注入的BeanAzure.java、Emerald.javaIvory.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, EmeraldIvory,并通過(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é)果:
Spring高手之路3——揭秘Spring依賴注入和SpEL表達(dá)式

  • 在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"?>
<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個(gè)Bean,如果是使用XML來(lái)配置SpringBean的話,那么在Java類中就不需要使用@Component注解了。因?yàn)?code>XML配置文件已經(jīng)明確地告訴Spring這些類是Spring Bean。

??同樣的,如果在XML文件中定義了Bean的屬性值,那么在Java類中就不需要使用@Value注解來(lái)注入這些值了。因?yàn)?code>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();
    }

}

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

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

Spring高手之路3——揭秘Spring依賴注入和SpEL表達(dá)式文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-479235.html



歡迎一鍵三連~

有問(wèn)題請(qǐng)留言,大家一起探討學(xué)習(xí)

----------------------Talk is cheap, show me the code-----------------------

到了這里,關(guān)于Spring高手之路3——揭秘Spring依賴注入和SpEL表達(dá)式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Web攻防--Java_SQL注入--XXE注入-- SSTI模板注入--SPEL表達(dá)式注入

    編譯器在編譯sql語(yǔ)句時(shí),會(huì)依次進(jìn)行詞法分析、語(yǔ)法分析、語(yǔ)義分析等操作, 預(yù)編譯技術(shù)會(huì)讓數(shù)據(jù)庫(kù)跳過(guò)編譯階段,也就無(wú)法就進(jìn)行詞法分析,不會(huì)被拆開,注入語(yǔ)句也就不會(huì)被識(shí)別為SQL的,從而防止惡意注入語(yǔ)句改變?cè)蠸QL語(yǔ)句本身邏輯。 在使用JDBC進(jìn)行數(shù)據(jù)

    2024年02月09日
    瀏覽(24)
  • Day66:WEB攻防-Java安全&SPEL表達(dá)式&SSTI模版注入&XXE&JDBC&MyBatis注入

    Day66:WEB攻防-Java安全&SPEL表達(dá)式&SSTI模版注入&XXE&JDBC&MyBatis注入

    目錄 JavaSec搭建 Hello-Java-Sec搭建 Java安全-SQL注入-JDBCMyBatis JDBC:Java語(yǔ)言連接數(shù)據(jù)庫(kù)操作 MyBatis( mybatis是一個(gè)優(yōu)秀的基于java的持久層框架,它內(nèi)部封裝了 jdbc) 代碼審計(jì)案例:inxedu后臺(tái)MyBatis注入 Java安全-XXE注入-ReaderBuilder 配置XML允許引入外部解析實(shí)體 白盒測(cè)試-XXE Java安全-SSTI模版

    2024年04月25日
    瀏覽(16)
  • Spring中的SpEL表達(dá)式

    SpEL (Spring Expression Language) 是 Spring 框架中用于在運(yùn)行時(shí)對(duì)對(duì)象圖進(jìn)行查詢和操作的表達(dá)式語(yǔ)言。它可以在不引入 Java 代碼的情況下,輕松地對(duì)對(duì)象進(jìn)行值的計(jì)算、屬性的讀取、調(diào)用方法、訪問(wèn)數(shù)組和集合等。SpEL廣泛應(yīng)用于Spring框架的許多模塊中,比如Spring MVC、Spring Data、Sp

    2024年02月15日
    瀏覽(28)
  • Spring表達(dá)式語(yǔ)言(SPEL)學(xué)習(xí)(03)

    在表達(dá)式中直接寫name和getName(),這時(shí)候Expression是無(wú)法解析的,因?yàn)槠洳恢纍ame和getName()對(duì)應(yīng)什么意思 當(dāng)表達(dá)式是基于某一個(gè)對(duì)象時(shí),我們可以把對(duì)應(yīng)的對(duì)象作為一個(gè)rootObject傳遞給對(duì)應(yīng)的Experssion進(jìn)行取值 通過(guò)指定EvaluationContext我們可以讓name和getName()變得有意義,指定了Ev

    2024年02月02日
    瀏覽(51)
  • javaee spring依賴注入之spel方式

    2024年02月11日
    瀏覽(23)
  • Spring判斷方法名是符合給定的SPEL+表達(dá)式的+API

    org.springframework.expression.spel.standard.SpelExpressionParser解析SPEL表達(dá)式 org.springframework.expression.spel.support.StandardEvaluationContext 驗(yàn)證方法名是否符合表達(dá)式 我們先使用SpelExpressionParser類來(lái)解析表達(dá)式,然后再創(chuàng)建一個(gè)StandardEvaluationContext對(duì)象,并將方法名作為變量設(shè)置到上下文中。最后

    2024年02月10日
    瀏覽(21)
  • 最新最全面的Spring詳解(三)——Resources,驗(yàn)證、數(shù)據(jù)綁定和類型轉(zhuǎn)換與Spring表達(dá)式語(yǔ)言(SpEL)

    最新最全面的Spring詳解(三)——Resources,驗(yàn)證、數(shù)據(jù)綁定和類型轉(zhuǎn)換與Spring表達(dá)式語(yǔ)言(SpEL)

    本文為 【Spring】Resources與Spring表達(dá)式語(yǔ)言(SpEL) 等相關(guān)知識(shí),下邊將對(duì) Resources (包含: Resource接口 、 內(nèi)置的 Resource的實(shí)現(xiàn) 、 ResourceLoader接口 、 應(yīng)用環(huán)境和資源路徑 ), 驗(yàn)證、數(shù)據(jù)綁定和類型轉(zhuǎn)換 (包含: BeanWrapper 、 PropertyEditor屬性編輯器 、 類型轉(zhuǎn)換 、 配置 DataB

    2023年04月26日
    瀏覽(26)
  • SpEL表達(dá)式詳解

    SpEL表達(dá)式詳解

    中文spring官網(wǎng):https://itmyhome.com/spring/expressions.html 英文spring官網(wǎng):https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions Spring Expression Language (簡(jiǎn)稱SpEL)是一種功能強(qiáng)大的表達(dá)式語(yǔ)言,是 spring 提供的,該語(yǔ)言類似于JSP當(dāng)中的EL表達(dá)式。但提供了很多額外的功能,最

    2023年04月08日
    瀏覽(21)
  • 【SpringBoot應(yīng)用篇】【AOP+注解】SpringBoot+SpEL表達(dá)式基于注解實(shí)現(xiàn)權(quán)限控制

    Spring 表達(dá)式語(yǔ)言 SpEL 是一種非常強(qiáng)大的表達(dá)式語(yǔ)言,它支持在運(yùn)行時(shí)查詢和操作對(duì)象圖。 它提供了許多高級(jí)功能,例如方法調(diào)用和基本的字符串模板功能。 表達(dá)式語(yǔ)言給靜態(tài)Java語(yǔ)言增加了動(dòng)態(tài)功能。 Spring 表達(dá)式語(yǔ)言最初是為 Spring 社區(qū)創(chuàng)建的,它擁有一種受良好支持的表

    2024年02月20日
    瀏覽(58)
  • Spring Boot 目錄遍歷--表達(dá)式注入--代碼執(zhí)行--(CVE-2021-21234)&&(CVE-2022-22963)&&(CVE-2022-22947)&&(CVE-2022-2296)

    Spring Boot 目錄遍歷--表達(dá)式注入--代碼執(zhí)行--(CVE-2021-21234)&&(CVE-2022-22963)&&(CVE-2022-22947)&&(CVE-2022-2296)

    spring-boot-actuator-logview 是一個(gè)簡(jiǎn)單的日志文件查看器作為Spring Boot執(zhí)行器端點(diǎn),在 0.2.13 版本之前存在著目錄遍歷漏洞,編號(hào) CVE-2021-21234。漏洞本質(zhì)是Spring Boot 執(zhí)行器通過(guò)請(qǐng)求的參數(shù)來(lái)指定文件名和文件夾路徑,經(jīng)過(guò)組合拼接達(dá)到目錄遍歷,雖然源碼中檢查了文件名(filename)

    2024年02月08日
    瀏覽(61)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包