SpEL表达式学习

注意:本文均采用JavaConfig的方式注入,而不是采用XML的方式进行配置。如果需要使用XML的方式注入,本文可以作为一个参考。

1. SpEL介绍

SpEL全称 Spring Expression Language(Spring表达式语言),是一种应用于Spring环境下的一种语言格式。
通常来说,我们往Spring环境中注入值,可以使用properties文件,也可以使用SpEL进行注入,效果是一样的。


2. 环境配置

本文采用的是Maven进行配置,以下是需要用到的pom文件

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.8.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.1.3.RELEASE</version>
</dependency>
<dependency>s
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.2</version>
</dependency>

3. Properties配置文件注入

在classpath目录下新建一个properties文件,命名为jdbc.properties

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.userName=root
jdbc.password=xxx
jdbc.url.prefix=jdbc.mysql://localhost:3306/
jdbc.url.suffix=?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true

新建一个普通组件(Component)类

@Component
@PropertySource(value = {"classpath:/jdbc.properties"})
public class DataBaseUtils {

	@Value("${jdbc.userName}")
	private String userName;
	@Value("${jdbc.password}")
	private String passWord;
    @Value("${jdbc.driverClass}")
	private String driverClass;
	@Value("${jdbc.url.prefix}")
	private String urlPrefix;
	@Value("${jdbc.url.suffix}")
	private String urlSuffix;

	private ComboPooledDataSource dataSource;

	@Bean
	public DataSource getDevDataSource(@Value("${jdbc.password}") String passWord) throws PropertyVetoException {
		System.out.println("来自dev环境");
		dataSource = new ComboPooledDataSource();
		dataSource.setJdbcUrl(urlPrefix + "java" + urlSuffix);
		dataSource.setUser(userName);
		dataSource.setPassword(passWord);
		dataSource.setDriverClass(driverClass);
		return dataSource;
	}
}

可以使用@Value注解进行参数的注入,@PropertySource注解的作用是定位配置文件。
语法格式:"${配置文件中描述的值}"。
因为可能引入多个配置文件,因此建议给配置文件中的属性进行全路径描述。

3.1 属性注入

@Value("${jdbc.url.prefix}")
private String urlPrefix;

3.2 方法参数注入

public DataSource getDevDataSource(@Value("${jdbc.password}") String passWord){}

3.3 使用EmbeddedValueResolverAware注入

需要实现EmbeddedValueResolverAware接口,接着实现setEmbeddedValueResolver方法,Spring容器会在装载Bean对象之前,往里面注入一个StringValueResolver对象

@Component
@PropertySource(value = {"classpath:/jdbc.properties"})
public class DataBaseUtils implements EmbeddedValueResolverAware {
    
    private String password;

    @Override
	public void setEmbeddedValueResolver(StringValueResolver resolver) {
		this.password = resolver.resolveStringValue("${jdbc.password}");
	}
}

3.4 使用EnvironmentAware注入

Spring容器会在装载Bean对象之前,往里面注入一个Environment对象,通过环境变量,我们可以非常强大的得到想要的结果

@Component
@PropertySource(value = {"classpath:/jdbc.properties"})
public class DataBaseUtils implements EnvironmentAware {
    private Environment environment;
    @Override
	public void setEnvironment(Environment environment) {
		this.environment = environment;
	}
}

Environment提供了以下四种获取配置文件中值的方式:

/**
* 获得配置文件中定义的值
*/
String getProperty(String key);
/**
* 获得配置文件中定义的值,没有则返回预设的默认值
*/
String getProperty(String key, String defaultValue);
/**
* 获得配置文件中定义的值,可以是一个Class类对象,也就是key可以为对象的全路径描述
*/
<T> T getProperty(String key, Class<T> targetType);
/**
* 获得配置文件中定义的值,可以是一个Class类对象,如果没有那么返回一个预设值
*/
<T> T getProperty(String key, Class<T> targetType, T defaultValue);

4. SpEL注入

语法格式:#{待解析的值},请记住,前面是#不是$

4.1 获得配置文件的值之属性注入

@Value(#{systemProperties['jdbc.driverClass']})
private String driverClass;

4.2 获得配置文件值之方法参数注入

public DataSource getDevDataSource(@Value(#{systemProperties['jdbc.passWord']}) String passWord){
	//方法主体省略
}

5. SpEL其他用法

5.1 常规用法

  • 获得浮点值:@Value("#{1.234}"),注:以后直接简略写成#{1.234}
  • 获得科学计数法值:#{1.234E5}
  • 获得String值:#{"Hello"}
  • 获得布尔值:#{false}
  • 获得已装配对象:#{DataBaseUtils}
  • 引用已装配对象的值#{DataBaseUtils.password}
  • 获得方法的返回值:#{DataBaseUtils.getDevDataSource()}
    • 对返回值进行操作:#{DataBaseUtils.getDevDataSource().getConnection()}
    • 判断返回值是否为空:#{DataBaseUtils.getDevDataSource()?.getConnection()},spring会检测传递的值是否为空,为空则不调用,直接返回null
  • 获得Java内置对象:T{java.lang.Math}
    • 获得属性:T{java.lang.Math}.PI
    • 调用方法:T{java.lang.Math}.random()

5.2 高级用法

  • 逻辑运算:连接符使用and,or,not
  • 复合运算:#{2 * T{java.lang.Math}.PI * circle.radius}
  • 连接运算:#{DataBaseUtils.urlPrefix + 'java' + DataBaseUtils.urlSuffix}
  • 比较运算:#{DataBaseUtils.userName == root}#{DataBaseUtils.userName eq root}
  • 三元运算:#{DataBaseUtils.userName == root ? "ok" : "no"}
  • 正则表达式:#{DataBaseUtils.password matches '[a-zA-Z0-9]{6,12}'}
  • 计算集合:#{songs[1]},得到songs里面的第二首歌曲
    • 得到属性:#{songs[1].title}
  • 计算字符串:#{'This is Hello'[3]},得到字符串中第4个字符
  • 查询运算符:#{songs.?[title eq 'hello']},得到歌曲中名字等于hello的歌曲
    • 匹配第一个:#{songs.^[title eq 'hello']}
    • 匹配最后一个:#{songs.$[title eq 'hello']}
  • 投影运算符:#{songs.![title]},将songs集合中的title取出来,放入对象中

猜你喜欢

转载自blog.csdn.net/qq_32409957/article/details/86325380