原文链接地址:http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=1933350
最近在做项目,开发时是通过driver创建datasource的,配置如下
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${dataSource.driverClassName}" />
<property name="url" value="${dataSource.url}" />
<property name="username" value="${dataSource.username}" />
<property name="password" value="${dataSource.password}" />
</bean>
实施时是通过jndi查找得到datasource,配置如下:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${dataSource.jndiName}" />
</bean>
其中属性文件是通过propertyConfigurer导入的:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
dependency-check="none">
<property name="fileEncoding" value="UTF-8" />
<property name="locations">
<list>
<value>classpath:spring-app.properties</value>
</list>
</property>
</bean>
属性
文件的内容如下:
dataSource.jndiName=jdbc/myDataSource
dataSource.driverClassName=oracle.jdbc.driver.OracleDriver
dataSource.url=jdbc:oracle:thin:@localhost:1521:myServId
dataSource.username=myUser
dataSource.password=myPassword
采用上面这种方式,在每次部署的时候都要修改applicationContext.xml的dataSource配置,有点麻烦
通过学习 JndiObjectFactoryBean 的代码,自己写了一个数据源的工厂类:
package laochake.spring.datasource;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jndi.JndiLocatorSupport;
import org.springframework.util.StringUtils;
/**
* 数据源工厂bean,通过 jndi 属性判断是从jndi取得数据源还是用jdbc驱动创建数据源<br>
* 设计此类的目的是简化部署时的配置,即只同过设置定jndi的值就可以自动切换数据源的获取方式
* @author laochake
* @since 2007-12-13 下午01:26:46
*/
public class DataSourceFactoryBean implements FactoryBean,InitializingBean {
/**缓存数据源对象*/
private DataSource dataSource;
/**是否jndi数据源*/
private boolean jndi;
/**数据源的名字(如果是jndi数据源)*/
private String jndiName;
/**jdbc驱动类(非jndi的情况)*/
private String driverClassName;
/**数据库的url(非jndi的情况)*/
private String url;
/**用户名(非jndi的情况)*/
private String username;
/**密码(非jndi的情况)*/
private String password;
//TODO:此处省略了属性的set方法
/**
* 初始化
* @author laochake
* @since 2007-12-13 下午01:48:03
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception {
if(this.isJndi()){
if (!StringUtils.hasText(this.jndiName)) {
throw new IllegalArgumentException("jndiName is required");
}
}else{
if (!StringUtils.hasText(this.driverClassName)) {
throw new IllegalArgumentException("driverClassName is required");
}
if (!StringUtils.hasText(this.url)) {
throw new IllegalArgumentException("url is required");
}
if (!StringUtils.hasText(this.username)) {
throw new IllegalArgumentException("username is required");
}
if (!StringUtils.hasText(this.password)) {
throw new IllegalArgumentException("password is required");
}
}
//在初始化时就创建数据源
this.createDataSource();
}
/**
* 实现 FactoryBean 的方法,取得对象
* @author laochake
* @since 2007-12-13 下午01:33:35
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
public Object getObject() {
DataSource ds = this.createDataSource();
return ds;
}
/**
* 创建数据源对象,并保存到 this.dataSource属性
* @author laochake
* @since 2007-12-13 下午01:46:44
* @return
*/
protected DataSource createDataSource(){
DataSource ds = this.dataSource;
if(ds==null){
try{
if(this.isJndi()){
ds = new JndiDataSourceSupport().lookupDataSource(this.jndiName);
}else{
ds=new DriverManagerDataSource(driverClassName, url, username, password);
}
}catch(Throwable err){
throw new RuntimeException(err);
}
}
this.dataSource=ds;
return ds;
}
/**
* 实现 FactoryBean 的方法,取得工厂创建的对象类型
* @author laochake
* @since 2007-12-13 下午01:42:57
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
*/
public Class getObjectType() {
return javax.sql.DataSource.class;
}
/**
* 实现 FactoryBean 的方法,是否单例模式(始终返回true)
* @author laochake
* @since 2007-12-13 下午01:43:29
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
*/
public boolean isSingleton() {
return true;
}
/**
* jndi数据源查找类(内部私有类)
* @author laochake
* @since 2007-12-13 下午01:49:09
*/
private class JndiDataSourceSupport extends JndiLocatorSupport{
public DataSource lookupDataSource(String jndiName) throws NamingException{
return (DataSource)super.lookup(jndiName, javax.sql.DataSource.class);
}
}
}
使用以上定义类,新的dataSource定义方式如下:
<bean id="dataSource" class="com.gdcn.spring.datasource.DataSourceFactoryBean">
<description><![CDATA[ 数据源定义 ]]></description>
<property name="jndi" value="${dataSource.IS_JNDI}" />
<property name="jndiName" value="${dataSource.jndiName}" />
<property name="driverClassName" value="${dataSource.driverClassName}" />
<property name="url" value="${dataSource.url}" />
<property name="username" value="${dataSource.username}" />
<property name="password" value="${dataSource.password}" />
</bean>
修改后的属性
文件的内容如下:
dataSource.IS_JNDI=true
dataSource.jndiName=jdbc/myDataSource
dataSource.driverClassName=oracle.jdbc.driver.OracleDriver
dataSource.url=jdbc:oracle:thin:@localhost:1521:myServId
dataSource.username=myUser
dataSource.password=myPassword
在部署应用时,如果使用jdbc驱动创建数据源,则IS_JNDI=false 如果使用jndi查找得到数据源,则IS_JNDI=true。
可见第二种方式的配置简单了很多,只通过修改dataSource.IS_JNDI就能实现 datasource获取方式的切换。
本文介绍了一种通过配置属性实现Spring中DataSource从JDBC驱动到JNDI查找方式自动切换的方法,简化了部署过程。
980

被折叠的 条评论
为什么被折叠?



