0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

探讨Spring框架中的属性注入技术

OSC开源社区 来源:OSCHINA 社区 2023-06-14 09:37 次阅读

在本文中,我们深入探讨了 Spring 框架中的属性注入技术,包括 setter 注入、构造器注入、注解式属性注入,以及使用 SpEL 表达式进行属性注入。我们通过 XML 和注解两种方式,详细讲解了如何进行属性注入,并给出了完整的代码示例。无论你是 Spring 新手,还是有一定经验的开发者,本文都将帮助你理解并掌握 Spring 中的属性注入技术。

1. setter 属性注入

1.1 使用 XML 进行 setter 方法注入

我们在前面的文章中已经使用过 XML 进行 setter 方法的属性注入了,下面让我们再来回顾一下:


 
 
1.2 使用 @Bean 注解进行 setter 方法注入 我们在前面的文章中也学习过如何在 bean 创建时通过编程方式设置属性:
@Bean
public User user() {
    User user = new User();
 user.setUsername("example-username-anno-setter");
 user.setAge(25);
 return user;
}
1.3 setter 方法注入完整代码示例

使用 XML 进行 setter 方法注入

首先,我们需要创建一个 User 类,并在其中包含 username 和 age 两个属性,以及相应的 getter、setter 方法和构造器。

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

对于 XML 方式的 setter 注入和构造器注入,我们需要创建一个配置文件,比如叫 applicationContext.xml。


  
 
 
 
 

然后,我们需要创建一个 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);
 }
}
运行结果如下:

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

使用 @Bean 注解进行 setter 方法注入

我们需要创建一个配置类,例如叫 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 来创建 Spring 的应用上下文,并加载配置类。Spring 会自动从配置类中获取所有的 Bean 定义,并创建相应的 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);
 }
}
运行结果如下

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

注意:XML 配置方式已经相对陈旧,而且在 Spring Boot 项目中,主流的做法是使用注解和 Java 配置方式。对于 setter 注入,有时会引发循环依赖的问题。在 Spring 中,可以使用构造器注入来避免这种情况,这里了解即可。

2. 构造器注入

setter 注入是一种在对象被实例化之后(通过调用无参构造器创建实例)再通过 setter 方法注入依赖的方式。构造器注入则是在创建对象实例的时候就通过构造器参数来注入依赖。 为了演示构造器注入,我们需要给 User 添加一个全参数构造器:

public User(String username, Integer age) {
 this.username = username;
 this.age = age;
}
添加这个构造器后,Java 不再提供默认的无参构造器,这会导致我们之前的 标签创建时失败,因为它找不到默认的构造器。

2.1 使用 XML 进行构造器注入

我们可以在 标签内部声明一个子标签:constructor-arg。它用于指定构造器的参数,来进行属性注入。constructor-arg 标签的编写规则如下:


 
 
index 属性表示构造函数参数的位置,它的值是一个非负整数,其中 0 表示第一个参数,1 表示第二个参数,以此类推。虽然 value 属性的值总是一个字符串,但是 Spring 会尝试将它转换为构造函数参数所需的类型。例如构造函数的第二个参数是 int 类型,那么 Spring 会尝试将字符串 "25" 转换为整数 25。 使用 index 属性来指定构造函数参数的位置在大多数情况下是可以的,但是如果构造函数的参数数量或者顺序发生了改变,就可能会出错。另外一种更为可靠的方式是使用 name 属性来指定参数的名称,如:

 
 
这样无论参数的顺序如何,只要参数名称不变,就不会出错。

2.2 使用 @Bean 注解进行构造器属性注入

在注解驱动的 bean 注册中,我们也可以直接使用编程方式赋值:

@Bean
public User user() {
 return new User("example-username-anno-constructor", 25);
}
2.3 构造器注入的完整代码示例

使用 XML 进行构造器注入

首先,我们需要创建一个 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;
 }
 // 为了节省篇幅,getter和setter方法省略......
    @Override
 public String toString() {
 return "User{username='" + username + "', age=" + age + "}";
 }
}

对于 XML 方式的构造器注入,我们需要创建一个配置文件,比如叫 applicationContext.xml,这里保留 setter 注入方便大家对比


  
  
 
 
 
 
  
 
 
 
 

然后,我们需要创建一个 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);
 }
}
运行结果如下:

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

使用 @Bean 注解进行构造器属性注入

我们需要创建一个配置类,例如叫 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);
 }
}

同样,我们需要创建一个 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);
 }
}
运行结果:

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

注意:如果在类中同时使用构造器注入和 setter 注入,需要注意它们注入的顺序:先进行构造器注入,然后是 setter 注入。

3. 注解式属性注入

上面我们已经说过注解式的 setter 和构造器注入。我们又是如何处理那些通过 @Component 扫描而注册的 bean 的属性的呢?我们来仔细说说这个问题,同时展示如何在 xml 中进行相同的操作。

3.1 @Value 注解式属性注入的应用

首先,让我们从最简单的属性注入方法:@Value 开始。创建一个新的 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}
3.2 引入外部配置文件 @PropertySource 如果我们需要在 Spring 中使用 properties 文件,我们应该怎么办呢?Spring 考虑到了这一点,并扩展了一个用于导入外部配置文件的注解:@PropertySource。

创建 Bean 和配置文件

创建一个新的 Blue 类,其结构与 White 类完全相同。然后在项目的 resources 目录下创建一个新的 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 注解加载的属性文件。

系统环境变量。

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

当我们使用 ${...}`占位符语法来引用一个配置项时,`Spring`会查找这个`Map`,取出与占位符名称相应的配置项的值。例如有一个配置项`blue.title=blue-value-properties`,我们可以在代码中使用`${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 能够发现并处理这些注解。

或者,你也可以使用 @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 表达式,会发现这和它非常相似!

测试启动类

修改启动类,将配置类引入,然后取出并打印 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.3 在 XML 中引入外部配置文件 在 xml 中,我们可以和 @Value 相同的方式使用占位符:


  
 
 
 
 
 
3.4 注解式属性注入完整代码示例

@Value 注解式属性注入的应用

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

创建启动类 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);
 }
}
运行结果如下:

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

引入外部配置文件 @PropertySource

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

创建配置类 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);
 }
}
运行结果如下:

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

在 xml 中引入外部配置文件

在使用 XML 配置的情况下,我们需要创建一个 XML 文件来替代 InjectValueConfiguration 类,我们可以先注释掉 InjectValueConfiguration 类的所有内容 下面是相应的 XML 文件内容:



  
 
 
 
 
 
在这里我们使用了 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);
 }
}
运行结果如下:

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

4. SpEL 表达式

当我们谈到属性注入的时候,我们可能会遇到一些复杂的需求,例如我们需要引用另一个 Bean 的属性,或者我们需要动态处理某个属性值。这种需求无法通过使用 ${} 的占位符方式实现,我们需要一个更强大的工具:SpEL 表达式。 Spring Expression Language(SpEL)是从 Spring 框架 3.0 开始支持的强大工具。

SpEL 不仅是 Spring 框架的重要组成部分,也可以独立使用。它的功能丰富,包括调用属性值、属性参数、方法调用、数组存储以及逻辑计算等。它与开源项目 OGNL(Object-Graph Navigation Language)相似,但 SpEL 是 Spring 框架推出的,并默认内嵌在 Spring 框架中。

4.1 使用 @Value 注解和 SpEL 表达式实现属性注入

SpEL 的表达式用 #{} 表示,花括号中就是我们要编写的表达式。 我们创建一个 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,现在我们再创建一个 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 的环境中使用 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}
4.2 在 XML 中使用 SpEL 表达式实现属性注入:

 
 
学习 SpEL 表达式不需要花费大量的精力,掌握基础的使用方法即可。 4.3 SpEL 表达式属性注入完整代码示例

使用 @Value 注解和 SpEL 表达式实现属性注入

创建三个 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();
 }
}
运行结果:

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

在 XML 中使用 SpEL 表达式实现属性注入

对于 XML 配置,Spring 还支持在 bean 定义中使用 SpEL。 首先,需要创建一个 Spring XML 配置文件,我们将其命名为 app-config.xml:



 
 
 
 
 
 
 
 
 
 
 
 
 
注意:在 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 了。 运行结果如下:

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






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 存储器
    +关注

    关注

    38

    文章

    7447

    浏览量

    163586
  • JAVA语言
    +关注

    关注

    0

    文章

    138

    浏览量

    20073
  • XML技术
    +关注

    关注

    0

    文章

    15

    浏览量

    6010
  • YAML
    +关注

    关注

    0

    文章

    21

    浏览量

    2314

原文标题:揭秘Spring依赖注入和SpEL表达式

文章出处:【微信号:OSC开源社区,微信公众号:OSC开源社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    java spring教程

    Spring核心概念介绍控制反转(IOC)依赖注入(DI)集合对象注入等Bean的管理BeanFactoryApplicationContextSpring 在web的使用
    发表于 09-11 11:09

    什么是java spring

    。在SSH项目中管理事务以及对象的注入Spring是非侵入式的:基于Spring开发的系统的对象一般不依赖于Spring的类。组成
    发表于 09-11 11:16

    怎么阅读Spring源码

    封装,很有可能在读源码的过程掉到各种细节里出不来,所以读这种源码要事无巨细,理解原理即可。基本原理其实就是通过反射解析类及其类的各种信息,包括构造器、方法及其参数,属性。然后将其封装成bean定义
    发表于 05-04 15:21

    三大框架Spring

    ;出现了Spring,可以自动创建需要被调用的对象以及进行属性注入,也可以维护这些bean(具体的java类)之间的关系;
    发表于 05-27 07:21

    Spring框架的设计理念

    Spring作为现在最优秀的框架之一,已被广泛的使用,51CTO也曾经针对Spring框架的hqC应用做过报道。本文将从另外一个视角试图剖
    发表于 07-15 08:17

    一文解析Spring框架

    Spring框架详解 - 03
    发表于 06-17 17:15

    Spring笔记分享

    ; 可以管理所有的组件(类)Spring的优良特性1) 非侵入式:基于Spring开发的应用的对象可以不依赖于Spring的API2) 依赖注入
    发表于 11-04 07:51

    MVC框架实例—Spring MVC配置

    本文旨在让您在使用Spring MVC框架配置完成日常工作的时候更加轻松。根据Spring MVC框架配置,为基于本技术开发的项目提供一系列
    发表于 12-14 17:37 3168次阅读

    Spring集成Acegi安全框架在J2EE的应用

    Acegi是一个基于Spring的安全框架探讨Spring框架集成Acegi的方法,即在Spring
    发表于 05-07 14:11 19次下载

    spring mvc框架介绍

    。使用 Spring 可插入的 MVC 架构,可以选择是使用内置的 Spring Web 框架还是 Struts 这样的 Web 框架。通过策略接口,
    发表于 11-17 16:28 2330次阅读
    <b class='flag-5'>spring</b> mvc<b class='flag-5'>框架</b>介绍

    spring框架定时器使用与配置

    Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式)轻量级开源框架
    发表于 01-26 17:11 1743次阅读

    Spring认证」Spring 框架概述

    Spring 框架是一个开源的 Java 平台。它最初由 Rod Johnson 编写,并于 2003 年 6 月在 Apache 2.0 许可下首次发布。 Spring Framework 的核心
    的头像 发表于 08-12 15:07 642次阅读
    「<b class='flag-5'>Spring</b>认证」<b class='flag-5'>Spring</b> <b class='flag-5'>框架</b>概述

    Spring依赖注入的方式

    Spring 是一个开源的轻量级框架,可以用于构建企业级应用程序。其最重要的特性之一是依赖注入(Dependency Injection,DI),这是一种设计模式,它可以帮助我们解耦代码、提高
    的头像 发表于 11-22 15:12 460次阅读

    Spring依赖注入的四种方式

    Spring框架,依赖注入是一种核心的概念和机制。通过依赖注入,我们可以让对象之间的依赖关系更加松散,并且能够方便地进行单元测试和模块化
    的头像 发表于 12-03 15:11 1893次阅读

    Spring Cloud Gateway网关框架

    Spring Cloud Gateway网关框架 本软件微服务架构采用Spring Cloud Gateway网关控制框架
    的头像 发表于 08-22 09:58 426次阅读
    <b class='flag-5'>Spring</b> Cloud Gateway网关<b class='flag-5'>框架</b>