不錯的Spring學習筆記(轉)


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團隊建議使用注解的方式進行配置,這樣配置文件顯得精簡,同時也會做到精確控制。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM