首先我们来看看 Spring 参考文档的 11.2.6. 执行SQL语句 这里有个代码片断:
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
public class ExecuteAStatement {
private JdbcTemplate jt;
private DataSource dataSource;
public void doExecute() {
jt = new JdbcTemplate(dataSource);
jt.execute("create table mytable (id integer, name varchar(100))");
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
这个就是普通的 Java 类, 再参考 11.2.4. DataSource接口, 这里的另一个代码片断:
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername("sa");
dataSource.setPassword("");
当然上面的连接方式可以配置成我们课程里面介绍的 MyEclipse Derby 的数据库连接:
org.apache.derby.jdbc.ClientDriver
jdbc:derby://localhost:1527/myeclipse;create=true
app
app
我们可以写一个测试类来执行代码:
import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class TestTemplate {
public static void main(String[] args) {
// 新建一个数据源对象
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername("sa");
dataSource.setPassword("");
// 新建一个ExecuteAStatement 对象
ExecuteAStatement eas = new ExecuteAStatement();
// 给执行表达式的对象关联数据源(也就是常说的注入, 通过 JavaBean 的 setXxx 方法关联起来)
eas.setDataSource(dataSource);
// 执行功能代码
eas.doExecute();
}
}
这个代码可以跑通, 就是普通的编程方式, 大家可以去看刚才介绍的文档附近的详细说明。
那么如果用 Spring 来做, 代码会变成这样:
ExecuteAStatement 类代码保持不变, 多了个 beans.xml:
ExecuteAStatement 类代码保持不变, 多了个 beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="userDAO" class="ExecuteAStatement">
<property name="dataSource">
<ref bean="myDataSource" />
</property>
</bean>
<bean id="myDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>org.hsqldb.jdbcDriver</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 org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) throws IOException {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
ExecuteAStatement eas =(ExecuteAStatement)context.getBean("userDAO");
// 执行功能代码
eas.doExecute();
}
}
和上面的 TestTemplate 类相比, 就会发现 new DriverManagerDataSource() 这个过程不用我们写了, 运行的时候会发现一切都执行的好好的, 也就是常说的 ExecuteAStatement 的 dataSource 这个属性被注入了。
那么这个过程到底该如何理解呢? Spring 是一个对象池, 可以简化为一个 Map, 存多个主键和对象的映射。 那么 Spring 运行的过程中, 会根据 beans.xml 一步步进行必要的解析工作:
Map springEngine = new HashMap();
OK, 解析到了
<bean id="userDAO" class="ExecuteAStatement">, 发现 bean 定义, 那就新建一个实例存到对象池里吧, 主键就是 userDAO, 值就是对象:
ExecuteAStatement bean1 = new ExecuteAStatement();
springEngine.put("userDAO", bean1);
再往下执行, 发现 property 定义:
<property name="dataSource">
到了这里, 就知道应该调用 bean1.setDataSource(DataSource) 方法了。 可以接着执行, 发现
<ref bean="myDataSource" />, 哦, 这个方法的参数还没有呢, 是个 bean 的引用, 好了, 要调用这个方法, 还是先 new 一个名字为 myDataSource 的 bean2 吧。 就跳到下面寻找 myDataSource 的定义, 找到了:
<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>org.hsqldb.jdbcDriver</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 bean2 = new DriverManagerDataSource();
bean2.setDriverClassName("org.hsqldb.jdbcDriver");
bean2.setUrl("jdbc:hsqldb:hsql://localhost:");
bean2.setUsername("sa");
bean2.setPassword("");
不是还有个 bean 的 id 名字为 myDataSource 嘛, 那就把它存到对象池里面:
springEngine.put("myDataSource", bean2);
好了, 最后就是把他们两个关联起来了, 通过 ref 里指定的 bean id 名来关联起来:
// 省略类型转换的代码
springEngine.get("userDAO")。setDataSource(springEngine.get("myDataSource"));
最后返回给用户的就是一个对象池(一个 Map)了, 所以别人调用的时候, 就发现 springEngine.get("userDAO") 回来的类的 dataSource 属性已经被实例化过了, 这些都是 Spring 幕后工作的代码, 通过反射机制来实现。
所以最后写代码调用:
context.getBean("userDAO") 的时候, 得到的是 ExecuteAStatement, 这时候还有一个 myDataSource, 也可以被调用:
context.getBean("myDataSource"), 得到的是 DriverManagerDataSource.
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
public class ExecuteAStatement {
private JdbcTemplate jt;
private DataSource dataSource;
public void doExecute() {
jt = new JdbcTemplate(dataSource);
jt.execute("create table mytable (id integer, name varchar(100))");
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
这个就是普通的 Java 类, 再参考 11.2.4. DataSource接口, 这里的另一个代码片断:
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername("sa");
dataSource.setPassword("");
当然上面的连接方式可以配置成我们课程里面介绍的 MyEclipse Derby 的数据库连接:
org.apache.derby.jdbc.ClientDriver
jdbc:derby://localhost:1527/myeclipse;create=true
app
app
我们可以写一个测试类来执行代码:
import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class TestTemplate {
public static void main(String[] args) {
// 新建一个数据源对象
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername("sa");
dataSource.setPassword("");
// 新建一个ExecuteAStatement 对象
ExecuteAStatement eas = new ExecuteAStatement();
// 给执行表达式的对象关联数据源(也就是常说的注入, 通过 JavaBean 的 setXxx 方法关联起来)
eas.setDataSource(dataSource);
// 执行功能代码
eas.doExecute();
}
}
这个代码可以跑通, 就是普通的编程方式, 大家可以去看刚才介绍的文档附近的详细说明。
那么如果用 Spring 来做, 代码会变成这样:
ExecuteAStatement 类代码保持不变, 多了个 beans.xml:
ExecuteAStatement 类代码保持不变, 多了个 beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="userDAO" class="ExecuteAStatement">
<property name="dataSource">
<ref bean="myDataSource" />
</property>
</bean>
<bean id="myDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>org.hsqldb.jdbcDriver</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 org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) throws IOException {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
ExecuteAStatement eas =(ExecuteAStatement)context.getBean("userDAO");
// 执行功能代码
eas.doExecute();
}
}
和上面的 TestTemplate 类相比, 就会发现 new DriverManagerDataSource() 这个过程不用我们写了, 运行的时候会发现一切都执行的好好的, 也就是常说的 ExecuteAStatement 的 dataSource 这个属性被注入了。
那么这个过程到底该如何理解呢? Spring 是一个对象池, 可以简化为一个 Map, 存多个主键和对象的映射。 那么 Spring 运行的过程中, 会根据 beans.xml 一步步进行必要的解析工作:
Map springEngine = new HashMap();
OK, 解析到了
<bean id="userDAO" class="ExecuteAStatement">, 发现 bean 定义, 那就新建一个实例存到对象池里吧, 主键就是 userDAO, 值就是对象:
ExecuteAStatement bean1 = new ExecuteAStatement();
springEngine.put("userDAO", bean1);
再往下执行, 发现 property 定义:
<property name="dataSource">
到了这里, 就知道应该调用 bean1.setDataSource(DataSource) 方法了。 可以接着执行, 发现
<ref bean="myDataSource" />, 哦, 这个方法的参数还没有呢, 是个 bean 的引用, 好了, 要调用这个方法, 还是先 new 一个名字为 myDataSource 的 bean2 吧。 就跳到下面寻找 myDataSource 的定义, 找到了:
<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>org.hsqldb.jdbcDriver</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 bean2 = new DriverManagerDataSource();
bean2.setDriverClassName("org.hsqldb.jdbcDriver");
bean2.setUrl("jdbc:hsqldb:hsql://localhost:");
bean2.setUsername("sa");
bean2.setPassword("");
不是还有个 bean 的 id 名字为 myDataSource 嘛, 那就把它存到对象池里面:
springEngine.put("myDataSource", bean2);
好了, 最后就是把他们两个关联起来了, 通过 ref 里指定的 bean id 名来关联起来:
// 省略类型转换的代码
springEngine.get("userDAO")。setDataSource(springEngine.get("myDataSource"));
最后返回给用户的就是一个对象池(一个 Map)了, 所以别人调用的时候, 就发现 springEngine.get("userDAO") 回来的类的 dataSource 属性已经被实例化过了, 这些都是 Spring 幕后工作的代码, 通过反射机制来实现。
所以最后写代码调用:
context.getBean("userDAO") 的时候, 得到的是 ExecuteAStatement, 这时候还有一个 myDataSource, 也可以被调用:
context.getBean("myDataSource"), 得到的是 DriverManagerDataSource.