1.1????增強(qiáng)類型擴(kuò)展
在第5章中學(xué)習(xí)Spring AOP時(shí)學(xué)習(xí)了前置增強(qiáng)和后置增強(qiáng)兩種增強(qiáng)處理肥荔。本節(jié)將學(xué)習(xí)更多的增強(qiáng)方式鸿市。
1.1.1????異常拋出增強(qiáng)
異常拋出增強(qiáng)是指當(dāng)目標(biāo)對(duì)象方法拋出異常時(shí)進(jìn)行織入操作的一種增強(qiáng)方式。通常遂填,異常拋出增強(qiáng)用來(lái)為項(xiàng)目提供統(tǒng)一的異常處理功能赡茸,具有可靈活插拔的特點(diǎn)。使用異常拋出增強(qiáng)時(shí)渡讼,需要在配置文件中使用<aop:after-throwing>標(biāo)簽進(jìn)行配置,語(yǔ)法如下耳璧。
語(yǔ)法:
<aop:config>
? ? <aop:aspect ref="增強(qiáng)方法所在的Bean">
? ? ? ? <aop:after-throwing method="增強(qiáng)處理方法"
? ? ? ? ? ? ? ? ? ? pointcut-ref="切入點(diǎn)id"? ?throwing="e"? ? />
????</aop:aspect>
</aop:config>
上述語(yǔ)法中,<aop:after-throwing>標(biāo)簽表示增強(qiáng)處理類型為異常拋出增強(qiáng)展箱。method屬性表示增強(qiáng)處理最終調(diào)用的方法旨枯,用以捕獲異常。如果需要獲取拋出的異常信息混驰,可以為增強(qiáng)方法聲明相關(guān)類型的參數(shù)攀隔,并通過(guò)throwing屬性指定該參數(shù)名稱皂贩。Spring框架會(huì)為其注入從目標(biāo)方法拋出的異常實(shí)例。根據(jù)語(yǔ)法編寫(xiě)配置文件昆汹,代碼如示例1所示明刷。
示例1
<!-- 聲明增強(qiáng)方法所在的Bean -->
<bean id="theLogger" class="aop.ErrorLogger">
<!-- 配置切面 -->
<aop:config>
? ? <!-- 定義切入點(diǎn) -->
? ? <aop:pointcut id="pointcut" expression="execution(* service.UserService.*(..))" />
? ? <!-- 引用包含增強(qiáng)方法的Bean -->
? ? <aop:aspect ref="theLogger">
? ? ? ? <!-- 將afterThrowing()方法定義為異常拋出增強(qiáng)并引用pointcut切入點(diǎn) -->
? ? ? ? <!-- 通過(guò)throwing屬性指定為名為e的參數(shù)注入異常實(shí)例 -->
? ? ? ? <aop:after-throwing method="afterThrowing"
? ? ? ? ? ? ? pointcut-ref="pointcut" throwing="e" />
? ? </aop:aspect>
</aop:config>
定義異常處理類ErrorLogger,并在類中創(chuàng)建處理異常的方法afterThrowing()满粗,如示例2所示辈末。
示例2
/**
* 定義包含增強(qiáng)方法的JavaBean
*/
public class ErrorLogger {
private static final Loggerlog = Logger.getLogger(ErrorLogger.class);
? ? public void afterThrowing(JoinPoint jp, RuntimeException e) {
log.error(jp.getSignature().getName() +" 方法發(fā)生異常:" + e);
? ? }
}
1.1.2????最終增強(qiáng)
最終增強(qiáng)是指無(wú)論目標(biāo)對(duì)象的方法正常運(yùn)行還是拋出異常,該增強(qiáng)處理都會(huì)被執(zhí)行的一種增強(qiáng)方式映皆。其與Java中finally代碼塊的作用相似挤聘,通常用于釋放資源等操作,具有可靈活插拔的特點(diǎn)捅彻。使用最終增強(qiáng)组去,需要在配置文件中使用aop:after標(biāo)簽進(jìn)行配置,語(yǔ)法如下步淹。
語(yǔ)法:
<aop:config>
? ? <aop:aspect ref="增強(qiáng)方法所在的Bean">
? ? ? ? <aop:after? ?method="增強(qiáng)處理方法"? pointcut-ref="切入點(diǎn)id"? ?/>
? ? </aop:aspect>
</aop:config>
上述語(yǔ)法中从隆,<aop:after>標(biāo)簽表示增強(qiáng)處理類型為最終增強(qiáng)。method屬性表示增強(qiáng)處理最終調(diào)用的方法缭裆。根據(jù)語(yǔ)法編寫(xiě)配置文件广料,代碼如示例3所示。
示例3
<!-- 聲明增強(qiáng)方法所在的Bean -->
<bean id="theLogger" class="aop.AfterLogger">
<!-- 配置切面 -->
<aop:config>
? ? <!-- 定義切入點(diǎn) -->
? ? <aop:pointcut id="pointcut"
? ? ? ? expression="execution(* service.UserService.*(..))" />
? ? <!-- 引用包含增強(qiáng)方法的Bean -->
? ? <aop:aspect ref="theLogger">
? ? ? ? <!-- 將afterLogger()方法定義為最終增強(qiáng)并引用pointcut切入點(diǎn) -->
? ? ? ? <aop:after method="afterLogger" pointcut-ref="pointcut"/>
? ? </aop:aspect>
</aop:config>
定義最終增強(qiáng)處理類AfterLogger幼驶,并在類中創(chuàng)建處理異常的方法afterLogger()艾杏,如示例4所示。
示例4
/**
* 定義包含增強(qiáng)方法的JavaBean
*/
public class AfterLogger {
private static final Loggerlog = Logger.getLogger(AfterLogger.class);
? ? public void afterLogger(JoinPoint jp) {
log.info(jp.getSignature().getName() +" 方法結(jié)束執(zhí)行盅藻。");
? ? }
}
1.1.3????環(huán)繞增強(qiáng)
環(huán)繞增強(qiáng)是指在目標(biāo)對(duì)象方法前后都可以進(jìn)行織入的一種增強(qiáng)處理方式购桑。在環(huán)繞增強(qiáng)處理中,可以獲取或修改目標(biāo)方法的參數(shù)氏淑、返回值勃蜘,可以對(duì)它進(jìn)行異常處理,甚至可以決定目標(biāo)方法是否被執(zhí)行假残。使用環(huán)繞增強(qiáng)缭贡,需要在配置文件中使用<aop:around>標(biāo)簽進(jìn)行配置,語(yǔ)法如下辉懒。
語(yǔ)法:
<aop:config>
? ? <aop:aspect? ?ref="增強(qiáng)方法所在的Bean">
? ? ? ? <aop:around method="增強(qiáng)處理方法"? ?pointcut-ref="切入點(diǎn)id"? ?/>
? ? </aop:aspect>
</aop:config>
上述語(yǔ)法中阳惹,<aop:around>標(biāo)簽表示增強(qiáng)處理類型為環(huán)繞增強(qiáng)。method屬性表示增強(qiáng)處理最終調(diào)用的方法眶俩。根據(jù)語(yǔ)法編寫(xiě)配置文件莹汤,代碼如示例5所示。
示例5
<!-- 聲明增強(qiáng)方法所在的Bean -->
<bean id="theLogger" class="aop.AroundLogger">
<!-- 配置切面 -->
<aop:config>
? ? <!-- 定義切入點(diǎn) -->
? ? <aop:pointcut id="pointcut"
? ? ? ? expression="execution(* service.UserService.*(..))" />
? ? <!-- 引用包含增強(qiáng)方法的Bean -->
? ? <aop:aspect ref="theLogger">
? ? ? ? <!-- 將aroundLogger()方法定義為環(huán)繞增強(qiáng)并引用pointcut切入點(diǎn) -->
? ? ? ? <aop:after method="aroundLogger" pointcut-ref="pointcut"/>
? ? </aop:aspect>
</aop:config>
定義環(huán)繞增強(qiáng)處理類AroundLogger颠印,并在類中創(chuàng)建處理異常的方法aroundLogger()纲岭,如示例6所示抹竹。
示例6
/**
* 定義包含增強(qiáng)方法的JavaBean
*/
public class AroundLogger {
private static final Loggerlog = Logger.getLogger(AroundLogger.class);
? ? public ObjectaroundLogger(ProceedingJoinPoint jp)throws Throwable {
log.info("調(diào)用 " + jp.getTarget() +" 的 " + jp.getSignature().
getName() +" 方法。方法入?yún)? " + Arrays.toString(jp.getArgs()));
? ? ? ? try {
Object result = jp.proceed(); //執(zhí)行目標(biāo)方法并獲得其返回值
? ? ? ? ? ? log.info("調(diào)用 " + jp.getTarget() +" 的 " + jp.getSignature().
getName() +" 方法止潮。方法返回值: " + result);
? ? ? ? ? ? return result;
? ? ? ? }catch (Throwable e) {
log.error(jp.getSignature().getName() +" 方法發(fā)生異常: " + e);
? ? ? ? ? ? throw e;
? ? ? ? }finally {
log.info(jp.getSignature().getName() +" 方法結(jié)束執(zhí)行窃判。");
? ? ? ? }
}
}
通過(guò)為增強(qiáng)方法聲明ProceedingJoinPoint類型的參數(shù),可以獲得連接點(diǎn)信息喇闸,方法與JoinPoint相同袄琳。ProceedingJoinPoint是JoinPoint的子接口,其不僅封裝目標(biāo)方法及其入?yún)?shù)組仅偎,還封裝了被代理的目標(biāo)對(duì)象跨蟹,通過(guò)它的proceed()方法可以調(diào)用真正的目標(biāo)方法,從而達(dá)到對(duì)連接點(diǎn)的完全控制橘沥。
1.2? ? 依賴注入方式擴(kuò)展
在第5章中同學(xué)們學(xué)習(xí)了Spring IoC通過(guò)setter方法實(shí)現(xiàn)對(duì)屬性的賦值功能窗轩,這種方式被稱為設(shè)值注入。除此之外座咆,Spring框架還提供了多種屬性注入方式痢艺,下面逐一進(jìn)行學(xué)習(xí)。
1.2.1? ? 構(gòu)造注入
構(gòu)造注入是指Spring框架通過(guò)構(gòu)造方法為屬性賦值的一種注入方式介陶。構(gòu)造注入可以在對(duì)象初始化時(shí)為屬性賦值堤舒,具有良好的時(shí)效性。使用構(gòu)造注入哺呜,需要在配置文件中使用<constructor-arg>標(biāo)簽進(jìn)行配置舌缤,語(yǔ)法如下。
語(yǔ)法:
<bean id="唯一標(biāo)識(shí)" class="類的全路徑">
? ? <constructor-arg name="參數(shù)名稱" ref="依賴對(duì)象"/ >
</bean>
上述語(yǔ)法中某残,<constructor-arg>標(biāo)簽表示使用構(gòu)造器注入的方式向當(dāng)前Bean注入依賴国撵,其內(nèi)部的ref標(biāo)簽用來(lái)配置被注入的Bean名稱。以保存用戶功能為例玻墅,根據(jù)上述語(yǔ)法編寫(xiě)配置文件介牙,代碼如示例7所示。
示例7
<!-- 定義UserDaoImpl對(duì)象澳厢,并指定id為userDao -->
<bean id="userDao" class="dao.impl.UserDaoImpl" />
<!-- 定義UserServiceImpl對(duì)象环础,并指定id為userService -->
<bean id="userService" class="service.impl.UserServiceImpl">
? ? <!-- 通過(guò)參數(shù)名稱為構(gòu)造方法注入值 -->
? ? <constructor-arg name="userDao" ref="userDao"/>
</bean>
知識(shí)擴(kuò)展:
(1)如果有多個(gè)參數(shù),可以在當(dāng)前bean標(biāo)簽下配置多個(gè)<constructor-arg>標(biāo)簽剩拢。
(2)除使用name屬性區(qū)別多個(gè)參數(shù)外线得,還可以使用<constructor-arg>標(biāo)簽中的index屬性指定參數(shù)的位置索引,位置從0開(kāi)始裸扶。
(3)<constructor-arg>標(biāo)簽提供了type屬性框都,用以標(biāo)識(shí)參數(shù)的類型。
在示例7中呵晨,把userDao以構(gòu)造注入的方式注入userService中魏保,所以在userService中應(yīng)該提供一個(gè)以u(píng)serDao為參數(shù)的構(gòu)造方法,如示例8所示摸屠。
示例8
/**
* 用戶功能業(yè)務(wù)層實(shí)現(xiàn)
*/
public class UserServiceImplimplements UserService {
//只聲明接口類型引用
? ? private UserDaodao;
? ? //無(wú)參構(gòu)造
? ? public UserServiceImpl() {? }
//用于為dao屬性賦值的構(gòu)造方法
? ? public UserServiceImpl(UserDao dao) {
this.dao = dao;
? ? }
/**
? ? * 保存用戶
? ? * @param user
? ? */
? ? public void save(User user) {
//保存用戶信息
? ? ? ? dao.saveUser(user);
? ? }
}
構(gòu)造注入方式具有良好的時(shí)效性谓罗,在對(duì)象實(shí)例化時(shí)就能得到所依賴的對(duì)象,便于在對(duì)象初始化方法中使用所依賴的對(duì)象季二。但是檩咱,其受限于方法重載的形式,使用靈活性不足胯舷。相比而言刻蚯,設(shè)值注入使用靈活,但時(shí)效性不足桑嘶,并且大量的set()方法增加了類的復(fù)雜性炊汹。Spring框架并不傾向于某種注入方式,用戶應(yīng)該根據(jù)實(shí)際情況進(jìn)行合理的選擇逃顶。
經(jīng)驗(yàn):
Spring框架提供的注入方式不止這兩種讨便,只是這兩種方式用得較普遍,有興趣的同學(xué)可以通過(guò)Spring框架的開(kāi)發(fā)手冊(cè)了解其他注入方式以政。
1.2.2? ? p命名空間注入
在第5章學(xué)習(xí)Spring AOP時(shí)霸褒,同學(xué)們學(xué)習(xí)了使用Spring配置文件中aop命名空間下的相關(guān)標(biāo)簽實(shí)現(xiàn)織入切面的功能,除aop外盈蛮,Spring提供的命名空間還有很多废菱。Spring配置文件從2.0版本開(kāi)始采用schema形式,schema的配置方案為許多領(lǐng)域提供了簡(jiǎn)化的配置方法抖誉,極大地簡(jiǎn)化了配置文件的復(fù)雜度和工作量殊轴。本節(jié)將學(xué)習(xí)和使用p命名空間,體驗(yàn)它帶來(lái)的便捷之處寸五。
使用Spring配置文件做屬性注入時(shí)梳凛,需要用到property標(biāo)簽,如示例9所示梳杏。
示例9
<bean id="user" class="entity.User">
? ? <property name="userName">
? ? ? ? <value>諸葛亮
? ? <property name="age">
? ? ? ? <value>27
? ? <property name="evaluate">
? ? ? ? <value>鞠躬盡瘁韧拒,死而后已
<bean id="userDao" class="dao.impl.UserDaoImpl" />
<bean id="userService" class="service.impl.UserServiceImpl">
? ? <property name="dao">
? ? ? ? <ref bean="userDao" />
</bean>
p命名空間的特點(diǎn)是使用屬性而不是子元素的形式配置Bean的屬性,從而簡(jiǎn)化了Bean的配置十性。p標(biāo)簽的語(yǔ)法非常簡(jiǎn)單叛溢,如下所示。
語(yǔ)法:
<bean id="唯一標(biāo)識(shí)" class="類的全路徑"
? ? p:? ?"屬性 1"? ="注入的值"? ? p:? ? "屬性 2"? ?="注入的值"/>
<bean id="唯一標(biāo)識(shí)" class="類的全路徑"
? ? p:dao-ref="注入的Bean"? ?/>
使用p標(biāo)簽注入屬性時(shí)劲适,如果有多個(gè)屬性楷掉,寫(xiě)多個(gè)p標(biāo)簽即可。
1.2.3? ? 不同數(shù)據(jù)類型的注入
Java方法中的參數(shù)類型包括基本類型霞势、集合數(shù)組類型烹植、引用類型等斑鸦,本節(jié)將針對(duì)以上類型參數(shù)在Spring配置文件中的配置方式進(jìn)行擴(kuò)展學(xué)習(xí)。創(chuàng)建一個(gè)包含這些參數(shù)的實(shí)體類用于測(cè)試草雕,關(guān)鍵代碼如示例10所示巷屿。
示例10
public class TestEntity {
private StringspecialCharacter1;? ? ? ? ? ? ? //特殊字符值1
? ? private StringspecialCharacter2;? ? ? ? ? //特殊字符值2
? ? private Useruser;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //引用外部對(duì)象
? ? private UserinnerBean;? ? ? ? ? ? ? ? ? ? ? ? ?//JavaBean類型
? ? private Listlist;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//List類型
? ? private String[]array;? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//數(shù)組類型
? ? private Setset;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//Set類型
? ? private Mapmap;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//Map類型
? ? private Propertiesprops;? ? ? ? ? ? ? ? ? ? ? ? //Properties類型
? ? private StringemptyValue;? ? ? ? ? ? ? ? ? ? ?//注入空字符串值
? ? private StringnullValue ="init value";? ? ? //注入null值
? ? ······? //省略getter、setter方法
}
示例11中省略標(biāo)準(zhǔn)的getter墩虹、setter方法嘱巾。
1.3? ? 使用注解實(shí)現(xiàn)Spring IoC
第5章中已經(jīng)學(xué)習(xí)了使用XML配置文件的方式實(shí)現(xiàn)Spring IoC相關(guān)的內(nèi)容,但是當(dāng)項(xiàng)目越來(lái)越龐大時(shí)诫钓,使用這種方式需要在配置文件中編寫(xiě)大量的代碼旬昭。Spring從2.0版本開(kāi)始引入注解的配置方式來(lái)解決這個(gè)問(wèn)題。
1.3.1? ? 使用注解方式實(shí)現(xiàn)用戶保存功能
高版本的Spring在使用注解實(shí)現(xiàn)IoC時(shí)菌湃,需要依賴spring-aop.jar问拘。所以,在項(xiàng)目lib文件夾下添加spring-aop-5.2.2.RELEASE.jar慢味。
1.3.2? ? 使用Java標(biāo)準(zhǔn)注解完成裝配
Spring框架是一個(gè)超級(jí)黏合平臺(tái)场梆,它除本身提供@Autowired注解實(shí)現(xiàn)Bean的裝配功能外,還支持同樣可以實(shí)現(xiàn)該功能的@Resource注解纯路。@Resource注解是在Java規(guī)范提案——JSR-250中定義的或油。
說(shuō)明:JSR全稱是Java Specification Requests,即Java規(guī)范提案驰唬。Java的版本和功能在不斷地更新和擴(kuò)展顶岸,JSR就是用來(lái)規(guī)范這些功能和接口的標(biāo)準(zhǔn),其已經(jīng)成為Java業(yè)界的一個(gè)重要標(biāo)準(zhǔn)叫编。
@Resource注解的使用方式如示例11所示辖佣。
示例11
/**
* 用戶模塊業(yè)務(wù)層實(shí)現(xiàn)
*/
@Service("userService")
public class UserServiceImplimplements UserService {
@Resource
? ? private UserDaodao;
? ? ······? //省略業(yè)務(wù)方法
}
1.4? ? 使用注解實(shí)現(xiàn)Spring AOP
使用注解實(shí)現(xiàn)Spring AOP需要用到AspectJ框架。AspectJ本身就是AOP的框架搓逾,它擴(kuò)展了Java語(yǔ)言卷谈,定義了AOP語(yǔ)法,且自帶編譯器霞篡。此編譯器可以將代碼編譯成遵守字節(jié)編碼規(guī)范的Class文件世蔗,在編譯期間即可實(shí)現(xiàn)代碼的織入功能。AspectJ5中提供了一個(gè)非常重要的注解——@AspectJ朗兵。該注解需要JDK5.0注解技術(shù)的支持和AspectJ切入點(diǎn)表達(dá)式語(yǔ)言描述切面污淋,因此,使用@AspectJ時(shí)余掖,需要保證JDK是5.0或其以上版本寸爆。此外,因?yàn)镴ava的反射機(jī)制無(wú)法獲取方法參數(shù)名,Spring還需要利用輕量級(jí)的字節(jié)碼處理框架asm(已集成在Spring Core模塊中)處理@AspectJ中所描述的方法參數(shù)名赁豆。
1.4.1? ? 使用注解方式標(biāo)注切面
Spring框架通過(guò)集成AspectJ框架實(shí)現(xiàn)了以注解的方式定義切面仅醇,這使配置文件中的代碼大大減少。相對(duì)于使用配置文件實(shí)現(xiàn)AOP而言歌憨,注解的方式更加清晰簡(jiǎn)潔着憨。下面通過(guò)使用注解方式實(shí)現(xiàn)對(duì)業(yè)務(wù)方法前后增加日志的功能學(xué)習(xí)AspectJ框架墩衙。以用戶保存功能為例务嫡,業(yè)務(wù)方法的關(guān)鍵代碼如示例12所示。
示例12
/**
* 用戶業(yè)務(wù)類漆改,實(shí)現(xiàn)對(duì)User功能的業(yè)務(wù)管理
*/
@Service("userService")
public class UserServiceImplimplements UserService {
@Autowired
private UserDao dao;
? ? /**
? ? * 保存用戶
? ? * @param user
? ? */
? ? public void save(User user) {
//調(diào)用用戶DAO的方法保存用戶信息
? ? dao.saveUser(user);
? ? }
}
創(chuàng)建切面類UserServiceLogger心铃,并創(chuàng)建前后增強(qiáng)的方法before()及afterReturning()方法。關(guān)鍵代碼如示例13所示挫剑。
示例13
import java.util.Arrays;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.AfterReturning;
/**
* 使用注解定義切面
*/
@Aspect
public class UserServiceLogger {
private static final Loggerlog = Logger.getLogger(UserServiceLogger.class);
? ? /**
? ? * 前置增強(qiáng)
? ? * @param jp
? ? */
? ? @Before("execution(* service.UserService.*(..))")
public void before(JoinPoint jp) {
log.info("調(diào)用 " + jp.getTarget() +" 的 " + jp.getSignature()
.getName() +" 方法去扣。方法入?yún)? " + Arrays.toString(jp.getArgs()));
? ? }
/**
? ? * 后置增強(qiáng)
? ? * @param jp
? ? * @param returnValue
? ? */
? ? @AfterReturning(pointcut ="execution(* service.UserService.*(..))",
? ? ? ? ? returning ="returnValue")
public void afterReturning(JoinPoint jp, Object returnValue) {
log.info("調(diào)用 " + jp.getTarget() +" 的 " + jp.getSignature()
.getName() +" 方法。方法返回值: " + returnValue);
? ? }
}
在示例13中樊破,分別使用了@Aspect愉棱、@Before和@AfterReturning注解。其中哲戚,@Aspect注解的作用是將UserServiceLogger類定義為切面奔滑;@Before注解是作用是將before()方法定義為前置增強(qiáng);@AfterReturning注解的作用是將afterReturning()方法定義為后置增強(qiáng)顺少。增強(qiáng)方法中使用了JoinPoint類型的參數(shù)朋其,以獲得當(dāng)前連接點(diǎn)的信息。對(duì)于后置增強(qiáng)脆炎,還可以定義一個(gè)參數(shù)用于接收目標(biāo)方法的返回值梅猿。需要注意的是,必須在@AfterReturning注解中通過(guò)returning屬性指定該參數(shù)的名稱秒裕,Spring框架才會(huì)將目標(biāo)方法發(fā)返回值賦值給指定名稱的參數(shù)袱蚓。定義好切面之后,還需要對(duì)配置文件做一些修改才能完成織入工作几蜻。配置文件信息如示例14所示喇潘。
示例14
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
? ? ? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
? ? ? xmlns:context="http://www.springframework.org/schema/context"
? ? ? xmlns:aop="http://www.springframework.org/schema/aop"
? ? ? xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
? ? ? http://www.springframework.org/schema/aop/spring-aop.xsd">
? ? ? <!-- 注解掃描 -->
? ? ? <context:component-scan base-package="service,dao" />
? ? ? <bean class="aop.UserServiceLogger">
? ? ? <aop:aspectj-autoproxy />
</beans>
配置文件中的內(nèi)容非簡(jiǎn)單,首先需要導(dǎo)入aop命名空間入蛆,然后將定義好的切面注冊(cè)到Spring容器中响蓉,最后只需在配置文件中添加<aop:aspectj-autoproxy />標(biāo)簽,這些步驟完成之后就可以啟用對(duì)于@AspectJ注解的支持了哨毁,Spring框架將自動(dòng)為匹配的Bean創(chuàng)建代理枫甲。
注意:
如果不需要被其他Bean引用,可以不指定id屬性。
1.4.2? ? 使用注解定義其他類型的增強(qiáng)
依然以保存用戶功能為例想幻,分別學(xué)習(xí)通過(guò)注解方式實(shí)現(xiàn)異常拋出類增強(qiáng)粱栖、最終增強(qiáng)和環(huán)繞增強(qiáng)功能。對(duì)于異常拋出增強(qiáng)的注解是@AfterThrowing脏毯,增強(qiáng)代碼如示例15所示闹究。
示例15
import org.apache.log4j.Logger;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
/**
* 使用注解實(shí)現(xiàn)異常拋出增強(qiáng)
*/
@Aspect
public class ErrorLogger {
private static final Loggerlog = Logger.getLogger(ErrorLogger.class);
? ? @AfterThrowing(pointcut ="execution(* service.UserService.*(..))"
? ? ? ? ? ? , throwing ="e")
public void afterThrowing(JoinPoint jp, RuntimeException e) {
log.error(jp.getSignature().getName() +" 方法拋出異常: " + e);
? ? }
}
示例15中,使用@AfterThrowing注解可以定義異常拋出增強(qiáng)食店。如果需要獲取拋出的異常信息渣淤,可以為增強(qiáng)方法聲明相關(guān)類型的參數(shù),并通過(guò)@AfterThrowing注解的throwing屬性指定該參數(shù)名稱吉嫩,Spring框架會(huì)為其注入業(yè)務(wù)方法拋出的異常實(shí)例价认。
總結(jié)
◎? ? Spring框架提供了設(shè)值注入、構(gòu)造注入等依賴注入方式自娩。
◎? ? 在Spring配置文件中使用<context:component-scan>掃描包含注解的類用踩,完成初始化。
◎? ? 用來(lái)定義Bean組件的注解包括@Component忙迁、@Repository脐彩、@Service、@Controller姊扔。
◎? ? Bean組件的裝配可以通過(guò)@Autowired惠奸、@Qualifier或@Resource實(shí)現(xiàn)。
◎? ? 使用p命名空間可以簡(jiǎn)化屬性注入的配置旱眯。
◎? ? 通過(guò)在配置文件中添加<aop:aspectj-autoproxy>晨川,就可以啟用對(duì)@AspectJ注解的支持。
◎? ? Spring框架提供的增強(qiáng)處理方式主要包括前置增強(qiáng)删豺、后置增強(qiáng)共虑、異常拋出增強(qiáng)、環(huán)繞增強(qiáng)呀页、最終增強(qiáng)等妈拌。