Spring提供两种运行时求值方式:
- 属性占位符
- Spring表达式语言(SpEL)
1、从Environment中检索属性并注入
例子:
@Configuration
@PropertySource("classpath:/com/soundsystem/app.properties")
public class ExpressiveConfig{
@Autowired
Environment env;
@Bean
public BlankDisc disc(){
return new BlankDisc(env.getProperty("disc.title"), env.getProperty(disc.artist"));
}
}
disc.title=xxxxx
disc.artist=xxxxx
2、关于Environment
getProperty()方法的四个重载形式:
- String getProperty(String key)
- String getProperty(String key, String defaultValue)
- T getProperty(String key, Class<T> type)
- T getProperty(String key, Class<T> type, T defaultValue)
Environment还提供了一些与属性相关的方法:
- getRequiredProperty() //当希望一个属性必须有定义时
- containsProperty() //检查某个属性是否存在
- getPropertyAsClass() //将属性解析为类
Environment还提供了检查哪些profile处于激活状态的方法:
- String[] getActiveProfiles() //返回激活profile名称的数组
- String[] getDefaultProfiles() //返回默认profile名称的数组
- boolean acceptsProfiles(String... profiles) //如果environment支持给定profile的话就返回true
3、属性占位符
例子:
<bean id="sgtPeppers" class="soundsystem.BlankDisc" c:_title="${disc.title}" c:_artist="${disc.artist}" />
public BlankDisc(@Value("${disc.title}") String title, @Value("${disc.artist}") String artist){
this.title = title;
this.artist = artist;
}
第二种是依赖于组件扫描和自动装配来创建和初始化应用组件时使用占位符的方式,其中@Value的用法和@Autowired十分相似。
为了使用占位符必须要配置一个PropertySourcesPlaceholderConfigurer bean,例子如下:
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer(){
return new PropertySourcesPlaceholderConfigurer();
}
如果想使用XML进行配置,则首先在XML顶部声明context命名空间,然后如下:
<context:property-placeholder />
4、使用Spring表达式语言进行装配
4.1、使用SpEL进行bean装配
SpEL特性:
- 使用bean的ID来引用bean
- 调用方法和访问对象的属性
- 对值进行算术、关系和逻辑运算
- 正则表达式匹配
- 集合操作
使用Spring表达式语言进行装配例子(依赖于组件扫描和自动装配的方式):
public BlankDisc(@Value("#{systemProperties['disc.title']") String title, @Value("#{systemProperties['disc.artist']}"){
this.title = title;
this.artist = artist;
}
在XML配置中,可以将SpEL表达式传入<property>或<constructor-arg>的value属性中,或将其作为p-命名空间或c-命名空间条目的值,例子如下:
<bean id="sgtPeppers" class="soundsystem.BlankDisc" c:_title="#{systemProperties['disc.title']}" c:_artist="#{systemProperties['disc.artist']}" />
4.2、SpEL所支持的基础表达式
表示字面值:
#{9.87E4}
#{'Hello'}
#{false}
引用bean、属性和方法:
#{sgtPeppers}
#{sgtPeppers.artist}
#{artistSelector.selectArtist()?.toUpperCase()}
其中第三个例子使用了"?"运算符,如果返回值为null的话,则不会执行toUpperCase(),直接返回null。
在表达式中使用类型:
T(java.lang.Math).PI
T(java.lang.Math).random()
T()运算符的结果会得到一个Class对象,其真正价值在于能够直接访问目标类型的静态方法和常量。
SpEL运算符:
例子:
#{2 * T{java.lang.Math).PI * circle.radius}
#{T(java.lang.Math).PI * cercle.radius ^ 2}
#{disc.title + 'by' + disc.artist}
#{counter.total == 100}
#{counter.total eq 100}
#{scoreboard.score > 1000 ? "Winner!" : "Loser"}
#{disc.title ?: 'Rattle and Hum'}
计算正则表达式:
#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-0.-]+//.com'}
计算集合:
#{jukebox.song[T(java.lang.Math).random() * jukebox.songs.size()].title}
#{'This is a test'[3]}
#{jukebox.songs.?[artist eq 'Aerosmith']}
#{jukebox.songs.^[artist eq 'Aerosmith']}
#{jukebox.songs.$[artist eq 'Aerosmith']}
#{jukebox.songs.![title]}
#{jukebox.songs.?[artist eq 'Aerosmith'].![title]}