首先我们来看看 Spring 参考文档的 11.2.6. 执行SQL语句 这里有个代码片段:
/ D6 w S. T/ O& @ import javax.sql.DataSource;import org.springframework.jdbc.core.JdbcTemplate;public class ExecuteAStatement public void setDataSource }1 X1 i0 O7 x9 k# X9 ]
这个就是通俗的 Java 类, 再参考 11.2.4. DataSource接口, 这里的另一个代码片段:
; f3 G) y U: J1 T3 H; _ DriverManagerDataSource dataSource = new DriverManagerDataSource;dataSource.setDriverClassName;dataSource.setUrl;dataSource.setUsername;dataSource.setPassword;. U$ J1 }& V" I' |. g
当然膳缦沔的毗连体例可以设置装备摆设成我们课程琅缦沔介绍的 MyEclipse Derby 的数据库毗连:
* @/ ^1 p: j' T' ^ org.apache.derby.jdbc.ClientDriverjdbc:derby://localhost:1527/myeclipse;create=trueappapp. O5 e$ N0 W# b$ X6 ~$ c& o
我们可以写一个测试类来执行代码:4 g2 y1 y3 } p8 T# b4 V2 b0 C
import org.springframework.jdbc.datasource.DriverManagerDataSource;public class TestTemplate }( X; B5 {1 y1 e1 c G& w% k- y
这个代码可以跑通, 就是通俗的编程体例, 巨匠可以去看适才介绍的文档四周的具体声名。
/ U9 b4 H* K9 v' Y 那么假如用 Spring 来做, 代码会酿成这样:" ?9 N% ~- i$ D2 j5 V! x/ y
ExecuteAStatement 类代码连结不变, 多了个 beans.xml:
/ }; S9 ?$ o. N ExecuteAStatement 类代码连结不变, 多了个 beans.xml:/ ~9 g% m$ a, F. c
?xml version="1.0" encoding="UTF-8"?/ d- U; {# u4 [
beans
C9 j; h) B; S$ M xmlns="http://www.springframework.org/schema/beans"! c* `7 w+ T( O- ?0 C" O4 i$ g+ ]- c
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/ K9 g# ]( I% }- i8 ^: w4 @. J7 `
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd", {0 p2 M% [1 |, [
bean id="userDAO"
+ ~) x+ ~5 ?- @" w; I# ~# B/ _ property name="dataSource"- R6 `/ _( z3 d) \
ref bean="myDataSource" /
* Q, J( C* ~- j; B) [3 m: M /property# b' ^9 w) Y. p# {: [
/bean7 h' \; P$ u! Y2 g7 ]& y
bean id="myDataSource"
1 h2 o( R7 j3 u& u; T* V property name="driverClassName"
" S" ~" S4 y4 W1 T7 h" Q2 }) D valueorg.hsqldb.jdbcDriver/value
1 A" w3 Q5 w4 g1 T2 x! a% _/ J /property0 d5 N( D! c! H |9 c9 d
property name="url"
8 e7 Q6 B0 E2 P) l3 P valuejdbc:hsqldb:hsql://localhost:/value
1 Q2 \0 L2 S' J( Y; [* v) Z: m /property
9 V' M+ P* D, x property name="username"
o& O+ e; J% n valuesa/value
) q4 }( y; c* P* Z /property1 o' F+ Q) i/ \% I( [2 w5 w# Q: @% c
property name="password"3 ?+ q0 _5 y$ b0 Y- L! z
value/value
. p* @( k) v- W" N( B3 e /property
$ h6 h0 l+ Y1 R3 p! m" U /bean i- H1 U6 P) j# N% X) ~4 \3 ~
/beans
! b/ m8 n# S3 `% O5 t8 ^# J0 c 测试类:
, t$ v, m- _" e import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test } y" ]2 R. m# X2 N& b2 m
和膳缦沔的 TestTemplate 类对比, 就会发现 new DriverManagerDataSource() 这个过程不用我们写了, 运行的时辰会发现一切都执行的好好的, 也就是常说的 ExecuteAStatement 的 dataSource 这个属性被注入了。2 m5 }9 @& [! ?' i
那么这个过程到底该若何理解呢? Spring 是一个对象池, 可以简化为一个 Map, 存多个主键和对象的映射。 那么 Spring 运行的过程中, 会按照 beans.xml 一步步进行需要的解析工作:% {* Q b& Z0 @6 n
Map springEngine = new HashMap();
+ c9 y: _' C( M3 L( B OK, 解析到了
8 E3 {. _" s0 Q0 ? bean id="userDAO" , 发现 bean 界说, 那就新建一个实例存到对象池里吧, 主键就是 userDAO, 值就是对象:
8 X5 |: X3 ^8 d1 ] k; o ExecuteAStatement bean1 = new ExecuteAStatement();
h) |7 y# k$ H/ q springEngine.put("userDAO", bean1); V$ r( T y1 g( k/ | Z
再往下执行, 发现 property 界说:5 v, J* k- E9 R h
property name="dataSource"
/ }$ u& S/ e! k& v 到了这里, 就知道应该挪用 bean1.setDataSource(DataSource) 体例了。 可以接着执行, 发现: B% f* H6 z7 E8 h6 q
ref bean="myDataSource" /, 哦, 这个体例的参数还没有呢, 是个 bean 的引用, 好了, 要挪用这个体例, 仍是先 new 一个名字为 myDataSource 的 bean2 吧。 就跳到下面寻找 myDataSource 的界说, 找到了:5 |* {# l/ |" ^; B4 a
bean id="myDataSource"property name="driverClassName"valueorg.hsqldb.jdbcDriver/value/propertyproperty name="url"valuejdbc:hsqldb:hsql://localhost:/value/propertyproperty name="username"valuesa/value/propertyproperty name="password"value/value/property /bean1 f# i* L1 {' [ b" t, q& ?, ^1 K
像以前一样, 先实例化这个类, 然后看到 property 神色就挪用对应的 setXxx() 这样的体例, 相当于下面一段代码:
/ p5 O) b) o% x) l" C8 U" t // 新建一个数据源对象DriverManagerDataSource bean2 = new DriverManagerDataSource;bean2.setDriverClassName;bean2.setUrl;bean2.setUsername;bean2.setPassword;
$ E* C7 ^/ x: E# o: ^3 ? 不是还有个 bean 的 id 名字为 myDataSource 嘛, 那就把它存到对象池琅缦沔:
) }9 Z* O$ Q/ D2 b springEngine.put("myDataSource", bean2);
2 h, G% s1 p/ @9 S8 c' x 好了, 最后就是把他们两个联系关系起来了, 经由过程 ref 里指定的 bean id 名来联系关系起来:
: n! t5 W7 D! G& `: V // 省略类型转换的代码9 a' u1 `* G4 ?' [2 K0 z
springEngine.get("userDAO")。setDataSource(springEngine.get("myDataSource"));
6 ~/ G/ Q. ]4 o% Z& O; y 最后返回给用户的就是一个对象池(一个 Map)了, 所以别人挪用的时辰, 就发现 springEngine.get("userDAO") 回来的类的 dataSource 属性已经被实例化过了, 这些都是 Spring 幕后工作的代码, 经由过程反射机制来实现。
7 d4 E: }9 j/ K. r b' S, S( | 所以最后写代码挪用:( a6 s! U: J/ l9 S4 C8 [. s
context.getBean("userDAO") 的时辰, 获得的是 ExecuteAStatement, 这时辰还有一个 myDataSource, 也可以被挪用:
5 H |7 c4 b# T context.getBean("myDataSource"), 获得的是 DriverManagerDataSource. |