说明:本文摘自优快云的一位网友的博客。
最近在做项目,开发时是通过driver创建datasource的,配置如下
- <beanid="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
- <propertyname="driverClassName"value="${dataSource.driverClassName}"/>
- <propertyname="url"value="${dataSource.url}"/>
- <propertyname="username"value="${dataSource.username}"/>
- <propertyname="password"value="${dataSource.password}"/>
- </bean>
实施时是通过jndi查找得到datasource,配置如下:
- <beanid="dataSource"class="org.springframework.jndi.JndiObjectFactoryBean">
- <propertyname="jndiName"value="${dataSource.jndiName}"/>
- </bean>
其中属性文件是通过propertyConfigurer导入的:
- <beanid="propertyConfigurer"
- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
- dependency-check="none">
- <propertyname="fileEncoding"value="UTF-8"/>
- <propertyname="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
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 DataSourceFactoryBeanimplements 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 JndiDataSourceSupportextends JndiLocatorSupport{
- public DataSource lookupDataSource(String jndiName)throws NamingException{
- return (DataSource)super.lookup(jndiName, javax.sql.DataSource.class);
- }
- }
- }
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定义方式如下:
- <beanid="dataSource"class="com.gdcn.spring.datasource.DataSourceFactoryBean">
- <description><![CDATA[ 数据源定义 ]]></description>
- <propertyname="jndi"value="${dataSource.IS_JNDI}"/>
- <propertyname="jndiName"value="${dataSource.jndiName}"/>
- <propertyname="driverClassName"value="${dataSource.driverClassName}"/>
- <propertyname="url"value="${dataSource.url}"/>
- <propertyname="username"value="${dataSource.username}"/>
- <propertyname="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
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获取方式的切换。
本文详细介绍了如何优化数据源配置,通过引入工厂类来简化部署时的数据源获取方式。从传统的XML配置转向使用JNDI查找或直接使用JDBC驱动创建数据源,实现灵活的配置切换。通过引入自定义工厂类,只需通过修改属性文件中的一个开关参数即可轻松切换数据源获取策略,提高了部署效率。
375

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



