Spring4.0学习6--使用外部属性文件和SpEL

使用外部属性文件

在配置文件里配置 Bean 时, 有时需要在 Bean 的配置里混入系统部署的细节信息(例如: 文件路径, 数据源配置信息等). 而这些部署细节实际上需要和 Bean 配置相分离
Spring 提供了一个 PropertyPlaceholderConfigurer 的 BeanFactory 后置处理器, 这个处理器允许用户将 Bean 配置的部分内容外移到属性文件中. 可以在 Bean 配置文件里使用形式为 ${var} 的变量, PropertyPlaceholderConfigurer 从属性文件里加载属性, 并使用这些属性来替换变量.
Spring 还允许在属性文件中使用 ${propName},以实现属性之间的相互引用。

连数据库示例,本地要有数据库且开启。
新建个包,com.liudehua,新建个Main.java:

1
2
3
4
5
6
7
public class Main {
public static void main(String[] args) throws SQLException {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-properties.xml");
DataSource dataSource = (DataSource)ctx.getBean("dataSource");
System.out.println(dataSource.getConnection());
}
}

新建个beans-properties.xml配置文件:

1
2
3
4
5
6
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///test"></property>
</bean>

注意:这里我又踩坑了。后台报异常Connections could not be acquired from the underlying database!,遂百度,得知可能是以下几点造成的:

  • 1.驱动配置有误:driver=com.mysql.jdbc.Driver
  • 2.数据库连接地址有误
  • 3.密码或帐号有误
  • 4.数据库未启动或无权访问
  • 5.项目未引入对应的驱动jar包mysql-connector-java-5.1.6-bin.jarc3p0-0.9.1.2.jar
  • 6.mysql root没有远程访问的权限,需要增加权限,增加权限的步骤如下:进入mysql数据库:grant all privileges on . to ‘root’@’%’ identified by ‘root’ with grant option;flush privileges;
    后来,我想可能是我参数写错了,仔细找,发现确实拼错了,改之启动还是一样的错,然后看看第4点,嗯,我电脑上没有数据库。。。

没数据库没关系,可以装,后面的接着学。
部署数据库连接的基本信息最好是拿出来,放到一个属性文件里面。
src下新建一个属性文件,db.properties:

1
2
3
4
user=root
password=123456
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql:///test

注意:本地mysql必须有一个名为test的数据库

接下来引用该属性文件。
修改beans-properties.xml代码:

1
2
3
4
5
6
7
8
9
<!-- 导入属性文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 使用外部化属性文件的属性 -->
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
<property name="driverClass" value="${driverClass}"></property>
<property name="jdbcUrl" value="${jdbcUrl}"></property>
</bean>

Spring表达式语言:SpEL

Spring 表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言。
语法类似于 EL:SpEL 使用 #{…} 作为定界符,所有在大框号中的字符都将被认为是 SpEL
SpEL 为 bean 的属性进行动态赋值提供了便利
通过 SpEL 可以实现:

  • 通过 bean 的 id 对 bean 进行引用
  • 调用方法以及引用对象中的属性
  • 计算表达式的值
  • 正则表达式的匹配

字面量的表示:

  • 整数:<property name="count" value="#{5}"/>
  • 小数:<property name="frequency" value="#{89.7}"/>
  • 科学计数法:<property name="capacity" value="#{1e4}"/>
  • String可以使用单引号或者双引号作为字符串的定界符号:<property name=“name” value="#{'Chuck'}"/><property name='name' value='#{"Chuck"}'/>
  • Boolean:<property name="enabled" value="#{false}"/>

引用 Bean、属性和方法
1.引用其他对象:

1
2
<!-- 通过value属性和SpEL配置bean之间的关系 -->
<property name="prefix" value="#{prefixGenerator}"></property>

2.引用其他对象的属性:

1
2
<!-- 通过value属性和SpEL配置suffix属性值为另一个bean的suffix的属性值 -->
<property name="suffix" value="#{sequenceGenerator2.suffix}"></property>

3.调用其他方法,还可以链式操作:

1
2
3
4
<!-- 通过value属性和SpEL配置suffix属性值为另一个bean的方法的返回值 -->
<property name="suffix" value="#{sequenceGenerator2.toString}"></property>
<!-- 方法的连缀 -->
<property name="suffix" value="#{sequenceGenerator2.toString.toUpperCase()}" />

4.调用静态方法或静态属性:通过 T() 调用一个类的静态方法,它将返回一个 Class Object,然后再调用相应的方法或属性:

1
<property name="initValue" value="#{T(java.lang.Math).PI}" />

SpEL支持的运算符号
1.算数运算符:+, -, *, /, %, ^:

1
2
3
4
5
6
<property name="adjustedAmount" value="#{counter.total + 2}" />
<property name="adjustedAmount" value="#{counter.total - 2}" />
<property name="circumference" value="#{2 * T(java.lang.Math).PI * circle.radius}" />
<property name="average" value="#{counter.total / counter.count}" />
<property name="remainder" value="#{counter.total % counter.count}" />
<property name="area" value="#{T(java.lang.Math).PI * circle.radius ^ 2}" />

2.加号还可以用作字符串连接:

1
<constructor-arg value="#{performer.firstname + ' ' + performer.lastname}"/>

3.比较运算符: <, >, ==, <=, >=, lt, gt, eq, le, ge

1
<property name="equal" value="#{counter.total == 100}" />

4.逻辑运算符号: and, or, not, |

1
2
3
<property name="largeCircle" value="#{shape.kind == 'circle' and shape.perimeter gt 10000}" />
<property name="outOfStock" value="#{!product.available}" />
<property name="outOfStock" value="#{not product.available}" />

5.if-else 运算符:?: (ternary), ?: (Elvis)

1
<constructor-arg value="#{songSelector.selectSong()=='Jingle Bells' ? 'pinao':'Jingle Bells'}" />

6.if-else 的变体

1
<constructor-arg value="#{kenny.song ?:'Greensleeves'}" />

7.正则表达式:matches

1
<constructor-arg value="#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}'}" />

Newer Post

Spring4.0学习7--IOC 容器中 Bean 的生命周期方法 和 创建 Bean 后置处理器

IOC 容器中 Bean 的生命周期方法 Spring IOC 容器可以管理 Bean 的生命周期, Spring 允许在 Bean 生命周期的特定点执行定制的任务.Spring IOC 容器对 Bean 的生命周期进行管理的过程: 通过构造器或工厂方法创建 Bean 实例 为 Bean 的属性设 …

继续阅读
Older Post

Spring4.0学习5--bean之间的关系以及bean的作用域

继承 Spring 允许继承 bean 的配置, 被继承的 bean 称为父 bean. 继承这个父 Bean 的 Bean 称为子 Bean子 Bean 从父 Bean 中继承配置, 包括 Bean 的属性配置子 Bean 也可以覆盖从父 Bean 继承过来的配置父 Bean 可以作为配置模板, …

继续阅读