首先我们来看看 Spring 参考文档的 执行SQL语句 这里有个代码片断
import javaxsqlDataSource; import orgsprireJdbcTemplate; public class ExecuteAStatement { private JdbcTemplate jt; private DataSource dataSource; public void doExecute() { jt = new JdbcTemplate(dataSource); jtexecute(create table mytable (id integer name varchar())); } public void setDataSource(DataSource dataSource) { thisdataSource = dataSource; } }
这个就是普通的 Java 类 再参考 DataSource接口 这里的另一个代码片断
DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSourcesetDriverClassName(orghsqldbjdbcDriver);dataSourcesetUrl(jdbc:hsqldb:hsql://localhost:);dataSourcesetUsername(sa);dataSourcesetPassword();
当然上面的连接方式可以配置成我们课程里面介绍的 MyEclipse Derby 的数据库连接
orgapachederbyjdbcClientDriverjdbc:derby://localhost:/myeclipse;create=trueappapp
我们可以写一个测试类来执行代码
import orgspringframeworkjdbcdatasourceDriverManagerDataSource;public class TestTemplate { public static void main(String[] args) { // 新建一个数据源对象 DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSourcesetDriverClassName(orghsqldbjdbcDriver); dataSourcesetUrl(jdbc:hsqldb:hsql://localhost:); dataSourcesetUsername(sa); dataSourcesetPassword(); // 新建一个ExecuteAStatement 对象 ExecuteAStatement eas = new ExecuteAStatement(); // 给执行表达式的对象关联数据源(也就是常说的注入 通过 JavaBean 的 setXxx 方法关联起来) eassetDataSource(dataSource); // 执行功能代码 easdoExecute(); }}
这个代码可以跑通 就是普通的编程方式 大家可以去看刚才介绍的文档附近的详细说明
那么如果用 Spring 来做 代码会变成这样
ExecuteAStatement 类代码保持不变 多了个 beansxml
ExecuteAStatement 类代码保持不变 多了个 beansxml:
<?xml version= encoding=UTF?>
<beans
xmlns=
xmlns:xsi=instance
xsi:schemaLocation= beansxsd>
<bean id=userDAO class=ExecuteAStatement>
<property name=dataSource>
<ref bean=myDataSource />
</property>
</bean>
<bean id=myDataSource
class=orgspringframeworkjdbcdatasourceDriverManagerDataSource>
<property name=driverClassName>
<value>orghsqldbjdbcDriver</value>
</property>
<property name=url>
<value>jdbc:hsqldb:hsql://localhost:</value>
</property>
<property name=username>
<value>sa</value>
</property>
<property name=password>
<value></value>
</property>
</bean>
</beans>
测试类
import orgntextApplicationContext;import orgntextsupportClassPathXmlApplicationContext;public class Test { public static void main(String[] args) throws IOException { ApplicationContext context = new ClassPathXmlApplicationContext(beansxml); ExecuteAStatement eas =(ExecuteAStatement)contextgetBean(userDAO); // 执行功能代码 easdoExecute(); }}
和上面的 TestTemplate 类相比 就会发现 new DriverManagerDataSource() 这个过程不用我们写了 运行的时候会发现一切都执行的好好的 也就是常说的 ExecuteAStatement 的 dataSource 这个属性被注入了
那么这个过程到底该如何理解呢? Spring 是一个对象池 可以简化为一个 Map 存多个主键和对象的映射 那么 Spring 运行的过程中 会根据 beansxml 一步步进行必要的解析工作
Map springEngine = new HashMap()
OK 解析到了
<bean id=userDAO class=ExecuteAStatement> 发现 bean 定义 那就新建一个实例存到对象池里吧 主键就是 userDAO 值就是对象
ExecuteAStatement bean = new ExecuteAStatement()
springEngineput(userDAO bean)
再往下执行 发现 property 定义
<property name=dataSource>
到了这里 就知道应该调用 beansetDataSource(DataSource) 方法了 可以接着执行 发现
<ref bean=myDataSource /> 哦 这个方法的参数还没有呢 是个 bean 的引用 好了 要调用这个方法 还是先 new 一个名字为 myDataSource 的 bean 吧 就跳到下面寻找 myDataSource 的定义 找到了
<bean id=myDataSource
class=orgspringframeworkjdbcdatasourceDriverManagerDataSource>
<property name=driverClassName>
<value>orghsqldbjdbcDriver</value>
</property>
<property name=url>
<value>jdbc:hsqldb:hsql://localhost:</value>
</property>
<property name=username>
<value>sa</value>
</property>
<property name=password>
<value></value>
</property>
</bean>
像以前一样 先实例化这个类 然后看到 property 表情就调用对应的 setXxx() 这样的方法 相当于下面一段代码
// 新建一个数据源对象 DriverManagerDataSource bean = new DriverManagerDataSource(); beansetDriverClassName(orghsqldbjdbcDriver); beansetUrl(jdbc:hsqldb:hsql://localhost:); beansetUsername(sa); beansetPassword();
不是还有个 bean 的 id 名字为 myDataSource 嘛 那就把它存到对象池里面
springEngineput(myDataSource bean)
好了 最后就是把他们两个关联起来了 通过 ref 里指定的 bean id 名来关联起来
// 省略类型转换的代码
springEngineget(userDAO)setDataSource(springEngineget(myDataSource))
最后返回给用户的就是一个对象池(一个 Map)了 所以别人调用的时候 就发现 springEngineget(userDAO) 回来的类的 dataSource 属性已经被实例化过了 这些都是 Spring 幕后工作的代码 通过反射机制来实现
所以最后写代码调用
contextgetBean(userDAO) 的时候 得到的是 ExecuteAStatement 这时候还有一个 myDataSource 也可以被调用
contextgetBean(myDataSource) 得到的是 DriverManagerDataSource