不錯的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團隊建議使用註解的方式進行配置,這樣配置文件顯得精簡,同時也會作到精確控制。
相關文章
相關標籤/搜索