寫在前面:
好長時間沒有寫部落格了,主要是最近一直忙于工作上面的事情沒有研究什麼新的東西,也沒有什麼寫的,最近應一個朋友的邀請一起開發一套教材,我才有開始對Spring研究起來,今天把寫的其中一部分貼出來與大家共享.如有不足之處請多多指教.
Spring2.5注釋驅動
<b>8.4.1</b><b> Spring2.5</b><b>注釋驅動</b>
注釋文法越來越多的被業界所使用,并且注釋配置相對于 XML 配置具有很多的優勢:它可以充分利用 Java 的反射機制擷取類結構資訊,這些資訊可以有效減少配置的工作。注釋和 Java 代碼位于一個檔案中,而 XML 配置采用獨立的配置檔案,大多數配置資訊在程式開發完成後都不會調整,如果配置資訊和 Java 代碼放在一起,有助于增強程式的内聚性。而采用獨立的 XML 配置檔案,程式員在編寫一個功能時,往往需要在程式檔案和配置檔案中不停切換,這種思維上的不連貫會降低開發效率。是以在很多情況下,注釋配置比 XML 配置更受歡迎,注釋配置有進一步流行的趨勢。Spring 2.5 的一大增強就是引入了很多注釋類,現在您已經可以使用注釋配置完成大部分XML 配置的功能。
在使用注釋配置之前,先來回顧一下傳統上是如何配置 Bean 并完成 Bean 之間依賴關系的建立。
代碼清單1 Foo.java Foo對象有一個String類型的name屬性.
<b>package</b> com.tony.test;
<b>public</b> <b>class</b> Foo {
<b>private</b> String name;
<b>public</b> String toStirng(){
<b>return</b> "Foo Name is :" + <b>this</b>.name;
}
<b>Set</b><b>和</b><b>get</b><b>方法</b>
}
代碼清單2 Bar.java Bar對象有一個String類型的add屬性.
<b>package</b> com.tony.test;
<b>public</b> <b>class</b> Bar {
<b>private</b> String add;
<b>return</b> "Bar Add is :" + <b>this</b>.add;
代碼清單3 Main.java Main對象有兩個屬性分别是Foo和Bar
<b>public</b> <b>class</b> Main {
<b>private</b> Foo foo;
<b>private</b> Bar bar;
<b>public</b> String toString(){
<b>return</b> "Main : [" + <b>this</b>.foo.toStirng() +" "+ <b>this</b>.bar.toStirng() + "]";
代碼清單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 id="bar" class="com.tony.test.Bar">
<property name="add" value="Bar"></property>
</bean>
代碼清單 5 Test.java Test類用于初始化Spring容器并獲得main對象
<b>import</b> org.springframework.context.ApplicationContext;
<b>import</b> org.springframework.context.support.
ClassPathXmlApplicationContext;
<b>public</b> <b>class</b> Test {
<b>public</b> <b>static</b> <b>void</b> main(String[] args) {
String[] locations = {"spring-config-beans.xml"};
ApplicationContext ctx = <b>new</b> ClassPathXmlApplicationContext(locations);
Main main = (Main) ctx.getBean("main");
System.out.println(main);
}
運作Test類控制台輸出以下資訊:
Main : [Foo Name is :Foo Bar Add is :Bar]
這說明Spring已經完成了Bean的建立和裝配工作。
<b>1)</b><b>使用 @Autowired </b><b>注釋</b>
Spring 2.5 引入了 @Autowired 注釋,它可以對類成員變量、方法及構造函數進行标注,完成自動裝配的工作。下面我們來看一下使用 @Autowired 進行成員變量自動注入的代碼:
代碼清單6使用 @Autowired 注釋的 Main.java,此時可以将Main.java類中的set和get方法删除
<b>import</b> org.springframework.beans.factory.annotation.Autowired;
@Autowired
<b>private</b> Foo foo;
<b>private</b> Bar bar;
<b>public</b> String toString(){
}
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>
當 Spring 容器啟動時,AutowiredAnnotationBeanPostProcessor 将掃描 Spring 容器中所有 Bean,當發現 Bean 中擁有 @Autowired 注釋時就找到和其比對(預設按類型比對)的 Bean,并将其注入。
<b>2)</b><b>使用@Qualifier </b><b>注釋</b>
Spring 允許我們通過 @Qualifier 注釋指定注入 Bean 的名稱,這樣就不會産生注入錯誤了,請看下面代碼清單:
代碼清單8 修改Main.java類中的foo屬性注釋增加注釋@Qualifier("foo1")
@Qualifier("foo1")
代碼清單9 在配置檔案中增加id為foo2 Bean定義
<bean id="foo1" class="com.tony.test.Foo">
<property name="name" value="Foo1"></property>
<bean id="foo2" class="com.tony.test.Foo">
<property name="name" value="Foo2"></property>
運作Test.java控制台輸出如下資訊:
Main : [Foo Name is :Foo1 Bar Add is :Bar]
證明Spring容器成功将foo1注入進main類中
<b>3)</b><b>使用 </b><b><context:annotation-config/> </b><b>簡化配置</b>
Spring 2.1 添加了一個新的 context 的 Schema 命名空間,該命名空間對注釋驅動、屬性檔案引入、加載期織入等功能提供了便捷的配置。我們知道注釋本身是不會做任何事情的,它僅提供中繼資料資訊。要使中繼資料資訊真正起作用,必須讓負責處理這些中繼資料的處理器工作起來。而我們前面所介紹的 AutowiredAnnotationBeanPostProcessor 就是處理這些注釋中繼資料的處理器。但是直接在 Spring 配置檔案中定義這些 Bean 顯得比較笨拙。Spring 為我們提供了一種友善的注冊這些 BeanPostProcessor 的方式,這就是 <context:annotation-config/>。請看下面的代碼清單:
代碼清單10
<context:annotation-config/>
代碼清單中将
替換成為<context:annotation-config/>
<context:annotationconfig/> 将隐式地向 Spring 容器注冊 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor 以及 equiredAnnotationBeanPostProcessor 這 4 個 BeanPostProcessor。
<b>4) </b><b>使用 @Component</b>
雖然我們可以通過 @Autowired在 Bean 類中使用自動注入功能,但是 Bean 還是在 XML 檔案中通過 <bean> 進行定義,也就是說,在 XML 配置檔案中定義 Bean,通過 @Autowired 為 Bean 的成員變量、方法入參或構造函數入參提供自動注入的功能。能否也通過注釋定義 Bean,從 XML 配置檔案中完全移除 Bean 定義的配置呢?答案是肯定的,我們通過 Spring 2.5 提供的 @Component 注釋就可以達到這個目标。請看下面的代碼清單:
代碼清單11 Foo.java
@Component
<b>private</b> String name = "Foo's name.";
<b>public</b> String toStirng(){
<b>return</b> "Foo Name is :" + <b>this</b>.name;
在類的開始位置使用@Component注釋,标明此類是一個Bean
代碼清單12 Main.java
@Component("main")
<b>private</b> Bar bar;
<b>……</b>
@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 屬性指定了需要掃描的類包,類包及其遞歸子包中所有的類都會被處理。
<b>8.4.2</b><b> Spring2.5</b><b>基于注解驅動的MVC</b>
Spring 2.5 也為 Spring MVC 引入了注釋驅動功能。現在我們無須讓 Controller 繼承任何接口,無需在 XML配置檔案中定義請求和 Controller 的映射關系,僅僅使用注釋就可以讓一個 POJO 具有 Controller 的絕大部分功能 —— Spring MVC 架構的易用性得到了進一步的增強。
由于 Spring MVC 的 Controller 必須事先是一個 Bean,是以 @Controller 注解是不可缺少的。請看下面的代碼清單
代碼清單1
@Controller //将這個類标注為Controller
<b>public</b> <b>class</b> FooController {
@Autowired
<b>private</b> FooService fooService;
@RequestMapping("/list.do") //URL請求映射
<b>public</b> String[] list() {
String[] list = fooService.getAll();
System.out.println(list);
<b>return</b> list;
@RequestMapping("/del.do") //URL請求映射
<b>public</b> <b>void</b> del(HttpServletRequest request, HttpServletResponse response) {
fooService.doDel(request.getParameter("id"));
在代碼清單1中我們通過@Controller注釋将FooController.java 标注為一個控制器,而不需繼承或者實作任何類和接口,就使FooController.java擁有了控制器的功能。代碼清單1中使用了兩個連結分别通路了不同的方法,在實際應用中我們也許有另外一種需求一個控制器隻接受一個URL請求,而控制器中不同的方法來處理URL請求中攜帶的不同的參數,請看下面的代碼清單。
<b>2) </b><b>一個</b><b> </b><b>Controller</b><b> </b><b>對應一個</b><b> </b><b>URL</b><b>,由請求參數決定請求處理方法</b><b></b>
代碼清單2
@Controller
@RequestMapping("/doFoo.do")// 指定控制器對應URL請求
<b>private</b> FooService fooService;
//list方法對應URL /doFoo.do?mode=list
@RequestMapping(params = "mode=list")
String[] list = fooService.getAll();
System.out.println(list);
<b>return</b> list;
//del方法對應URL /doFoo.do?mode=del
@RequestMapping(params = "mode=del")
<b>public</b> <b>void</b> del(HttpServletRequest request,
HttpServletResponse response) {
fooService.doDel(request.getParameter("id"));
代碼清單2中滿足了針對不同粒度程式設計的需要。我們還可以讓請求處理方法處理特定的 HTTP 請求如POST類型的,請看下面的代碼清單。
<b>3) </b><b>讓請求處理方法處理特定的</b><b> HTTP </b><b>請求方法</b><b></b>
代碼清單3
//隻針對POST請求
@RequestMapping(params = "mode=submit",
method = RequestMethod.POST)
<b>public</b> String submit(HttpServletRequest request,
HttpServletResponse response){
System.out.println("調用 submit 方法.");
<b>return</b> "success";
方法submit隻處理類型為POST的URL請求
代碼清單4
//del方法對應URL /doFoo.do?mode=del&id=10
<b>public</b> String del(<b>int</b> id) {
fooService.doDel(id);
<b>return</b> "success";
當我們發送 /doFoo.do?mode=del&id=10 的 URL 請求時,
Spring 不但讓 del() 方法處理這個請求,而且還将 id 請求參數在類型轉換後綁定到 del() 方法的 id 入參上。而 del() 方法的傳回類型是 String,它将被解析為邏輯視圖的名稱。也就是說 Spring 在如何給處理方法入參自動指派以及如何将處理方法傳回值轉化為ModelAndView 中的過程中存在一套潛在的規則,不熟悉這個規則就不可能很好地開發基于注解的請求處理方法,是以了解這個潛在規則無疑成為了解 Spring MVC 架構基于注解功能的核心問題。代碼清單4還可以寫成下面這種形式
代碼清單5
<b>public</b> String del(@RequestParam("id")<b>int</b> id) {
代碼清單5中對 del() 請求處理方法的 id 入參标注了 @RequestParam("id") 注釋,是以它将和 id 的 URL 參數綁定。
我的其它Spring文章,也許會對您有幫助
<a href="http://tonyaction.blog.51cto.com/227462/84008" target="_blank">Spring的任務排程和郵件發送</a>
<a href="http://tonyaction.blog.51cto.com/227462/84178" target="_blank">Spring應用的單元測試</a>
<a href="http://tonyaction.blog.51cto.com/227462/84724" target="_blank">Spring的資料庫支援</a>
<a href="http://tonyaction.blog.51cto.com/227462/84893" target="_blank">Spring的MVC架構</a>
<a href="http://tonyaction.blog.51cto.com/227462/85159" target="_blank">Spring的IoC容器</a>
<a href="http://tonyaction.blog.51cto.com/227462/85504" target="_blank">Spring對AOP的支援</a>
<a href="http://tonyaction.blog.51cto.com/227462/83874" target="_blank">Spring2.5注釋驅動與基于注釋的MVC</a>
本文轉自 tony_action 51CTO部落格,原文連結:http://blog.51cto.com/tonyaction/83874,如需轉載請自行聯系原作者