在傳統Spring架構中配置POJOs的基本操作有兩種:裝配和依賴(lài)注入。下面的例子中裝配了兩個(gè)POJO,同時(shí)指定了兩個(gè)對象之間的依賴(lài)關(guān)系。 例1:實(shí)現一個(gè)簡(jiǎn)單類(lèi)(Main.java)
package test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main {private BasicService service;public BasicService getService() {return service;}public void setService(BasicService service) {this.service = service;}public void print() {service.print();}public static void main(String[] args) {String[] locations = { "beans.xml" };ApplicationContext ctx =new ClassPathXmlApplicationContext(locations);Main main = (Main)ctx.getBean("main");main.print();}}
例2:基本服務(wù)類(lèi)(BasicService.java)
package test;public class BasicService {public void print() {System.out.println("success");}}例3:在配置文件中的聲明(beans.xml)
<?xml version="1.0" encoding="UTF-8" ?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><bean id="main" class="test.Main"><property name="service"><ref bean="service" /></property></bean><bean id="service" class="test.BasicService"></bean></beans>對于傳統裝配方式而言,最大的問(wèn)題在于規模逐漸變大的項目中將會(huì )有越來(lái)越多的POJOs需要在XML文件中設置。這樣一方面無(wú)法迅速定位指定的對象,另一方面難于掌握對象之間的依賴(lài)關(guān)系。得益于Java5.0的注釋功能,到Spring2.5之后,其架構中提供了一系列注釋?zhuān)糜诤?jiǎn)化裝配POJOs的過(guò)程。這種方式大大降低了傳統XML配置文件的管理成本,讓我們來(lái)看一下將上面的例子修改成注釋方式的樣子。
例4:注釋版Main.java
package test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.stereotype.Component;@Componentpublic class Main {@Autowiredprivate BasicService service;public void print() {service.print();}public static void main(String[] args) {String[] locations = { "beans.xml" };ApplicationContext ctx =new ClassPathXmlApplicationContext(locations);Main main = (Main) ctx.getBean("main");main.print();}}例5:注釋版BasicService.java
package test;import org.springframework.stereotype.Component;@Component("service")public class BasicService {public void print() {System.out.println("success");}}例6:注釋版beans.xml
<?xml version="1.0" encoding="UTF-8" ?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"><context:component-scan base-package="test"></context:component-scan></beans>對于Spring架構中的注釋功能而言,我們需要掌握哪些要點(diǎn)呢?
所有的Spring注釋中最重要的莫過(guò)于@Component,其作用就是在Spring容器中裝配一個(gè)POJO對象。@Component作用于類(lèi)聲明之前,其用法有兩種:
@Component
@Component(“Spring容器內的對象名”)
第一種注釋方法會(huì )在Spring容器中實(shí)例化一個(gè)以類(lèi)名的首字母為小寫(xiě)命名的POJO對象。如例4中對Main類(lèi)的注釋將會(huì )在Spring容器中實(shí)例化一個(gè)名為main的POJO對象:
package test;...@Componentpublic class Main {...public static void main(String[] args) {String[] locations = { "beans.xml" };ApplicationContext ctx =new ClassPathXmlApplicationContext(locations);Main main = (Main)ctx.getBean("main");main.print();}}當然,如果不滿(mǎn)意類(lèi)名首字母小寫(xiě)的命名規則,第二種注釋方法允許我們自定義POJO的名稱(chēng)。如例5中對BasicService的注釋?zhuān)?/p>
package test;...@Component("service")public class BasicService {...} 通常情況下保存在Spring容器中的POJOs有兩種形態(tài):singleton與prototype。@Component與@Scope配合即可指定不同的形態(tài)。@Scope緊隨@Component之后,其用法如下:@Scope(“singleton”)
@Scope(“prototype”)
我們可以用下面的例子測試prototype或singleton形態(tài)的POJOs:
package test;import org.springframework.context.ApplicationContext;import org.springframework.context.annotation.Scope;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.stereotype.Component;@Component@Scope("prototype")public class Main {public void print() {System.out.println(toString());}public static void main(String[] args) {String[] locations = { "beans.xml" };ApplicationContext ctx =new ClassPathXmlApplicationContext(locations);Main main1 = (Main) ctx.getBean("main");main1.print();Main main2 = (Main) ctx.getBean("main");main2.print();System.out.println(main1 != main2);}} 與@Component對應,@Autowired用于Spring容器中POJOs之間的依賴(lài)注入操作,使用該注釋的最大好處是不必提供傳統JavaBeans的setter方法。如例4與例1相比,私有的成員變量service沒(méi)有提供settter方法,僅靠@Autowired就可以注入與之對應的service對象。@Autowired作用于類(lèi)的成員變量、類(lèi)的setter方法或類(lèi)的構造函數。其用法有以下兩種:
@Autowired
@Autowired(required = false)
獨立的@Autowired以byType方式進(jìn)行依賴(lài)注入。如例4中對service成員變量的注釋?zhuān)?/p>
package test;...@Componentpublic class Main {@Autowiredprivate BasicService service;...}只要在Spring容器中存在一個(gè)(只有一個(gè))類(lèi)型為test.BasicService的POJO時(shí),byType方式就可以正確注入。否則將拋出異常,如果不希望強制注入不存在的對象,可以使用第二種方式進(jìn)行注釋。如:
package test;...@Componentpublic class Main {@Autowired(required = false)private BasicService service;...} 當Spring容器中不存在相同類(lèi)型的POJO對象時(shí),成員變量service將不進(jìn)行依賴(lài)注入操作。但是如果Spring容器中存在多個(gè)相同類(lèi)型但名字不同的POJOs時(shí),又該如何處理呢?@Autowired與@Qualifier配合使用時(shí)將會(huì )以byName方式進(jìn)行依賴(lài)注入。以byName方式進(jìn)行依賴(lài)注入正是為了避免相同類(lèi)型的不同POJOs在注入時(shí)發(fā)生沖突。@Qualifier作用于類(lèi)的成員變量、類(lèi)的setter方法中的參數或類(lèi)的構造函數中的參數,@Qualifier的用法如下:
@Qualifier(“Spring容器內的對象名”)
如將例4的內容修改一下。如下例:
package test;...@Componentpublic class Main {private BasicService service;@Autowiredpublic Main(@Qualifier("basicService")BasicService service) {this.service = service;}...} 此時(shí)的成員變量只會(huì )從Spring容器中查找名字為service的POJO進(jìn)行注入。當然如果定位到的POJO類(lèi)型不符合要求或者相同名字的POJO在Spring容器中不存在,上述方法仍然會(huì )拋出異常。此時(shí)如有必要就需要@Autowired(required=false)來(lái)幫忙了。package test;...@Componentpublic class Main {private BasicService service;@Autowiredpublic Main(@Qualifier("basicService")BasicService service) {this.service = service;}...} 與成員變量的依賴(lài)注入功能相似,@Autowired同樣可以通過(guò)構造函數或setter方法進(jìn)行注入。如:
package test;...@Componentpublic class Main {private BasicService service;@Autowiredpublic Main(@Qualifier("basicService")BasicService service) {this.service = service;}...} 上述代碼中指明了在構造函數中進(jìn)行依賴(lài)注入,同時(shí)指定參數service只接收名字為basicService的POJO。
為了使用Spring架構中的注釋功能,例6所示的內容是最小的配置要求。請注意XML根標簽屬性中與傳統Spring配置文件的不同:
傳統配置文件
<?xml version="1.0" encoding="UTF-8" ?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><bean id="main" class="test.Main"><property name="service"><ref bean="service" /></property></bean><bean id="service" class="test.BasicService"></bean></beans>
注釋用配置文件
<?xml version="1.0" encoding="UTF-8" ?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"><context:component-scan base-package="test"></context:component-scan></beans>與傳統Spring配置文件相比,最大的不同在于配置文件中不必使用bean標簽來(lái)裝配已經(jīng)使用了注釋的POJOs,配置文件的內容將變得簡(jiǎn)潔明了。
其中標簽<context:component-scan/>的作用有兩點(diǎn):
1. 允許使用Spring架構中的所有注釋功能,包括上述所有注釋?zhuān)?br>2. 指定了需要掃描的類(lèi)包,類(lèi)包及其遞歸子包中所有的類(lèi)都會(huì )被處理。
總之,Spring2.5的注釋功能可以極大的提高開(kāi)發(fā)效率,使大量的維護工作得以簡(jiǎn)化。我們沒(méi)有理由不掌握這樣的技術(shù)!
聯(lián)系客服