Spring學習筆記(
1
)----簡單的實例
---------------------------------
首先須要準備Spring包,可從官方網站上下載。
下載解壓後,必須的兩個包是spring.jar和commons-logging.jar。此外爲了便於測試加入了JUnit包。
在Myeclipse中建立Java項目。
編寫一個接口類,爲了簡單,只加入了一個方法。
Java代碼
1
.
package
com.szy.spring.interfacebean;
2
.
3
.
public
interface
PersonBean
4
.{
5
.
void
show();
6
.}
而後寫一個類實現這個接口。
Java代碼
1
.
package
com.szy.spring.implbean;
2
.
import
com.szy.spring.interfacebean.PersonBean;
3
.
4
.
public
class
UserBean
implements
PersonBean
5
.{
6
.
7
.
public
void
show()
8
. {
9
. System.out.println(
"Hello Kuka"
);
10
. }
11
.
12
.}
以上的過程咱們再熟悉不過了,下面開始加入Spring的內容了。首先從下載的Sping包中找到配置文件,刪除不須要的,找到最原始的部分:
Xml代碼
1
.<?xml version=
"1.0"
encoding=
"UTF-8"
?>
2
.<beans xmlns=
"http://www.springframework.org/schema/beans"
3
. xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
4
. xmlns:context=
"http://www.springframework.org/schema/context"
5
. xmlns:tx=
"http://www.springframework.org/schema/tx"
6
. xsi:schemaLocation="http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7
. http:
//www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
8
. http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
9
.
10
.</beans>
咱們在配置文件中加入咱們的bean信息
Xml代碼
1
.<bean id=
"userBean"
class
=
"com.szy.spring.implbean.UserBean"
/>
其中id做爲標識符,
class
爲類的包路徑。
這樣咱們的配置文件就寫好了,完整的配置文件呢以下。
Xml代碼
1
.<?xml version=
"1.0"
encoding=
"UTF-8"
?>
2
.<beans xmlns=
"http://www.springframework.org/schema/beans"
3
. xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
4
. xmlns:context=
"http://www.springframework.org/schema/context"
5
. xmlns:tx=
"http://www.springframework.org/schema/tx"
6
. xsi:schemaLocation="http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7
. http:
//www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
8
. http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
9
.
10
. <bean id=
"userBean"
class
=
"com.szy.spring.implbean.UserBean"
/>
11
.</beans>
最後咱們建立一個測試類測試:
Java代碼
1
.
package
com.szy.spring.test;
2
.
3
.
import
org.junit.Test;
4
.
import
org.springframework.context.ApplicationContext;
5
.
import
org.springframework.context.support.ClassPathXmlApplicationContext;
6
.
import
com.szy.spring.interfacebean.PersonBean;
7
.
8
.
9
.
public
class
TestClass
10
.{
11
.
@Test
12
.
public
void
testMethod()
throws
Exception
13
. {
14
.
//讀取配置文件
15
. ApplicationContext ctx=
new
ClassPathXmlApplicationContext(
"applicationContext.xml"
);
16
.
//獲取UserBean的實例
17
. PersonBean bean=(PersonBean)ctx.getBean(
"userBean"
);
18
.
//調用方法
19
. bean.show();
20
. }
21
.}
運行,輸入以下結果:
結果代碼
1
.Hello Kuka
Ok,咱們的第一個Spring程序成功運行。
Sping學習筆記(
2
)----實例化Bean的三種方式
-------------------------------------------
Spring的實例化Bean有三種方式:
使用類構造器直接實例化
使用靜態工廠的方法實例化
使用實例工廠方法實例化
三種方式對應的配置以下
Xml代碼
1
.<?xml version=
"1.0"
encoding=
"UTF-8"
?>
2
.<beans xmlns=
"http://www.springframework.org/schema/beans"
3
. xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
4
. xmlns:context=
"http://www.springframework.org/schema/context"
5
. xmlns:tx=
"http://www.springframework.org/schema/tx"
6
. xsi:schemaLocation="http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7
. http:
//www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
8
. http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
9
. <!-- 使用類構造器直接實例化 -->
10
. <bean id=
"userBean1"
class
=
"com.szy.spring.implbean.UserBean"
/>
11
. <!-- 使用靜態工廠的方法實例化 -->
12
. <bean id=
"userBean2"
class
=
"com.szy.spring.factory.BeanFactory"
factory-method=
"UserBeanService"
/>
13
. <!-- 使用實例工廠方法實例化 -->
14
. <bean id=
"factory"
class
=
"com.szy.spring.factory.BeanFactory"
/>
15
. <bean id=
"userBean3"
factory-bean=
"factory"
factory-method=
"getUserBeanService"
/>
16
.</beans>
其中BeanFactory類的代碼以下
Java代碼
1
.
package
com.szy.spring.factory;
2
.
3
.
import
com.szy.spring.implbean.UserBean;
4
.
import
com.szy.spring.interfacebean.PersonBean;
5
.
6
.
public
class
BeanFactory
7
.{
8
.
//使用靜態工廠的方法實例化使用
9
.
public
static
PersonBean UserBeanService()
10
. {
11
.
return
new
UserBean();
12
. }
13
.
14
.
public
PersonBean getUserBeanService()
15
. {
16
.
return
new
UserBean();
17
. }
18
.}
在這三種方式中咱們最經常使用的仍是第一種。
Spring學習筆記(
3
)----編碼剖析Spring管理Bean的原理
--------------------------------------------------
Xml代碼
1
.<?xml version=
"1.0"
encoding=
"UTF-8"
?>
2
.<beans xmlns=
"http://www.springframework.org/schema/beans"
3
. xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
4
. xmlns:context=
"http://www.springframework.org/schema/context"
5
. xmlns:tx=
"http://www.springframework.org/schema/tx"
6
. xsi:schemaLocation="http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7
. http:
//www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
8
. http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
9
. <bean id=
"userBean"
class
=
"com.szy.spring.implbean.UserBean"
/>
10
.</beans>
Spring的配置文件中記錄了類的包路徑,所以咱們首先是要讀入配置文件。在配置文件中Bean有id和
class
兩個屬性,咱們首先定義一個Bean類,包含這兩個屬性:
Java代碼
1
.
package
com.szy.spring.implbean;
2
.
3
.
public
class
Bean
4
.{
5
.
private
String id;
6
.
private
String className;
7
.
public
String getId()
8
. {
9
.
return
id;
10
. }
11
.
public
void
setId(String id)
12
. {
13
.
this
.id = id;
14
. }
15
.
public
String getClassName()
16
. {
17
.
return
className;
18
. }
19
.
public
void
setClassName(String className)
20
. {
21
.
this
.className = className;
22
. }
23
.
24
.}
25
.
因爲配置文件是xml文件,在這裏使用Jdom包操做xml文件,讀入配置文件中的Bean信息。
Java代碼
1
.
/**
2. * 讀取xml配置文件
3. * @param fileName 配置文件名
4. */
5
.
private
void
readXML(String fileName)
6
. {
7
.
// 尋找配置文件
8
. URL xmlPath =
this
.getClass().getClassLoader().getResource(fileName);
9
. Document doc =
null
;
10
. Element root =
null
;
11
.
try
12
. {
13
. SAXBuilder sb =
new
SAXBuilder(
false
);
14
. doc = sb.build(
new
FileInputStream(
new
File(xmlPath.toURI())));
15
.
// 設置命名空間
16
. Namespace xhtml = Namespace.getNamespace(
"xhtml"
,
17
.
"http://www.springframework.org/schema/beans"
);
18
. root = doc.getRootElement();
// 獲取根元素
19
. List<Element> list = root.getChildren(
"bean"
, xhtml);
//獲取所有bean節點
20
.
for
(Element element : list)
// 遍歷節點,取得每一個節點的屬性
21
. {
22
. String id = element.getAttributeValue(
"id"
);
23
. String className = element.getAttributeValue(
"class"
);
24
. Bean bean =
new
Bean();
25
. bean.setId(id);
26
. bean.setClassName(className);
27
. beanList.add(bean);
28
. }
29
. }
catch
(Exception e)
30
. {
31
. e.printStackTrace();
32
. }
33
.
34
. }
其中beanList是一個List對象,由於在配置文件中存在不少Bean。
獲得了全部的Bean對象後,下面就實例化每一個Bean對象,結果存放在Map對象中。
Java代碼
1
.
/**
2. * bean的實例化
3. */
4
.
private
void
instanceBeans()
5
. {
6
.
for
(Bean bean : beanList)
7
. {
8
.
try
9
. {
10
.
if
(bean.getClassName() !=
null
&& !
""
.equals(bean.getClassName().trim()))
11
. beanObject.put(bean.getId(), Class.forName(bean.getClassName()).newInstance());
12
. }
catch
(Exception e)
13
. {
14
. e.printStackTrace();
15
. }
16
. }
17
.
18
. }
其中beanObject爲Map對象。
最後再加入一個方法,方便外部能獲取Map中的對象
Java代碼
1
.
/**
2. * 獲取bean實例
3. * @param beanName 配置文件中bean的Id
4. * @return
5. */
6
.
public
Object getBean(String beanName)
7
. {
8
.
return
this
.beanObject.get(beanName);
9
. }
完整的MyClassPathXMLApplicationContext見附件中的代碼。
下面測試MyClassPathXMLApplicationContext類。
Java代碼
1
.
@Test
2
.
public
void
testMethod()
throws
Exception
3
. {
4
.
//讀取配置文件
5
. MyClassPathXMLApplicationContext ctx=
new
MyClassPathXMLApplicationContext(
"applicationContext.xml"
);
6
.
//獲取UserBean的實例
7
. PersonBean bean=(PersonBean)ctx.getBean(
"userBean"
);
8
.
//調用方法
9
. bean.show();
10
. }
輸出結果
結果代碼
1
.Hello Kuka
成功。
上面僅是簡單的演示了Spring管理Bean的原理,可是在實際操做中還須要考慮很對其它因素。
Spring學習筆記(
4
)----Bean節點信息配置
---------------------------------------
默認狀況下,Spring的Ioc容器啓動時會初始化bean,可是咱們能夠指定Bean節點的lazy-init=
"true"
,來延遲初始化bean。這時候,只有第一次獲取bean纔會初始化bean。如
Xml代碼
1
.<bean id=
"userBean"
class
=
"com.szy.spring.implbean.UserBean"
lazy-init=
"true"
/>
若是想對全部的bean有應用延遲初始化,能夠在跟節點beans設置
default
-lazy-init=
"true"
,以下:
Xml代碼
1
.<beans
default
-lazy-init=
"true"
....>
此外,若是咱們還想UserBean在實例化是調用初始化方法時,咱們能夠加入「init-method=
"init"
」屬性,其中init爲Userbean中的init()方法,與之對應,「destroy-method=
"destroy"
」爲銷燬屬性。
在Spring中咱們經過getBean(name)方法得到實例,那麼咱們每次獲取的實例化對象是一個仍是多個呢?
咱們能夠經過「==」進行測試
Java代碼
1
.ApplicationContext ctx=
new
ClassPathXmlApplicationContext(
"applicationContext.xml"
);
2
.PersonBean bean1=(PersonBean)ctx.getBean(
"userBean"
);
3
.PersonBean bean2=(PersonBean)ctx.getBean(
"userBean"
);
4
.System.out.println(bean1==bean2);
運行輸出結果爲:
true
這說明了Bean交給sping容器管理以後,Bean默認狀況下是單實例的。
若是咱們想每次經過getBean(name)方法得到實例是一個新的實例化對象該怎麼辦呢?
在配置文件中節點bean有一個屬性scope,只要咱們配置以下便可:
Xml代碼
1
.<bean id=
"userBean"
class
=
"com.szy.spring.implbean.UserBean"
scope=
"prototype"
/>
在運行測試代碼,輸出結果爲:
false
Spring學習筆記(
5
)----依賴注入的簡單實現
-----------------------------------------
Spring的核心機制是依賴注入。依賴注入讓bean與bean之間以配置文件組織在一塊兒,而不是以硬編碼的方式耦合在一塊兒。依賴注入(Dependency Injection)和控制反轉(Inversion of Control)是同一個概念。具體含義是:當某個角色(多是一個Java實例,調用者)須要另外一個角色(另外一個Java實例,被調用者)的協助時,在傳統的程序設計過程當中,一般由調用者來建立被調用者的實例。但在Spring裏,建立被調用者的工做再也不由調用者來完成,所以稱爲控制反轉;建立被調用者實例的工做一般由Spring容器來完成,而後注入調用者,所以也稱爲依賴注入。管是依賴注入,仍是控制反轉,都說明Spring採用動態、靈活的方式來管理各類對象。對象與對象之間的具體實現互相透明。
下面經過簡單的實例演示依賴注入。
項目中主要包含一下一個文件:
UserDAO是一個接口,包含了一個方法:
Java代碼
1
.
package
com.szy.spring.dao;
2
.
3
.
public
interface
UserDAO
4
.{
5
.
void
show();
6
.}
而UserDAO4MySqlImpl和UserDAO4OracleImpl實現了UserDAO中的方法。
Java代碼
1
.
package
com.szy.spring.dao;
2
.
public
class
UserDAO4MySqlImpl
implements
UserDAO
3
.{
4
.
public
void
show()
5
. {
6
. System.out.println(
"MySqlDAO Implement"
);
7
. }
8
.}
Java代碼
1
.
package
com.szy.spring.dao;
2
.
public
class
UserDAO4OracleImpl
implements
UserDAO
3
.{
4
.
public
void
show()
5
. {
6
. System.out.println(
"OracleDAO Implement"
);
7
. }
8
.}
UserService是另一個包中的接口,
Java代碼
1
.
package
com.szy.spring.service;
2
.
3
.
public
interface
UserService
4
.{
5
.
void
show();
6
.}
UserServiceImpl實現了這個接口,
Java代碼
1
.
package
com.szy.spring.service;
2
.
3
.
import
com.szy.spring.dao.UserDAO;
4
.
5
.
public
class
UserServiceImpl
implements
UserService
6
.{
7
.
private
UserDAO userDAO;
8
.
9
.
public
void
show()
10
. {
11
. userDAO.show();
12
. }
13
.
14
.
public
UserDAO getUserDAO()
15
. {
16
.
return
userDAO;
17
. }
18
.
public
void
setUserDAO(UserDAO userDAO)
19
. {
20
.
this
.userDAO = userDAO;
21
. }
22
.}
可是在實現這個接口中,調用了UserDAO中的方法。通常狀況下咱們須要在這裏實例化一個UserDAO對象,好比
Java代碼
1
.UserDAO userDAO=
new
UserDAO4MySqlImpl();
這樣的話耦合度就比較高,經過spring咱們能夠下降耦合度。
在Sping的配置文件中,咱們須要這樣配置
Java代碼
1
.<?xml version=
"1.0"
encoding=
"UTF-8"
?>
2
.<beans xmlns=
"http://www.springframework.org/schema/beans"
3
. xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
4
. xmlns:context=
"http://www.springframework.org/schema/context"
5
. xmlns:tx=
"http://www.springframework.org/schema/tx"
6
. xsi:schemaLocation="http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7
. http:
//www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
8
. http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
9
. <bean id=
"mySqlDAO"
class
=
"com.szy.spring.dao.UserDAO4MySqlImpl"
/>
10
. <bean id=
"oracleDAO"
class
=
"com.szy.spring.dao.UserDAO4OracleImpl"
/>
11
. <bean id=
"userService"
class
=
"com.szy.spring.service.UserServiceImpl"
>
12
. <!--構造方法注入
13
. <property name=
"userDAO"
ref=
"mySqlDAO"
></property>
14
. -->
15
. <property name=
"userDAO"
ref=
"oracleDAO"
></property>
16
. </bean>
17
.</beans>
下面咱們測試
Java代碼
1
.ApplicationContext ctx=
new
ClassPathXmlApplicationContext(
"applicationContext.xml"
);
2
. UserService service=(UserService)ctx.getBean(
"userService"
);
3
. service.show();
輸入內容爲
輸出代碼
1
.OracleDAO Implement
若是咱們想實用Mysql數據庫呢?
此時咱們只要修改配置文件便可,而不須要修改Java文件。
Xml代碼
1
.<property name=
"userDAO"
ref=
"mySqlDAO"
></property>
Spring學習筆記(
6
)----編碼剖析Spring依賴注入的原理
---------------------------------------------------
在Spring學習筆記(
3
)中剖析了Spring管理Bean的原理,下面解釋下Spring依賴注入的原理
在進行依賴注入時,咱們的配置文件以下配置:
Xml代碼
1
.<?xml version=
"1.0"
encoding=
"UTF-8"
?>
2
.<beans xmlns=
"http://www.springframework.org/schema/beans"
3
. xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
4
. xmlns:context=
"http://www.springframework.org/schema/context"
5
. xmlns:tx=
"http://www.springframework.org/schema/tx"
6
. xsi:schemaLocation="http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7
. http:
//www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
8
. http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
9
. <bean id=
"mySqlDAO"
class
=
"com.szy.spring.dao.UserDAO4MySqlImpl"
/>
10
. <bean id=
"oracleDAO"
class
=
"com.szy.spring.dao.UserDAO4OracleImpl"
/>
11
. <bean id=
"userService"
class
=
"com.szy.spring.service.UserServiceImpl"
>
12
. <!--構造方法注入
13
. <property name=
"userDAO"
ref=
"mySqlDAO"
></property>
14
. -->
15
. <property name=
"userDAO"
ref=
"oracleDAO"
></property>
16
. </bean>
17
.</beans>
根據配置文件信息,咱們首先須要創建一個Bean類,用來保存bean節點的信息:
Java代碼
1
.
package
com.szy.spring.bean;
2
.
3
.
import
java.util.List;
4
.
5
.
public
class
Bean
6
.{
7
.
private
String id;
8
.
private
String className;
9
.
private
List<Property> propertyList;
10
.
public
Bean(String id, String className, List<Property> propertyList)
11
. {
12
.
super
();
13
.
this
.id = id;
14
.
this
.className = className;
15
.
this
.propertyList = propertyList;
16
. }
17
.
public
String getId()
18
. {
19
.
return
id;
20
. }
21
.
public
void
setId(String id)
22
. {
23
.
this
.id = id;
24
. }
25
.
public
String getClassName()
26
. {
27
.
return
className;
28
. }
29
.
public
void
setClassName(String className)
30
. {
31
.
this
.className = className;
32
. }
33
.
public
List<Property> getPropertyList()
34
. {
35
.
return
propertyList;
36
. }
37
.
public
void
setPropertyList(List<Property> propertyList)
38
. {
39
.
this
.propertyList = propertyList;
40
. }
41
.}
此外,因爲bean下存在property信息,所以咱們還須要創建property類
Java代碼
1
.
package
com.szy.spring.bean;
2
.
3
.
public
class
Property
4
.{
5
.
private
String name;
6
.
private
String ref;
7
.
8
.
public
Property(String name, String ref)
9
. {
10
.
super
();
11
.
this
.name = name;
12
.
this
.ref = ref;
13
. }
14
.
public
String getName()
15
. {
16
.
return
name;
17
. }
18
.
public
void
setName(String name)
19
. {
20
.
this
.name = name;
21
. }
22
.
public
String getRef()
23
. {
24
.
return
ref;
25
. }
26
.
public
void
setRef(String ref)
27
. {
28
.
this
.ref = ref;
29
. }
30
.
31
.}
在Spring學習筆記(
3
)中,咱們在讀取xml文件時bean節點下面是不存在property節點的,所以在這裏咱們須要修改readXML()方法:
Java代碼
1
.
/**
2. * 讀取xml配置文件
3. * @param fileName 配置文件名
4. */
5
.
private
void
readXML(String fileName)
6
. {
7
.
// 尋找配置文件
8
. URL xmlPath =
this
.getClass().getClassLoader().getResource(fileName);
9
. Document doc =
null
;
10
. Element root =
null
;
11
.
try
12
. {
13
. SAXBuilder sb =
new
SAXBuilder(
false
);
14
. doc = sb.build(
new
FileInputStream(
new
File(xmlPath.toURI())));
15
.
// 設置命名空間
16
. Namespace xhtml = Namespace.getNamespace(
"xhtml"
,
17
.
"http://www.springframework.org/schema/beans"
);
18
. root = doc.getRootElement();
// 獲取根元素
19
. List<Element> bList = root.getChildren(
"bean"
, xhtml);
//獲取所有bean節點
20
.
for
(Element beanElement : bList)
// 遍歷節點,取得每一個節點的屬性
21
. {
22
. String id = beanElement.getAttributeValue(
"id"
);
23
. String className = beanElement.getAttributeValue(
"class"
);
24
.
//得到每一個bean下面的屬性
25
. List<Element> pList = beanElement
26
. .getChildren(
"property"
, xhtml);
27
. List<Property> propertyList =
new
ArrayList<Property>();
//存儲屬性信息
28
.
if
(pList.size() >
0
)
//若是存在屬性
29
. {
30
.
for
(Element propertyElement : pList)
//遍歷屬性節點
31
. {
32
. String name = propertyElement.getAttributeValue(
"name"
);
33
. String ref = propertyElement.getAttributeValue(
"ref"
);
34
. Property property =
new
Property(name, ref);
35
. propertyList.add(property);
//保存屬性節點
36
. }
37
. }
38
. Bean bean =
new
Bean(id, className, propertyList);
39
. beanList.add(bean);
40
. }
41
.
42
. }
catch
(Exception e)
43
. {
44
. e.printStackTrace();
45
. }
46
. }
讀取完配置文件後咱們仍是須要對bean進行實例化的,這方法和Spring學習筆記(
3
)中的instanceBeans()方法同樣。下面就是咱們須要給bean屬性進行注入,實現方法以下:
Java代碼
1
.
/**
2. * 爲bean對象的屬性注入值
3. */
4
.
public
void
injectObject()
5
. {
6
.
for
(Bean bean : beanList)
7
. {
8
. Object object = beanObject.get(bean.getId());
//獲取bean的實例
9
.
if
(object !=
null
)
10
. {
11
.
try
12
. {
13
. PropertyDescriptor[] ps = Introspector.getBeanInfo(
14
. object.getClass()).getPropertyDescriptors();
//取得bean的屬性描述
15
.
for
(Property property : bean.getPropertyList())
//獲取bean節點的屬性
16
. {
17
.
for
(PropertyDescriptor properdesc : ps)
18
. {
19
.
if
(property.getName().equals(properdesc.getName()))
20
. {
21
. Method setter = properdesc.getWriteMethod();
//獲取屬性的setter方法 ,private
22
.
if
(setter !=
null
)
23
. {
24
. Object value = beanObject.get(property.getRef());
//取得值
25
. setter.setAccessible(
true
);
//設置爲容許訪問
26
. setter.invoke(object, value);
//把引用對象注入到屬性
27
. }
28
.
break
;
29
. }
30
. }
31
. }
32
. }
catch
(Exception e)
33
. {
34
. e.printStackTrace();
35
. }
36
. }
37
. }
咱們進行測試:
Java代碼
1
.MyClassPathXMLApplicationContext ctx=
new
MyClassPathXMLApplicationContext(
"applicationContext.xml"
);
2
. UserService service=(UserService)ctx.getBean(
"userService"
);
3
. service.show();
運行輸出
結果代碼
1
.OracleDAO Implement
上面僅是簡單的演示了Spring依賴注入的原理,可是Spring學習筆記(
7
)----裝配各類集合類型的屬性在實際操做中還須要考慮很對其它因素,在此就不進行討論了。
Spring學習筆記(
7
)----裝配各類集合類型的屬性
---------------------------------------------
前面已經介紹瞭如何給屬性注入對象,下面介紹一下如何裝配集合類型的屬性
1
.Set類型
Java代碼
1
.
private
Set<String> sets=
new
HashSet<String>();
2
.
//咱們須要給它添加set方法
3
.
public
Set<String> getSets()
4
. {
5
.
return
sets;
6
. }
7
.
public
void
setSets(Set<String> sets)
8
. {
9
.
this
.sets = sets;
10
. }
11
.
public
Set<String> showSet()
12
. {
13
.
return
sets;
14
. }
而後根據屬性修改配置文件
Xml代碼
1
.<bean id=
"userService"
class
=
"com.szy.spring.service.UserServiceImpl"
>
2
. <property name=
"sets"
>
3
. <set>
4
. <value>Set1</value>
5
. <value>Set2</value>
6
. <value>Set3</value>
7
. </set>
8
. </property>
9
.
10
.</bean>
與之前不一樣的是咱們在property下面添加了<set></set>
這樣就能裝配set類型的屬性
2
.List類型
List類型的屬性和Set類型的方法同樣,主要是把配置文件中的set修改爲list。
Java代碼
1
.
private
List<String> lists=
new
ArrayList<String>();
2
.
public
List<String> getLists()
3
. {
4
.
return
lists;
5
. }
6
.
public
void
setLists(List<String> lists)
7
. {
8
.
this
.lists = lists;
9
. }
10
.
public
List<String> showList()
11
. {
12
.
return
lists;
13
. }
配置文件修改以下
Xml代碼
1
.<bean id=
"userService"
class
=
"com.szy.spring.service.UserServiceImpl"
>
2
.<property name=
"lists"
>
3
. <list>
4
. <value>List1</value>
5
. <value>List2</value>
6
. <value>List3</value>
7
. </list>
8
. </property>
9
. </bean>
3
.Properties類型
Java代碼
1
.
private
Properties properties=
new
Properties();
2
.
public
void
setProperties(Properties properties)
3
. {
4
.
this
.properties = properties;
5
. }
6
.
public
Properties getProperties()
7
. {
8
.
return
properties;
9
. }
10
.
public
Properties showProperties()
11
. {
12
.
return
properties;
13
. }
配置文件須要以下配置
Xml代碼
1
.<bean id=
"userService"
class
=
"com.szy.spring.service.UserServiceImpl"
>
2
.<property name=
"properties"
>
3
. <props>
4
. <prop key=
"key1"
>Properties1</prop>
5
. <prop key=
"key2"
>Properties2</prop>
6
. <prop key=
"key3"
>Properties3</prop>
7
. </props>
8
. </property>
9
. </bean>
10
.
4
.Map類型
Java代碼
1
.
private
Map<String, String> maps=
new
HashMap<String, String>();
2
.
public
List<String> getLists()
3
. {
4
.
return
lists;
5
. }
6
.
public
void
setLists(List<String> lists)
7
. {
8
.
this
.lists = lists;
9
. }
10
.
public
Map<String, String> showMaps()
11
. {
12
.
return
maps;
13
. }
配置文件作相應的配置
Xml代碼
1
.<bean id=
"userService"
class
=
"com.szy.spring.service.UserServiceImpl"
>
2
.lt;property name=
"maps"
>
3
. <map>
4
. <entry key=
"key1"
value=
"Map1"
></entry>
5
. <entry key=
"key2"
value=
"Map2"
></entry>
6
. <entry key=
"key3"
value=
"Map3"
></entry>
7
. </map>
8
. </property>
9
.</bean>
這樣就完成了對Map類型的屬性進行裝配。
Spring學習筆記(
8
)----屬性注入的方式
--------------------------------------
Spring中屬性注入的方式有三種:
1
.使用屬性setter方法注入
2
.使用構造器注入
3
.使用註解方式注入
使用屬性setter方法注入
使用屬性setter方法注入就是給屬性添加set()方法,在前面都是使用這種方法。
Java代碼
1
.
package
com.szy.spring.service;
2
.
3
.
import
com.szy.spring.dao.PersonDao;
4
.
5
.
public
class
UserServiceImplBySetter
implements
UserService
6
.{
7
.
private
PersonDao personDao;
8
.
9
.
public
void
show()
10
. {
11
. personDao.show();
12
. }
13
.
public
PersonDao getPersonDao()
14
. {
15
.
return
personDao;
16
. }
17
.
public
void
setPersonDao(PersonDao personDao)
18
. {
19
.
this
.personDao = personDao;
20
. }
21
.}
而後在配置文件中以下配置
Xml代碼
1
.<bean id=
"personDao"
class
=
"com.szy.spring.dao.PersonDaoBean"
/>
2
. <!-- 使用屬性Setter方法注入配置 -->
3
. <bean id=
"userService1"
class
=
"com.szy.spring.service.UserServiceImplBySetter"
>
4
. <property name=
"personDao"
ref=
"personDao"
></property>
5
. </bean>
使用構造器注入
使用構造器注入就是在類中添加含參構造函數
Java代碼
1
.
package
com.szy.spring.service;
2
.
3
.
import
com.szy.spring.dao.PersonDao;
4
.
5
.
public
class
UserServiceImplConstructor
implements
UserService
6
.{
7
.
private
PersonDao personDao;
8
.
private
String name;
9
.
10
.
public
UserServiceImplConstructor()
11
. {
12
. }
13
.
14
.
public
UserServiceImplConstructor(PersonDao personDao, String name)
15
. {
16
.
this
.personDao = personDao;
17
.
this
.name = name;
18
. }
19
.
20
.
public
void
show()
21
. {
22
. personDao.show();
23
. System.out.println(
"name屬性:"
+name);
24
. }
25
.}
下面就是在配置文件中添加配置信息,給每一個參數注入值
Xml代碼
1
.<bean id=
"personDao"
class
=
"com.szy.spring.dao.PersonDaoBean"
/>
2
. <!-- 使用構造器參數方法注入配置 -->
3
. <bean id=
"userService2"
class
=
"com.szy.spring.service.UserServiceImplConstructor"
>
4
. <constructor-arg index=
"0"
type=
"com.szy.spring.dao.PersonDao"
ref=
"personDao"
/>
5
. <constructor-arg index=
"1"
value=
"Kuka"
/>
6
. </bean>
注意:constructor-arg index是從
0
開始的
使用註解方式注入
若是使用前面的兩種方法,配置文件將會顯得很臃腫,所以咱們可使用註解的方式注入,使用註解方式注入有兩種方法,第一種使用javax.annotation.Resource中提供的註解方式方法以下:
Java代碼
1
.
package
com.szy.spring.service;
2
.
3
.
import
javax.annotation.Resource;
4
.
5
.
import
com.szy.spring.dao.PersonDao;
6
.
7
.
public
class
UserServiceImplByAnnotation4Resource
implements
UserService
8
.{
9
.
//@Resource默認是按照名稱裝配,找不到與名稱匹配的bean時按類型裝配
10
.
@Resource
(name=
"personDao"
)
private
PersonDao personDao;
11
.
12
.
public
void
show()
13
. {
14
. personDao.show();
15
. }
16
.
// 下面方法一樣能夠
17
.
// @Resource
18
.
// public void setPersonDao(PersonDao personDao)
19
.
// {
20
.
// this.personDao = personDao;
21
.
// }
22
.
23
.}
此時配置文件要作相應的改變
Xml代碼
1
.<?xml version=
"1.0"
encoding=
"UTF-8"
?>
2
.<beans xmlns=
"http://www.springframework.org/schema/beans"
3
. xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
4
. xmlns:context=
"http://www.springframework.org/schema/context"
5
. xmlns:tx=
"http://www.springframework.org/schema/tx"
6
. xsi:schemaLocation="http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7
. http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
8
. http:
//www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
9
. <context:annotation-config/>
10
. <bean id=
"personDao"
class
=
"com.szy.spring.dao.PersonDaoBean"
/>
11
. <bean id=
"userService"
class
=
"com.szy.spring.service.UserServiceImplByAnnotation4Autowired"
>
12
. </bean>
13
.</beans>
注意添加這句配置信息
<context:annotation-config/>
第二中方式就是使用spring提供的註解方式
org.springframework.beans.factory.annotation.Autowired;
注入使用時須要導入spring目錄lib\j2ee\common-annotations.jar這個包
使用方法以下:
Java代碼
1
.
package
com.szy.spring.service;
2
.
3
.
import
org.springframework.beans.factory.annotation.Autowired;
4
.
import
org.springframework.beans.factory.annotation.Qualifier;
5
.
6
.
import
com.szy.spring.dao.PersonDao;
7
.
8
.
public
class
UserServiceImplByAnnotation4Autowired
implements
UserService
9
.{
10
.
//@Autowired默認使用類型進行裝配,
11
.
@Autowired
private
PersonDao personDao;
12
.
// 若是使用按名稱進行裝配,則須要以下
13
.
// @Autowired @Qualifier("personDao")private PersonDao personDao;
14
.
public
void
show()
15
. {
16
. personDao.show();
17
. }
18
.
19
.}
配置文件和上面同樣。
在使用時建議使用
@Resource
,由於
@Resource
不依賴於spring框架。
Spring學習筆記(
9
)----讓Spring自動掃描和管理Bean
-------------------------------------------------
Java代碼
1
.
package
com.szy.spring.service;
2
.
3
.
import
org.springframework.stereotype.Service;
4
.
5
.
import
com.szy.spring.dao.PersonDao;
6
.
@Service
(
"service"
)
7
.
public
class
UserServiceImpl
implements
UserService
8
.{
9
.
private
PersonDao personDaoBean;
10
.
11
.
public
void
show()
12
. {
13
. personDaoBean.show();
14
. }
15
.
16
.
public
void
setPersonDaoBean(PersonDao personDaoBean)
17
. {
18
.
this
.personDaoBean = personDaoBean;
19
. }
20
.}
在前面的例子中,都是使用XML的bean定義來使用組件,在大的項目中,一般會有上百個組件,若是這些組件採用xml的bean定義來配置,顯然會使配置文件顯得很臃腫,查找和維護起來不方便。Spring2.
5
爲咱們引入了組件自動掃描機制,它能夠在類路徑下尋找標記了
@Component
、
@Service
、
@Controller
、
@Repository
註解的類,並把這些類歸入到spring容器中管理,它的做用和在xml中使用bean節點配置組件同樣。要使用自動掃描機制,咱們須要把配置文件以下配置:
Xml代碼
1
.<?xml version=
"1.0"
encoding=
"UTF-8"
?>
2
.<beans xmlns=
"http://www.springframework.org/schema/beans"
3
. xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
4
. xmlns:context=
"http://www.springframework.org/schema/context"
5
. xmlns:tx=
"http://www.springframework.org/schema/tx"
6
. xsi:schemaLocation="http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7
. http:
//www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
8
. http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
9
. <context:component-scan base-
package
=
"com.szy.spring"
></context:component-scan>
10
.</beans>
其中base-
package
爲須要掃描的包(包括子包)
@Service
用於標註業務層的組件,
@Controller
用於標註控制層組件(如struts中的action),
@Repository
用於標註數據訪問組件,即DAO組件,而
@Component
泛指組件,當組件很差歸類的時候,咱們可使用這個註解進行標註。可是在目前的spring版本中,這幾個註解的做用是同樣的,可是在之後可能會進行區分。
下面把先前的例子修改一下:
首先是PersonDaoBean類,修改以下
Java代碼
1
.
package
com.szy.spring.dao;
2
.
3
.
import
org.springframework.stereotype.Repository;
4
.
5
.
@Repository
6
.
//告訴spring這個類要交給spring管理,
7
.
public
class
PersonDaoBean
implements
PersonDao
8
.{
9
.
public
void
show()
10
. {
11
. System.out.println(
"執行PersonDaoBean中的add()方法"
);
12
. }
13
.}
而後是UserServiceImpl類
Java代碼
1
.
package
com.szy.spring.service;
2
.
3
.
import
org.springframework.stereotype.Service;
4
.
5
.
import
com.szy.spring.dao.PersonDao;
6
.
@Service
7
.
//把這個類交給spring管理,做爲服務了。
8
.
public
class
UserServiceImpl
implements
UserService
9
.{
10
.
private
PersonDao personDaoBean;
11
.
12
.
public
void
show()
13
. {
14
. personDaoBean.show();
15
. }
16
.
17
.
public
void
setPersonDaoBean(PersonDao personDaoBean)
18
. {
19
.
this
.personDaoBean = personDaoBean;
20
. }
21
.
22
.
public
PersonDao getPersonDaoBean()
23
. {
24
.
return
personDaoBean;
25
. }
26
.}
下面咱們進行測試,原來的測試代碼是userServiceImpl
Java代碼
1
.ApplicationContext ctx=
new
ClassPathXmlApplicationContext(
"applicationContext.xml"
);
2
. UserService service=(UserService)ctx.getBean(
"userService"
);
3
. service.show();
其中userService是咱們在配置文件中配置的bean的id。可是現在咱們並無id這個屬性,在spring2.
5
中,默認的id是類的名稱,可是開後是小寫,也就是userServiceImpl,所以測試代碼應修改以下:
Java代碼
1
.AbstractApplicationContext ctx=
new
ClassPathXmlApplicationContext(
"applicationContext.xml"
);
2
. UserService service=(UserService)ctx.getBean(
"userServiceImpl"
);
3
. System.out.println(service);
若是咱們想本身命名的話,則只需在註解後加上括號,裏面寫入你但願的名字,如
@Service
(
"userService"
)。
在spring中默認的是之生成一個bean實例,若是咱們想每次調用都產生一個實例,則標註需以下配置
@Service
@Scope
(
"prototype"
)
在xml中咱們還能夠配置初始化方法和銷燬方法,使用標註後只需以下標註
Java代碼
1
.
@PostConstruct
2
.
public
void
init()
3
. {
4
. System.out.println(
"初始化"
);
5
. }
6
.
@PreDestroy
7
.
public
void
destory()
8
. {
9
. System.out.println(
"銷燬"
);
10
. }
使用註解後,咱們的xml文件變得十分簡單,所以建議Spring學習筆記(
10
)----公共屬性的注入配置你們在之後的開發中使用註解。
Spring學習筆記(
10
)----公共屬性的注入配置
-------------------------------------------
假設咱們定義了四個bean類,其代碼分別以下:
Java代碼
1
.
package
com.szy.spring.bean;
2
.
3
.
public
class
Bean1 {
4
.
private
Bean2 bean2;
5
.
private
Bean3 bean3;
6
.
private
Bean4 bean4;
7
.
8
.
public
Bean2 getBean2()
9
. {
10
.
return
bean2;
11
. }
12
.
public
void
setBean2(Bean2 bean2)
13
. {
14
.
this
.bean2 = bean2;
15
. }
16
.
public
Bean3 getBean3()
17
. {
18
.
return
bean3;
19
. }
20
.
public
void
setBean3(Bean3 bean3)
21
. {
22
.
this
.bean3 = bean3;
23
. }
24
.
public
Bean4 getBean4()
25
. {
26
.
return
bean4;
27
. }
28
.
public
void
setBean4(Bean4 bean4)
29
. {
30
.
this
.bean4 = bean4;
31
. }
32
.}
Java代碼
1
.
package
com.szy.spring.bean;
2
.
3
.
public
class
Bean2
4
.{
5
.
private
int
id;
6
.
private
String name;
7
.
private
String password;
8
.
9
.
public
int
getId()
10
. {
11
.
return
id;
12
. }
13
.
public
void
setId(
int
id)
14
. {
15
.
this
.id = id;
16
. }
17
.
public
String getName()
18
. {
19
.
return
name;
20
. }
21
.
public
void
setName(String name)
22
. {
23
.
this
.name = name;
24
. }
25
.
public
String getPassword()
26
. {
27
.
return
password;
28
. }
29
.
public
void
setPassword(String password)
30
. {
31
.
this
.password = password;
32
. }
33
.}
Java代碼
1
.
package
com.szy.spring.bean;
2
.
3
.
public
class
Bean3
4
.{
5
.
private
int
id;
6
.
private
String name;
7
.
8
.
public
int
getId()
9
. {
10
.
return
id;
11
. }
12
.
public
void
setId(
int
id)
13
. {
14
.
this
.id = id;
15
. }
16
.
public
String getName()
17
. {
18
.
return
name;
19
. }
20
.
public
void
setName(String name)
21
. {
22
.
this
.name = name;
23
. }
24
.}
Java代碼
1
.
package
com.szy.spring.bean;
2
.
3
.
public
class
Bean4
4
.{
5
.
private
int
age;
6
.
7
.
public
int
getAge()
8
. {
9
.
return
age;
10
. }
11
.
public
void
setAge(
int
age)
12
. {
13
.
this
.age = age;
14
. }
15
.}
按照正常的思路,咱們下面就要給每一個類進行屬性的注入,配置文件以下設置:
Xml代碼
1
.<?xml version=
"1.0"
encoding=
"UTF-8"
?>
2
.<beans xmlns=
"http://www.springframework.org/schema/beans"
3
. xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
4
. xmlns:context=
"http://www.springframework.org/schema/context"
5
. xmlns:tx=
"http://www.springframework.org/schema/tx"
6
. xsi:schemaLocation="http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7
. http:
//www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
8
. http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
9
. <bean id=
"bean1"
class
=
"com.szy.spring.bean.Bean1"
>
10
. <property name=
"bean2"
ref=
"bean2"
/>
11
. <property name=
"bean3"
>
12
. <ref bean=
"bean3"
/>
13
. </property>
14
. <property name=
"bean4"
ref=
"bean4"
/>
15
. </bean>
16
.
17
. <bean id=
"bean2"
class
=
"com.szy.spring.bean.Bean2"
>
18
. <property name=
"id"
value=
"100"
/>
19
. <property name=
"name"
>
20
. <value>kuka</value>
21
. </property>
22
. <property name=
"password"
value=
"123"
/>
23
. </bean>
24
.
25
. <bean id=
"bean3"
class
=
"com.szy.spring.bean.Bean3"
>
26
. <property name=
"id"
value=
"100"
/>
27
. <property name=
"name"
value=
"kuka"
/>
28
. </bean>
29
.
30
. <bean id=
"bean4"
class
=
"com.szy.spring.bean.Bean4"
>
31
. <property name=
"age"
value=
"22"
/>
32
. </bean>
33
.</beans>
咱們進行測試:
Java代碼
1
.
@Test
2
.
public
void
testMethod()
throws
Exception
3
. {
4
. ApplicationContext ctx=
new
ClassPathXmlApplicationContext(
"applicationContext.xml"
);
5
. Bean1 bean1 = (Bean1)ctx.getBean(
"bean1"
);
6
.
7
. System.out.println(
"bean1.bean2.id="
+ bean1.getBean2().getId());
8
. System.out.println(
"bean1.bean2.name="
+ bean1.getBean2().getName());
9
. System.out.println(
"bean1.bean2.password="
+ bean1.getBean2().getPassword());
10
. System.out.println(
"bean1.bean3.id="
+ bean1.getBean3().getId());
11
. System.out.println(
"bean1.bean3.name="
+ bean1.getBean3().getName());
12
. System.out.println(
"bean1.bean4.age="
+ bean1.getBean4().getAge());
13
. }
正常輸出咱們所預期的信息,可是咱們觀察發現bean2和bean3的部分屬性的配置信息是相同的,這僅是兩個bean,若是是多個bean的話咱們要修改就好修改多處,所以咱們能夠把這些公共的部分提出出來,進行抽象。這個在Spring中是支持的。咱們在創建一個配置文件,命名爲:applicationCommon.xml,其內容以下配置
Xml代碼
1
.<?xml version=
"1.0"
encoding=
"UTF-8"
?>
2
.<beans xmlns=
"http://www.springframework.org/schema/beans"
3
. xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
4
. xmlns:context=
"http://www.springframework.org/schema/context"
5
. xmlns:tx=
"http://www.springframework.org/schema/tx"
6
. xsi:schemaLocation="http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7
. http:
//www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
8
. http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
9
. <bean id=
"beanAbstract"
abstract
=
"true"
>
10
. <property name=
"id"
value=
"100"
/>
11
. <property name=
"name"
value=
"kuka"
/>
12
. </bean>
13
.
14
. <bean id=
"bean2"
class
=
"com.szy.spring.bean.Bean2"
parent=
"beanAbstract"
>
15
. <property name=
"password"
value=
"123"
/>
16
. </bean>
17
.
18
. <bean id=
"bean3"
class
=
"com.szy.spring.bean.Bean3"
parent=
"beanAbstract"
/>
19
.
20
.</beans>
beanAbstract就是咱們抽象出來的,設置
abstract
=
"true"
屬性後就不須要指定
class
屬性。
咱們把原來配置文件裏的關於bean2和bean3節點註釋掉。
下面進行測試,在這裏要注意因爲咱們使用了兩個配置文件,所以咱們在讀取是要寫兩個配置文件名。咱們查看ClassPathXmlApplicationContext源文件發現其有個構造函數參數是string數組,所以咱們能夠把這個配置文件名放在數組裏面。此外咱們還有另一種實現方法,兩個配置文件一個叫applicationContext.xml,另外一個applicationCommon.xml,公共部分是applicationC*.xml,下面咱們就能夠這樣進行測試:
Java代碼
1
.
@Test
2
.
public
void
testMethod()
throws
Exception
3
. {
4
. ApplicationContext ctx=
new
ClassPathXmlApplicationContext(
"applicationC*.xml"
);
5
. Bean1 bean1 = (Bean1)ctx.getBean(
"bean1"
);
6
.
7
. System.out.println(
"bean1.bean2.id="
+ bean1.getBean2().getId());
8
. System.out.println(
"bean1.bean2.name="
+ bean1.getBean2().getName());
9
. System.out.println(
"bean1.bean2.password="
+ bean1.getBean2().getPassword());
10
. System.out.println(
"bean1.bean3.id="
+ bean1.getBean3().getId());
11
. System.out.println(
"bean1.bean3.name="
+ bean1.getBean3().getName());
12
. System.out.println(
"bean1.bean4.age="
+ bean1.getBean4().getAge());
13
. }
若是咱們bean2的name屬性的值不是kuka,那麼咱們只需在applicationCommon.xml文件的bean2節點下再添加property屬性便可
Xml代碼
1
.<property name=
"name"
value=
"coolszy"
/>
Spring學習筆記(
11
)----自定義屬性編輯器
-------------------------------------------
前面咱們所定義的屬性都是幾本的屬性,若是咱們定義一個屬性是Date類型,例如以下類中:
Java代碼
1
.
package
com.szy.spring.bean;
2
.
3
.
import
java.util.Date;
4
.
5
.
public
class
Bean {
6
.
private
Date date;
7
.
8
.
public
Date getDate()
9
. {
10
.
return
date;
11
. }
12
.
public
void
setDate(Date date)
13
. {
14
.
this
.date = date;
15
. }
16
.}
按照咱們之前學過的知識咱們須要在配置文件中給該屬性注入值
Xml代碼
1
.<bean id=
"bean"
class
=
"com.szy.spring.bean.Bean"
>
2
. <property name=
"date"
value=
"2009-11-21"
/>
3
. </bean>
下面咱們測試是否成功注入值
Java代碼
1
.ApplicationContext ctx=
new
ClassPathXmlApplicationContext(
"applicationContext.xml"
);
2
. Bean bean = (Bean)ctx.getBean(
"bean"
);
3
. System.out.println(bean.getDate());
運行包以下異常
Exception代碼
1
.org.springframework.beans.factory.BeanCreationException: Error creating bean with name
'bean'
defined in
class
path resource [applicationContext.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type [java.lang.String] to required type [java.util.Date]
for
property
'date'
; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required type [java.util.Date]
for
property
'date'
: no matching editors or conversion strategy found
經過錯誤提示信息咱們得知spring不能將string轉換成date類型,沒有匹配的編輯器或者轉換機制。
若是想實現string轉換成Date,那麼咱們本身須要寫一個屬性編輯器
咱們新建一個類DatePropertyEditor,這個類要繼承PropertyEditorSupport類。
咱們須要複寫這個類中的setAsText方法,其中text參數就是配置文件中的值。咱們的任務就是把text轉換成date類型的值。
Java代碼
1
.
package
com.szy.spring.util;
2
.
3
.
import
java.beans.PropertyEditorSupport;
4
.
import
java.text.SimpleDateFormat;
5
.
import
java.util.Date;
6
.
7
.
public
class
DatePropertyEditor
extends
PropertyEditorSupport
8
.{
9
.
10
.
@Override
11
.
public
void
setAsText(String text)
throws
IllegalArgumentException
12
. {
13
. String format=
"yyyy-MM-dd"
;
14
. SimpleDateFormat sdf=
new
SimpleDateFormat(format);
15
.
try
16
. {
17
. Date date=sdf.parse(text);
18
.
this
.setValue(date);
//把轉換後的值傳過去
19
. }
catch
(Exception e)
20
. {
21
. e.printStackTrace();
22
. }
23
. }
24
.
25
.}
寫完編輯器後咱們還須要把編輯器注入到spring中。 爲了方便管理咱們再新建一個配置文件applicationEditor.xml,用來配置屬性編輯器
Xml代碼
1
.<?xml version=
"1.0"
encoding=
"UTF-8"
?>
2
.<beans xmlns=
"http://www.springframework.org/schema/beans"
3
. xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
4
. xmlns:context=
"http://www.springframework.org/schema/context"
5
. xmlns:tx=
"http://www.springframework.org/schema/tx"
6
. xsi:schemaLocation="http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7
. http:
//www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
8
. http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
9
. <bean id=
"customEditorConfigurer"
class
=
"org.springframework.beans.factory.config.CustomEditorConfigurer"
>
10
. <!-- 把值注入到CustomEditorConfigurer的 Map類型的customEditors屬性-->
11
. <property name=
"customEditors"
>
12
. <map>
13
. <entry key=
"java.util.Date"
>
14
. <!-- 內部bean只供本身使用 -->
15
. <bean
class
=
"com.szy.spring.util.DatePropertyEditor"
/>
16
. </entry>
17
. </map>
18
. </property>
19
. </bean>
20
.
21
.</beans>
下面咱們修改下測試代碼已讀取全部的配置文件
Java代碼
1
.ApplicationContext ctx=
new
ClassPathXmlApplicationContext(
"application*.xml"
);
2
. Bean bean = (Bean)ctx.getBean(
"bean"
);
3
. System.out.println(bean.getDate());
最後測試,成功輸出時間。
剛纔咱們在配置文件中時間的格式是
2009
-
11
-
21
,若是咱們修改爲
2009
/
11
/
21
呢?
運行報錯:Unparseable date:
"2009/11/21"
這時咱們須要修改屬性編輯器類文件的格式了,很麻煩。既然spring支持注入,那麼咱們爲何不對格式進行注入呢?
修改屬性編輯器類:
Java代碼
1
.
package
com.szy.spring.util;
2
.
3
.
import
java.beans.PropertyEditorSupport;
4
.
import
java.text.SimpleDateFormat;
5
.
import
java.util.Date;
6
.
7
.
public
class
DatePropertyEditor
extends
PropertyEditorSupport
8
.{
9
.
10
.
private
String format;
11
.
@Override
12
.
public
void
setAsText(String text)
throws
IllegalArgumentException
13
. {
14
.
15
. SimpleDateFormat sdf=
new
SimpleDateFormat(format);
16
.
try
17
. {
18
. Date date=sdf.parse(text);
19
.
this
.setValue(date);
//把轉換後的值傳過去
20
. }
catch
(Exception e)
21
. {
22
. e.printStackTrace();
23
. }
24
. }
25
.
public
String getFormat()
26
. {
27
.
return
format;
28
. }
29
.
public
void
setFormat(String format)
30
. {
31
.
this
.format = format;
32
. }
33
.}
同時給該類對應的bean添加屬性節點
Xml代碼
1
.<bean
class
=
"com.szy.spring.util.DatePropertyEditor"
>
2
. <property name=
"format"
value=
"yyyy/MM/dd"
></property>
3
. </bean>
下次只要咱們修改配置文件便可,靈活性很大。
Spring學習筆記(
12
)----靜態代理模式分析演示
--------------------------------------------
代理模式分爲靜態代理和動態代理。靜態代理就是咱們本身定義的代理類,動態代理是程序在運行時生成的代理類。
下面演示下靜態代理類。首先咱們要定義一個接口:
Java代碼
1
.
package
com.szy.spring;
2
.
3
.
public
interface
UserManager
4
.{
5
.
public
void
addUser(String username,String password);
6
.
public
void
deleteUser(
int
userId);
7
.
public
void
modifyUser(
int
userId,String username,String password);
8
.
public
void
findUser(
int
userId);
9
.}
比較常見的對用戶進行增刪改查。
下面咱們常見一個實現類,實現這個接口。
Java代碼
1
.
package
com.szy.spring;
2
.
3
.
public
class
UserManagerImpl
implements
UserManager
4
.{
5
.
6
.
public
void
addUser(String username, String password)
7
. {
8
. System.out.println(
"--------UserManagerImpl.addUser()----------"
);
9
. }
10
.
11
.
public
void
deleteUser(
int
userId)
12
. {
13
. System.out.println(
"--------UserManagerImpl.deleteUser()----------"
);
14
. }
15
.
16
.
public
void
findUser(
int
userId)
17
. {
18
. System.out.println(
"--------UserManagerImpl.findUser()----------"
);
19
. }
20
.
21
.
public
void
modifyUser(
int
userId, String username, String password)
22
. {
23
. System.out.println(
"--------UserManagerImpl.modifyUser()----------"
);
24
. }
25
.}
每一個方法僅僅是輸出一句話。
下面咱們定義一個客戶端類來調用這些方法。
Java代碼
1
.
package
com.szy.spring;
2
.
3
.
public
class
Client
4
.{
5
.
public
static
void
main(String[] args)
6
. {
7
. UserManager userManager=
new
UserManagerImpl();
8
. userManager.addUser(
"coolszy"
,
"kuka"
);
9
. }
10
.}
運行正常輸出咱們指望的結果。
下面咱們須要加入安全性檢查,就是調用方法前咱們須要進行驗證,比較常見的就是權限驗證,驗證用戶是否擁有權限,
比較常見的作法就是在UserManagerImpl類中定義一個檢查安全性的方法:
Java代碼
1
.
public
void
checkSecurity()
2
. {
3
. System.out.println(
"--------UserManagerImpl.checkSecurity()----------"
);
4
. }
而後在每一個方法中都要調用這個方法。可是這樣不符合開-閉原則(Open-Closed principle,簡稱OCP)。所以咱們可使用代理類來實現這個功能。代理模式很顯著的特徵就是和目標對象的接口一致。在代理類中咱們能夠控制目標對象。要控制目標對象咱們必須有一個目標對象的引用。爲了靈活咱們能夠把目標對象傳到方法中,而不是在方法中實例化。同時咱們把安全性檢查的代碼也放到代理類中,在調用每一個方法以前調用這個檢查方法,經過代理對咱們之前的類沒有破壞。
Java代碼
1
.
package
com.szy.spring;
2
.
3
.
public
class
UserManagerImplProxy
implements
UserManager
4
.{
5
.
private
UserManager userManager;
6
.
7
.
public
UserManagerImplProxy(UserManager userManager)
8
. {
9
.
this
.userManager = userManager;
10
. }
11
.
public
void
addUser(String username, String password)
12
. {
13
. checkSecurity();
14
.
this
.userManager.addUser(username, password);
15
. }
16
.
public
void
deleteUser(
int
userId)
17
. {
18
. checkSecurity();
19
.
this
.userManager.deleteUser(userId);
20
. }
21
.
public
String findUser(
int
userId)
22
. {
23
. checkSecurity();
24
.
return
this
.userManager.findUser(userId);
25
. }
26
.
public
void
modifyUser(
int
userId, String username, String password)
27
. {
28
. checkSecurity();
29
.
this
.userManager.modifyUser(userId, username, password);
30
. }
31
.
public
void
checkSecurity()
32
. {
33
. System.out.println(
"--------UserManagerImpl.checkSecurity()----------"
);
34
. }
35
.}
下面修改客戶端類。
Java代碼
1
.UserManager userManager=
new
UserManagerImplProxy(
new
UserManagerImpl());
2
. userManager.addUser(
"coolszy"
,
"kuka"
);
這樣總的來講比較靈活。這個依賴關係是咱們本身作的,咱們徹底能夠交給spring處理。
按照上面的這種作法有一個缺點,若是接口中方法不少,那麼咱們實現每個方法都要添加檢查方法checkSecurity(),影響了咱們的業務處理。採用靜態代理模式咱們是無法解決的,這時咱們須要使用AOP思想。
Spring學習筆記(
13
)----動態代理模式分析演示
-----------------------------------------------
上一節演示的是靜態代理模式,本節演示的是靜態代理模式,既然是動態,那麼就不存在UserManagerImplProxy類。
使用動態代理咱們須要聲明一個類SecurityHandler,這個類要實現InvocationHandler接口。
在類中定義一個產生動態代理的方法newProxy();同時把咱們驗證的代碼放到這個類中。經過SecurityHandler,當咱們調用方法時默認會調用SecurityHandler類invoke方法,咱們在這個方法中進行安全性檢查,檢查經過後在調用真實的方法。須要注意的是目標對象接口中的部分方法是存在返回值的。
Java代碼
1
.
package
com.szy.spring;
2
.
3
.
import
java.lang.reflect.InvocationHandler;
4
.
import
java.lang.reflect.Method;
5
.
import
java.lang.reflect.Proxy;
6
.
7
.
public
class
SecurityHandler
implements
InvocationHandler
8
.{
9
.
private
Object targetObject;
10
.
11
.
public
Object newProxy(Object targetObject)
12
. {
13
.
this
.targetObject=targetObject;
14
.
//返回動態代理
15
.
return
Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
16
. targetObject.getClass().getInterfaces(),
17
.
this
);
18
. }
19
.
public
Object invoke(Object proxy, Method method, Object[] args)
20
.
throws
Throwable
21
. {
22
. checkSecurity();
23
. Object ret=
null
;
24
.
try
25
. {
26
.
//調用目標對象的真實方法
27
. ret=method.invoke(
this
.targetObject, args);
28
.
//ret接受存在的返回值,不存在返回值則爲Null
29
. }
catch
(Exception e)
30
. {
31
. e.printStackTrace();
32
. }
33
.
return
null
;
34
. }
35
.
public
void
checkSecurity()
36
. {
37
. System.out.println(
"--------UserManagerImpl.checkSecurity()----------"
);
38
. }
39
.}
使用這種方式維護起來相對比較好,我想進行安全性檢查就進行,不想就不進行,很方便。
下面進行客戶端調用
Java代碼
1
.
package
com.szy.spring;
2
.
3
.
public
class
Client
4
.{
5
.
public
static
void
main(String[] args)
6
. {
7
. SecurityHandler handler=
new
SecurityHandler();
8
.
//建立代理對象
9
. UserManager userManager=(UserManager)handler.newProxy(
new
UserManagerImpl());
10
. userManager.addUser(
"coolszy"
,
"kuka"
);
11
. }
12
.}
Spring學習筆記(
14
)----使用CGLIB實現AOP功能
-----------------------------------------------
接着這上面的例子,在上面的例子中咱們的UserManagerImpl類是實現了UserManager接口,若是UserManagerImpl沒有實現任何接口要怎麼辦呢?應爲建立代理對象時咱們須要指定接口的。
Java代碼
1
.Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
2
. targetObject.getClass().getInterfaces(),
3
.
this
);
因爲沒有時間接口,所以咱們是不能這樣建立代理接口的,這是咱們須要藉助第三方包來實現。在spring中提供了cglib-nodep-
2
.1_3.jar包。咱們經過cglib建立代理對象。
下面就經過實例演示經過cglib建立代理對象。
首先建立CGlibProxyFactory,實現MethodInterceptor接口,接口中有一個intercept方法,當代理對象的方法被調用時會調用這個方法。
Java代碼
1
.
package
com.szy.spring;
2
.
3
.
import
java.lang.reflect.Method;
4
.
import
net.sf.cglib.proxy.Enhancer;
5
.
import
net.sf.cglib.proxy.MethodInterceptor;
6
.
import
net.sf.cglib.proxy.MethodProxy;
7
.
8
.
9
.
public
class
CGlibProxyFactory
implements
MethodInterceptor
10
.{
11
.
private
Object targetObject;
12
.
13
.
public
Object newProxy(Object targetObject)
14
. {
15
.
this
.targetObject=targetObject;
16
. Enhancer enhancer=
new
Enhancer();
17
. enhancer.setSuperclass(
this
.targetObject.getClass());
18
. enhancer.setCallback(
this
);
19
.
//返回代理對象
20
.
return
enhancer.create();
21
. }
22
.
23
.
/**
24. * proxy 帶來對象自己
25. * method 被攔截到的方法
26. * args 方法的參數
27. * methodProxy 方法的代理對象
28. */
29
.
public
Object intercept(Object proxy, Method method, Object[] args,
30
. MethodProxy methodProxy)
throws
Throwable
31
. {
32
. checkSecurity();
33
. Object ret=
null
;
34
.
try
35
. {
36
.
//調用目標對象的真實方法
37
. ret=method.invoke(
this
.targetObject, args);
38
.
//ret接受存在的返回值,不存在返回值則爲Null
39
. }
catch
(Exception e)
40
. {
41
. e.printStackTrace();
42
. }
43
.
return
ret;
44
. }
45
.
public
void
checkSecurity()
46
. {
47
. System.out.println(
"--------UserManagerImpl.checkSecurity()----------"
);
48
. }
49
.}
其實整個代碼很前面的很類似,只是建立代理對象的方法不同。
測試代碼:
Java代碼
1
.CGlibProxyFactory factory=
new
CGlibProxyFactory();
2
.
//建立代理對象,這是這個代理對象是UserManagerImpl的子類
3
. UserManagerImpl userManager=(UserManagerImpl)factory.newProxy(
new
UserManagerImpl());
4
. userManager.addUser(
"coolszy"
,
"kuka"
);
上面演示的幾個事例是不借助與任何框架的狀況下實現AOP的方法。
Spring學習筆記(
15
)----使用Spring的註解方式實現AOP
-----------------------------------------------------
下面介紹使用Spring框架進行AOP編程。
首先咱們須要導入須要的jar包:
1
.aspectjrt.jar
2
.aspectjweaver.jar
3
.cglib-nodep-
2
.1_3.jar
在spring中有兩種方式實現面向切面編程,一種是基於XML配置,另外一種是使用註解份額方式,在實際開放中咱們能夠任選其中的一種便可。
首先介紹下使用註解方式進行AOP開發。
要使用註解方式,咱們須要打開註解處理器
Xml代碼
1
.<aop:aspectj-autoproxy/>
咱們仍是使用前面介紹的接口:
Java代碼
1
.
package
com.szy.spring;
2
.
3
.
public
interface
UserManager
4
.{
5
.
6
.
public
abstract
void
addUser(String username, String password);
7
.
8
.
public
abstract
void
deleteUser(
int
userId);
9
.
10
.
public
abstract
String findUser(
int
userId);
11
.
12
.
public
abstract
void
modifyUser(
int
userId, String username, String password);
13
.
14
.}
實現這個接口:
Java代碼
1
.
package
com.szy.spring;
2
.
3
.
public
class
UserManagerImpl
implements
UserManager
4
.{
5
.
6
.
public
void
addUser(String username, String password)
7
. {
8
. System.out.println(
"--------UserManagerImpl.addUser()----------"
);
9
. }
10
.
11
.
public
void
deleteUser(
int
userId)
12
. {
13
. System.out.println(
"--------UserManagerImpl.deleteUser()----------"
);
14
. }
15
.
16
.
public
String findUser(
int
userId)
17
. {
18
. System.out.println(
"--------UserManagerImpl.findUser()----------"
);
19
.
return
null
;
20
. }
21
.
22
.
public
void
modifyUser(
int
userId, String username, String password)
23
. {
24
. System.out.println(
"--------UserManagerImpl.modifyUser()----------"
);
25
. }
26
.}
下面咱們定義一個切面類,因爲咱們使用的是註解方式,所以咱們使用
@Aspect
來標識它是切面類。在切面類中咱們要定義切入點,切入點是用來定義咱們要攔截的方法。在切入點定義中使用了AOP表達式語言,下面經過實例簡單解釋一下:
表達式解釋代碼
1
.
@Pointcut
(
"execution (* com.szy.spring..*.*(..))"
)
2
.execution:表明執行
3
.第一個*:表明返回值類型,使用*表明任何類型的返回值
4
.com.szy.spring:表明包名
5
...:表明其底下的子包也進行攔截
6
.第二個*:表明對哪一個類進行攔截,*表明全部類
7
.第三個*:表明方法
8
.(..):表明方法的蠶食有無均可以
如今咱們要對UserManagerImpl類下的全部方法進行攔截,則切入點以下表示:
Java代碼
1
.
@Pointcut
(
"execution (* com.szy.spring.UserManagerImpl.*(..))"
)
2
.
3
.
private
void
anyMethod()
//定義切入點
4
. {
5
. }
其中切入點的名稱是下面方法的名稱aynMethod(),包括括號。
下面咱們定義通知,通知分爲前置通知、後置通知、意外通知、等。通知分爲前置通知、後置通知、意外通知、最終通知和環繞通知等。
演示前置通知,
Java代碼
1
.
@Before
(
"anyMethod()"
)
//括號內爲切入點名稱
2
.
public
void
doBefore()
3
. {
4
. System.out.println(
"----------------執行前置通知-----------------"
);
5
. }
6
.
7
.
@AfterReturning
(
"anyMethod()"
)
8
.
public
void
doAfterReturning()
9
. {
10
. System.out.println(
"----------------執行後置通知-----------------"
);
11
. }
Java代碼
1
.
@After
(
"anyMethod()"
)
2
.
public
void
doAfter()
3
. {
4
. System.out.println(
"----------------執行最終通知-----------------"
);
5
. }
6
.
7
.
@AfterThrowing
(
"anyMethod()"
)
8
.
public
void
doAfterThrowing()
9
. {
10
. System.out.println(
"----------------執行意外通知-----------------"
);
11
. }
12
.
13
.
@Around
(
"anyMethod()"
)
14
.
public
Object doAround(ProceedingJoinPoint pjp)
throws
Throwable
15
. {
16
. System.out.println(
"----------------進入判斷方法-----------------"
);
17
. Object result=pjp.proceed();
//該方法必須被執行
18
. System.out.println(
"----------------退出判斷方法-----------------"
);
19
.
return
result;
20
. }
咱們把切面交給spring管理,要交給spring管理咱們能夠在配置文件同進行bean配置,或者使用掃描的方式。
Xml代碼
1
.<bean id=
"interceptor"
class
=
"com.szy.spring.Interceptor"
/>
下面咱們進行測試
Java代碼
1
.ApplicationContext context=
new
ClassPathXmlApplicationContext(
"applicationContext.xml"
);
2
. UserManager manager=(UserManager)context.getBean(
"userManager"
);
3
. manager.addUser(
"coolszy"
,
"kuka"
);
按照咱們的設計,輸入的結果應爲
----------------執行前置通知-----------------
----------------進入判斷方法-----------------
--------UserManagerImpl.addUser()----------
----------------執行後置通知-----------------
----------------執行最終通知-----------------
----------------退出判斷方法-----------------
Spring學習筆記(
16
)----使用Spring配置文件實現AOP
----------------------------------------------
前面介紹了使用註解的方式,下面介紹使用配置文件的方式實現AOP。
使用配置方式,Interceptor類中不包含任何註解。
Java代碼
1
.
package
com.szy.spring;
2
.
3
.
import
org.aspectj.lang.ProceedingJoinPoint;
4
.
5
.
public
class
Interceptor
6
.{
7
.
public
void
doBefore()
8
. {
9
. System.out.println(
"----------------執行前置通知-----------------"
);
10
. }
11
.
12
.
public
void
doAfterReturning()
13
. {
14
. System.out.println(
"----------------執行後置通知-----------------"
);
15
. }
16
.
17
.
public
void
doAfter()
18
. {
19
. System.out.println(
"----------------執行最終通知-----------------"
);
20
. }
21
.
22
.
public
void
doAfterThrowing()
23
. {
24
. System.out.println(
"----------------執行意外通知-----------------"
);
25
. }
26
.
27
.
public
Object doAround(ProceedingJoinPoint pjp)
throws
Throwable
28
. {
29
. System.out.println(
"----------------進入判斷方法-----------------"
);
30
. Object result=pjp.proceed();
//該方法必須被執行
31
. System.out.println(
"----------------退出判斷方法-----------------"
);
32
.
return
result;
33
. }
34
.}
緊着這咱們在配置文件中配置切面、切入點、通知等:
Xml代碼
1
.<bean id=
"aspetbean"
class
=
"com.szy.spring.Interceptor"
/>
2
. <aop:config>
3
. <aop:aspect id=
"aspet"
ref=
"aspetbean"
>
4
. <aop:pointcut id=
"cut"
expression=
"execution (* com.szy.spring.UserManagerImpl.*(..))"
/>
5
. <aop:before pointcut-ref=
"cut"
method=
"doBefore"
/>
6
. <aop:after-returning pointcut-ref=
"cut"
method=
"doAfterReturning"
/>
7
. <aop:after pointcut-ref=
"cut"
method=
"doAfter"
/>
8
. <aop:after-throwing pointcut-ref=
"cut"
method=
"doAfterThrowing"
/>
9
. <aop:around pointcut-ref=
"cut"
method=
"doAround"
/>
10
. </aop:aspect>
11
. </aop:config>
運行測試代碼輸入正常結果。
在實際開發中AOP通常用於權限設置等。
Spring學習筆記(
17
)----使用Spring註解方式管理事務
--------------------------------------------------
使用Spring+JDBC集成步驟以下:
*配置數據源,例如:
Xml代碼
1
.<bean id=
"dataSource"
class
=
"org.apache.commons.dbcp.BasicDataSource"
destroy-method=
"close"
>
2
. <property name=
"driverClassName"
value=
"com.mysql.jdbc.Driver"
/>
3
. <property name=
"url"
value=
"jdbc:mysql://localhost:3306/test"
/>
4
. <property name=
"username"
value=
"root"
/>
5
. <property name=
"password"
value=
"123456"
/>
6
. <!-- 鏈接池啓動時的初始值 -->
7
. <property name=
"initialSize"
value=
"1"
/>
8
. <!-- 鏈接池的最大值 -->
9
. <property name=
"maxActive"
value=
"100"
/>
10
. <!-- 最大空閒值.當通過一個高峯時間後,鏈接池能夠慢慢將已經用不到的鏈接慢慢釋放一部分,一直減小到maxIdle爲止 -->
11
. <property name=
"maxIdle"
value=
"2"
/>
12
. <!-- 最小空閒值.當空閒的鏈接數少於閥值時,鏈接池就會預申請去一些鏈接,以避免洪峯來時來不及申請 -->
13
. <property name=
"minIdle"
value=
"1"
/>
14
. </bean>
*配置事務,配置事務時,須要在xml配置文件中引入用於聲明事務的tx命名空間,事務的配置有兩種方式:註解方式和基於XML配置的方式
下面演示下使用Spring註解方式管理事務
首先在配置文件中配置Spring提供的事務管理器
Xml代碼
1
.<bean id=
"txManager"
class
=
"org.springframework.jdbc.datasource.DataSourceTransactionManager"
>
2
. <!-- 指定數據源 -->
3
. <property name=
"dataSource"
ref=
"dataSource"
/>
4
. </bean>
因爲會使用註解方式,所以咱們要打開註解處理器,對註解進行解析
Xml代碼
1
.<tx:annotation-driven transaction-manager=
"txManager"
/>
這樣咱們的配置文件配置完成,下面咱們在Mysql中創建一張表,
Sql代碼
1
.create table users
2
.(
3
. id
int
(
11
) not
null
auto_increment,
4
. username varchar(
20
) not
null
,
5
. primary key (id)
6
.)
根據數據庫,咱們建立javabean
Java代碼
1
.
package
com.szy.spring.bean;
2
.
/**
3. * @author coolszy
4. * @time Dec 6, 2009 2:13:33 PM
5. */
6
.
public
class
User
7
.{
8
.
private
int
id;
9
.
private
String username;
10
.
public
int
getId()
11
. {
12
.
return
id;
13
. }
14
.
public
void
setId(
int
id)
15
. {
16
.
this
.id = id;
17
. }
18
.
public
String getUsername()
19
. {
20
.
return
username;
21
. }
22
.
public
void
setUsername(String username)
23
. {
24
.
this
.username = username;
25
. }
26
.}
而後建立DAO接口,在DAO中提供幾個方法:
Java代碼
1
.
package
com.szy.spring.dao;
2
.
3
.
import
java.util.List;
4
.
5
.
import
com.szy.spring.bean.User;
6
.
7
.
public
interface
UserDAO
8
.{
9
.
public
void
save(User user);
10
.
public
void
update(User user);
11
. Public User getUser(
int
id);
12
.
public
void
delete(
int
id);
13
.
public
List<User> getAllUsers();
14
.}
實現這個接口
Java代碼
1
.
package
com.szy.spring.dao.impl;
2
.
3
.
import
java.util.List;
4
.
5
.
import
com.szy.spring.bean.User;
6
.
import
com.szy.spring.service.UserService;
7
.
8
.
/**
9. * @author coolszy
10. * @time Dec 6, 2009 2:19:22 PM
11. */
12
.
public
class
UserDAOImpl
implements
UserDAO
13
.{
14
.
15
.
public
void
delete(
int
id)
16
. {
17
.
18
. }
19
.
20
.
public
List<User> getAllUsers()
21
. {
22
.
return
null
;
23
. }
24
.
25
.
public
User getUser(
int
id)
26
. {
27
.
28
. }
29
.
30
.
public
void
save(User user)
31
. {
32
.
33
. }
34
.
35
.
public
void
update(User user)
36
. {
37
.
38
. }
39
.
40
.}
下面把這個類交給Spring管理
Xml代碼
1
.<bean id=
"userDAO"
class
=
"com.szy.spring.dao.impl.UserDAOImpl"
/>
因爲要經過數據源對錶進行操做,所以在DAO中添加數據源。
Java代碼
1
.
private
DataSource dataSource;
2
.
3
.
public
void
setDataSource(DataSource dataSource)
4
. {
5
.
this
.dataSource = dataSource;
6
. }
而後在配置文件中進行配置
Xml代碼
1
.<bean id=
"userDAO"
class
=
"com.szy.spring.service.impl.UserDAOImpl"
>
2
. <property name=
"dataSource"
ref=
"dataSource"
/>
3
. </bean>
這樣咱們就把數據源注入到類中。
在UserDAOImpl類中咱們提供了dataSource,這樣咱們就能夠對數據庫進行操做,可是不推薦直接使用dataSource,建議使用JdbcTemplate
Java代碼
1
.
private
JdbcTemplate jdbcTemplate;
2
.
public
void
setDataSource(DataSource dataSource)
3
. {
4
.
//this.dataSource = dataSource;
5
.
this
.jdbcTemplate=
new
JdbcTemplate(dataSource);
6
. }
下面咱們使用jdbcTemplate對數據庫進行增刪改查,詳細代碼見附件。
Java代碼
1
.
package
com.szy.spring.dao.impl;
2
.
3
.
import
java.util.List;
4
.
5
.
import
javax.sql.DataSource;
6
.
7
.
import
org.springframework.jdbc.core.JdbcTemplate;
8
.
9
.
import
com.szy.spring.bean.User;
10
.
import
com.szy.spring.dao.UserDAO;
11
.
12
.
/**
13. * @author coolszy
14. * @time Dec 6, 2009 2:19:22 PM
15. */
16
.
public
class
UserDAOImpl
implements
UserDAO
17
.{
18
.
//private DataSource dataSource;
19
.
private
JdbcTemplate jdbcTemplate;
20
.
public
void
setDataSource(DataSource dataSource)
21
. {
22
.
//this.dataSource = dataSource;
23
.
this
.jdbcTemplate=
new
JdbcTemplate(dataSource);
24
. }
25
.
26
.
public
void
delete(
int
id)
27
. {
28
. jdbcTemplate.update(
"delete from users where id=?"
,
new
Object[]{id},
29
.
new
int
[]{java.sql.Types.INTEGER});
30
. }
31
.
32
.
public
List<User> getAllUsers()
33
. {
34
.
return
(List<User>)jdbcTemplate.query(
"select * from users"
,
new
UserRowMapper());
35
. }
36
.
37
.
public
User getUser(
int
id)
38
. {
39
.
return
(User)jdbcTemplate.queryForObject(
"select * from users where id=?"
,
new
Object[]{id},
40
.
new
int
[]{java.sql.Types.INTEGER},
new
UserRowMapper());
41
.
42
. }
43
.
44
.
public
void
save(User user)
45
. {
46
. jdbcTemplate.update(
"insert into users(username) values(?)"
,
new
Object[]{user.getUsername()},
47
.
new
int
[]{java.sql.Types.VARCHAR});
48
.
49
. }
50
.
51
.
public
void
update(User user)
52
. {
53
. jdbcTemplate.update(
"update users set username=? where id=?"
,
new
Object[]{user.getUsername(),user.getId()},
54
.
new
int
[]{java.sql.Types.VARCHAR, java.sql.Types.INTEGER});
55
.
56
. }
57
.
58
.}
編寫測試代碼,代碼運行正常。
在咱們實現的每一個方法中如delete()方法,若是delete方法是這樣
Java代碼
1
.
public
void
delete(
int
id)
2
. {
3
. jdbcTemplate.update(
"delete from users where id=?"
,
new
Object[]{id},
4
.
new
int
[]{java.sql.Types.INTEGER});
5
.jdbcTemplate.update(
"delete from users where id=?"
,
new
Object[]{id},
6
.
new
int
[]{java.sql.Types.INTEGER});
7
.
8
. }
9
.
這樣每條語句都會在各自的事務中執行,並不能保證在同一使用中執行,爲了保證在同一事務中執行,咱們應使用Spring容器提供的聲明事務,咱們在UserDAOImpl 類上加入
@Transactional
,表示該類受Spring事務管理。若是該類中每一個方法不須要事務管理,如getUser方法,則在該方法前加入
Java代碼
1
.
@Transactional
(propagation=Propagation.NOT_SUPPORTED)
PS:在上面的配置文件中咱們在配置文件中指明瞭驅動類等信息,若是咱們想寫在配置文件中要怎麼配置能,首先咱們編寫配置文件,
Jdbc.properties代碼
1
.driverClassName=com.mysql.jdbc.Driver
2
.url=jdbc\:mysql\:
//localhost\:3306/test
3
.username=root
4
.password=
123456
5
.initialSize=
1
6
.maxActive=
100
7
.maxIdle=
2
8
.minIdle=
1
而後Spring的配置文件需進行以下配置:
Xml代碼
1
.<context:property-placeholder location=
"classpath:jdbc.properties"
/>
2
. <bean id=
"dataSource"
class
=
"org.apache.commons.dbcp.BasicDataSource"
destroy-method=
"close"
>
3
. <property name=
"driverClassName"
value=
"${driverClassName}"
/>
4
. <property name=
"url"
value=
"${url}"
/>
5
. <property name=
"username"
value=
"${username}"
/>
6
. <property name=
"password"
value=
"${password}"
/>
7
. <property name=
"initialSize"
value=
"${initialSize}"
/>
8
. <property name=
"maxActive"
value=
"${maxActive}"
/>
9
. <property name=
"maxIdle"
value=
"${maxIdle}"
/>
10
. <property name=
"minIdle"
value=
"${minIdle}"
/>
11
. </bean>
這樣就能夠從屬性文件中讀取到配置信息。
Spring學習筆記(
18
)----使用Spring配置文件實現事務管理
-------------------------------------------------------
因爲咱們要攔截UserDAOImpl中的方法,所以咱們須要在配置文件中配置信息,在配置文件中使用了AOP技術來攔截方法。
Xml代碼
1
.<aop:config>
2
. <aop:pointcut id=
"transactionPointcut"
expression=
"execution(* com.szy.spring.dao.impl..*.*(..))"
/>
3
. <aop:advisor advice-ref=
"txAdvice"
pointcut-ref=
"transactionPointcut"
/>
4
. </aop:config>
5
. <tx:advice id=
"txAdvice"
transaction-manager=
"txManager"
>
6
. <tx:attributes>
7
. <!-- 若是鏈接的方法是以get開頭的方法,則不使用事務 -->
8
. <tx:method name=
"get*"
read-only=
"true"
propagation=
"NOT_SUPPORTED"
/>
9
. <tx:method name=
"*"
/>
10
. </tx:attributes>
11
. </tx:advice>
這樣Spring就能對這個類進行事務管理。
下面咱們測試下數據庫操做是否在同一事務中執行。
假設咱們的delete方法以下:
Java代碼
1
.
public
void
delete(
int
id)
2
. {
3
. jdbcTemplate.update(
"delete from users where id=?"
,
new
Object[]{id},
4
.
new
int
[]{java.sql.Types.INTEGER});
5
. jdbcTemplate.update(
"delete from users1 where id=10"
);
6
. }
在第二條刪除語句中,users1表是不存在的,若是兩次update語句是在兩個事務中執行,則第一條能成功執行,而且數據庫中該id的記錄已經被刪除,而第二條因爲不存在該表不能正常刪除。若是在同一事務中執行,因爲第二條update出錯,數據庫中不能刪除任何記錄。
測試代碼:
Java代碼
1
.
@Test
2
.
public
void
testDelete()
3
. {
4
. userDAO.delete(
5
);
5
. }
程序報錯,同時id=
5
的記錄沒有被刪除。若是咱們把配置文件中關於事務配置的信息給註釋掉,再次測試,程序一樣報錯,可是id=
5
的記錄被成功刪除掉,這說明這兩條update語句是在兩個不一樣的事務中運行。
PS:在平時開發中,Spring團隊建議使用註解的方式進行配置,這樣配置文件顯得精簡,同時也會作到精確控制。
|