Spring2.5註釋驅動與基於註釋的MVC

寫在前面:
好長時間沒有寫博客了,主要是最近一直忙於工做上面的事情沒有研究什麼新的東西,也沒有什麼寫的,最近應一個朋友的邀請一塊兒開發一套教材,我纔有開始對Spring研究起來,今天把寫的其中一部分貼出來與你們共享.若有不足之處請多多指教.
Spring2.5註釋驅動
       8.4.1 Spring2.5註釋驅動
       註釋語法愈來愈多的被業界所使用,而且註釋配置相對於 XML 配置具備不少的優點:它能夠充分利用 Java 的反射機制獲取類結構信息,這些信息能夠有效減小配置的工做。註釋和 Java 代碼位於一個文件中,而 XML 配置採用獨立的配置文件,大多數配置信息在程序開發完成後都不會調整,若是配置信息和 Java 代碼放在一塊兒,有助於加強程序的內聚性。而採用獨立的 XML 配置文件,程序員在編寫一個功能時,每每須要在程序文件和配置文件中不停切換,這種思惟上的不連貫會下降開發效率。所以在不少狀況下,註釋配置比 XML 配置更受歡迎,註釋配置有進一步流行的趨勢。Spring 2.5 的一大加強就是引入了不少註釋類,如今您已經可使用註釋配置完成大部分 XML 配置的功能。
       在使用註釋配置以前,先來回顧一下傳統上是如何配置 Bean 並完成 Bean 之間依賴關係的創建。
代碼清單1  Foo.java Foo 對象有一個 String 類型的 name 屬性 .
              package com.tony.test;
public class Foo {
        private String name ;
            public String toStirng(){
               return "Foo Name is :" + this . name ;
            }
Set get 方法
}
代碼清單 2  Bar.java Bar 對象有一個 String 類型的 add 屬性 .
package com.tony.test;
public class Bar {
        private String add ;
            public String toStirng(){
               return "Bar Add is :" + this . add ;
            }
Set get 方法
}
代碼清單 3 Main.java Main 對象有兩個屬性分別是 Foo Bar
package com.tony.test;
public class Main {
        private Foo foo ;
        private Bar bar ;
            public String toString(){
return "Main : [" + this . foo .toStirng() + " " + this . bar .toStirng() + "]" ;
            }
Set get 方法
}
代碼清單 4 配置文件 spring-config-beans.xml
        < bean id = "main" class = "com.tony.test.Main" >
           < property name = "foo" ref = "foo" ></ property >
           < property name = "bar" ref = "bar" ></ property >
        </ bean >
   
        < bean id = "foo" class = "com.tony.test.Foo" >
           < property name = "name" value = "Foo" ></ property >
        </ bean >
        < bean id = "bar" class = "com.tony.test.Bar" >
           < property name = "add" value = "Bar" ></ property >
</ bean >
代碼清單 5 Test.java Test 類用於初始化 Spring 容器並得到 main 對象
package com.tony.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.
ClassPathXmlApplicationContext ;
public class Test {
            public static void main(String[] args) {   
                 String[] locations = { "spring-config-beans.xml" };   
ApplicationContext ctx = new ClassPathXmlApplicationContext(locations);   
                 Main main = (Main) ctx.getBean( "main" );   
                 System. out .println(main);   
            }  
}
運行 Test 類控制檯輸出如下信息:
Main : [Foo Name is :Foo Bar Add is :Bar]
這說明Spring已經完成了Bean的建立和裝配工做。
1)使用 @Autowired 註釋
Spring 2.5 引入了 @Autowired 註釋,它能夠對類成員變量、方法及構造函數進行標註,完成自動裝配的工做。下面咱們來看一下使用 @Autowired 進行成員變量自動注入的代碼:
代碼清單6使用 @Autowired 註釋的 Main.java,此時能夠將Main.java類中的setget方法刪除
package com.tony.test;
 
import org.springframework.beans.factory.annotation.Autowired;
 
public class Main {
           @Autowired
           private Foo foo ;
           @Autowired
           private Bar bar ;
   
           public String toString(){
return "Main : [" + this . foo .toStirng() + " " + this . bar .toStirng() + "]" ;
           }
}
Spring 經過一個 BeanPostProcessor @Autowired 進行解析,因此要讓 @Autowired 起做用必須事先在 Spring 容器中聲明 AutowiredAnnotationBeanPostProcessor Bean
代碼清單 7 修改配置文件
<!--  BeanPostProcessor 將自動對標註 @Autowired  Bean 進行注入 -->    
< bean class = "org.springframework.beans.factory.annotation.
AutowiredAnnotationBeanPostProcessor" />
        <!—此時移除 main Bean 的屬性注入信息 -->  
        < bean id = "main" class = "com.tony.test.Main" ></ bean >
   
        < bean id = "foo" class = "com.tony.test.Foo" >
           < property name = "name" value = "Foo" ></ property >
        </ bean >
        < bean id = "bar" class = "com.tony.test.Bar" >
           < property name = "add" value = "Bar" ></ property >
</ bean >
Spring 容器啓動時,AutowiredAnnotationBeanPostProcessor 將掃描 Spring 容器中全部 Bean,當發現 Bean 中擁有 @Autowired 註釋時就找到和其匹配(默認按類型匹配)的 Bean,並將其注入。
2)使用@Qualifier 註釋
Spring 容許咱們經過 @Qualifier 註釋指定注入 Bean 的名稱,這樣就不會產生注入錯誤了,請看下面代碼清單:
       代碼清單8 修改Main.java類中的foo屬性註釋增長註釋 @Qualifier ( "foo1" )
public class Main {
           @Autowired
           @Qualifier ( "foo1" )
           private Foo foo ;
   
           @Autowired
           private Bar bar ;
   
           public String toString(){
return "Main : [" + this . foo .toStirng() + " " + this . bar .toStirng() + "]" ;
           }
}
代碼清單9 在配置文件中增長idfoo2 Bean定義
< bean class = "org.springframework.beans.factory.annotation.
AutowiredAnnotationBeanPostProcessor" />
   
        < bean id = "main" class = "com.tony.test.Main" ></ bean >
   
        < bean id = "foo1" class = "com.tony.test.Foo" >
           < property name = "name" value = "Foo1" ></ property >
        </ bean >
        < bean id = "foo2" class = "com.tony.test.Foo" >
           < property name = "name" value = "Foo2" ></ property >
        </ bean >
        < bean id = "bar" class = "com.tony.test.Bar" >
           < property name = "add" value = "Bar" ></ property >
</ bean >
運行 Test.java 控制檯輸出以下信息 :
Main : [Foo Name is :Foo1 Bar Add is :Bar]
證實 Spring 容器成功將 foo1 注入進 main 類中
3)使用 <context:annotation-config/> 簡化配置
Spring 2.1 添加了一個新的 context Schema 命名空間,該命名空間對註釋驅動、屬性文件引入、加載期織入等功能提供了便捷的配置。咱們知道註釋自己是不會作任何事情的,它僅提供元數據信息。要使元數據信息真正起做用,必須讓負責處理這些元數據的處理器工做起來。而咱們前面所介紹的 AutowiredAnnotationBeanPostProcessor 就是處理這些註釋元數據的處理器。可是直接在 Spring 配置文件中定義這些 Bean 顯得比較笨拙。Spring 爲咱們提供了一種方便的註冊這些 BeanPostProcessor 的方式,這就是 <context:annotation-config/> 。請看下面的代碼清單:
代碼清單 10
< context:annotation-config />
        < bean id = "main" class = "com.tony.test.Main" ></ bean >
   
        < bean id = "foo1" class = "com.tony.test.Foo" >
           < property name = "name" value = "Foo1" ></ property >
        </ bean >
        < bean id = "foo2" class = "com.tony.test.Foo" >
           < property name = "name" value = "Foo2" ></ property >
        </ bean >
        < bean id = "bar" class = "com.tony.test.Bar" >
           < property name = "add" value = "Bar" ></ property >
</ bean >
代碼清單中將
< bean class = "org.springframework.beans.factory.annotation.
AutowiredAnnotationBeanPostProcessor" />
替換成爲 < context:annotation-config />
<context:annotationconfig/> 將隱式地向 Spring 容器註冊 AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessorPersistenceAnnotationBeanPostProcessor 以及 equiredAnnotationBeanPostProcessor 4 BeanPostProcessor
4) 使用 @Component
雖然咱們能夠經過 @Autowired Bean 類中使用自動注入功能,可是 Bean 仍是在 XML 文件中經過 <bean> 進行定義,也就是說,在 XML 配置文件中定義 Bean,經過 @Autowired Bean 的成員變量、方法入參或構造函數入參提供自動注入的功能。可否也經過註釋定義 Bean,從 XML 配置文件中徹底移除 Bean 定義的配置呢?答案是確定的,咱們經過 Spring 2.5 提供的 @Component 註釋就能夠達到這個目標。請看下面的代碼清單:
代碼清單11 Foo.java
@Component
public class Foo {
           private String name = "Foo's name." ;
           public String toStirng(){
              return "Foo Name is :" + this . name ;
           }
}
在類的開始位置使用 @Component 註釋 , 標明此類是一個 Bean
代碼清單 12 Main.java
@Component ( "main" )
public class Main {
           @Autowired
           private Foo foo ;
   
           @Autowired
    private Bar bar ;
……
@Component 有一個可選的入參,用於指定 Bean 的名稱,在 Main 中,咱們就將 Bean 名稱定義爲「main」。在使用 @Component 註釋後,Spring 容器必須啓用類掃描機制以啓用註釋驅動 Bean 定義和註釋驅動 Bean 的自動注入的策略。Spring 2.5 context 命名空間進行了擴展,提供了這一功能。
代碼清單13 Spring配置文件中只保留如下配置信息
< context:component-scan base-package = "com.tony.test" />
這裏,全部經過 <bean> 元素定義 Bean 的配置內容已經被移除,僅須要添加一行 <context:component-scan/> 配置就解決全部問題了——Spring XML 配置文件獲得了極致的簡化(固然配置元數據仍是須要的,只不過以註釋形式存在罷了)。<context:component-scan/> base-package 屬性指定了須要掃描的類包,類包及其遞歸子包中全部的類都會被處理。
       8.4.2 Spring2.5基於註解驅動的MVC
Spring 2.5 也爲 Spring MVC 引入了註釋驅動功能。如今咱們無須讓 Controller 繼承任何接口,無需在 XML 配置文件中定義請求和 Controller 的映射關係,僅僅使用註釋就可讓一個 POJO 具備 Controller 的絕大部分功能 —— Spring MVC 框架的易用性獲得了進一步的加強。
因爲 Spring MVC Controller 必須事先是一個 Bean,因此 @Controller 註解是不可缺乏的。請看下面的代碼清單
代碼清單1
              @Controller // 將這個類標註爲 Controller
public class FooController {
            @Autowired
            private FooService fooService ;
            @RequestMapping ( "/list.do" ) //URL 請求映射
            public String[] list() {
            String[] list = fooService .getAll();
             System. out .println(list);
             return list;
            }
            @RequestMapping ( "/del.do" ) //URL 請求映射
public void del (HttpServletRequest request, HttpServletResponse response) {
                fooService .doDel(request.getParameter( "id" ));
            }
}
在代碼清單 1 中咱們經過 @ Controller 註釋將 FooController.java 標註爲一個控制器 , 而不需繼承或者實現任何類和接口,就使 FooController.java 擁有了控制器的功能。代碼清單 1 中使用了兩個連接分別訪問了不一樣的方法,在實際應用中咱們也許有另一種需求一個控制器只接受一個 URL 請求,而控制器中不一樣的方法來處理 URL 請求中攜帶的不一樣的參數,請看下面的代碼清單。
2)  一個 Controller 對應一個 URL,由請求參數決定請求處理方法
代碼清單 2
@Controller
@RequestMapping ( "/doFoo.do" ) // 指定控制器對應 URL 請求
public class FooController {
           @Autowired
           private FooService fooService ;
           //list 方法對應 URL /doFoo.do?mode=list
           @RequestMapping (params = "mode=list" )
            public String[] list() {
               String[] list = fooService .getAll();
                System. out .println(list);
                return list;
            }
           //del 方法對應 URL /doFoo.do?mode= del
           @RequestMapping (params = "mode= del " )
public void del (HttpServletRequest request,
HttpServletResponse response) {
               fooService .doDel(request.getParameter( "id" ));
            }
}
代碼清單2中知足了針對不一樣粒度程序設計的須要。咱們還能夠讓請求處理方法處理特定的 HTTP 請求如POST類型的,請看下面的代碼清單。
3)  讓請求處理方法處理特定的 HTTP 請求方法
代碼清單3
@Controller
@RequestMapping ( "/doFoo.do" ) // 指定控制器對應 URL 請求
public class FooController {
           // 只針對 POST 請求
        @RequestMapping (params = "mode=submit" ,
method = RequestMethod. POST )
           public String submit(HttpServletRequest request,
               HttpServletResponse response){
              System. out .println( " 調用 submit 方法 ." );
              return "success" ;
           }
}
方法 submit 只處理類型爲 POST URL 請求
代碼清單4
@Controller
@RequestMapping ( "/doFoo.do" ) // 指定控制器對應 URL 請求
public class FooController {
           @Autowired
           private FooService fooService ;
     
           //del 方法對應 URL /doFoo.do?mode= del &id=10
           @RequestMapping (params = "mode= del " )
            public String del ( int id) {
               fooService .doDel(id);
               return "success" ;
            }
}
當咱們發送 /doFoo.do?mode= del &id=10 URL 請求時,
Spring 不但讓 del() 方法處理這個請求,並且還將 id 請求參數在類型轉換後綁定到 del() 方法的 id 入參上。而 del() 方法的返回類型是 String ,它將被解析爲邏輯視圖的名稱。也就是說 Spring 在如何給處理方法入參自動賦值以及如何將處理方法返回值轉化爲 ModelAndView 中的過程當中存在一套潛在的規則,不熟悉這個規則就不可能很好地開發基於註解的請求處理方法,所以瞭解這個潛在規則無疑成爲理解 Spring MVC 框架基於註解功能的核心問題。代碼清單 4 還能夠寫成下面這種形式
代碼清單 5
@Controller
@RequestMapping ( "/doFoo.do" ) // 指定控制器對應 URL 請求
public class FooController {
           @Autowired
           private FooService fooService ;
     
           //del 方法對應 URL /doFoo.do?mode= del &id=10
           @RequestMapping (params = "mode= del " )
            public String del ( @RequestParam ( "id" ) int id) {
               fooService .doDel(id);
               return "success" ;
            }
}
代碼清單 5 中對 del() 請求處理方法的 id 入參標註了 @RequestParam("id") 註釋,因此它將和 id URL 參數綁定。
相關文章
相關標籤/搜索