Spring框架深入學(xué)習(xí)

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)等妈拌。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蓬蝶,隨后出現(xiàn)的幾起案子尘分,更是在濱河造成了極大的恐慌,老刑警劉巖丸氛,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件培愁,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡缓窜,警方通過(guò)查閱死者的電腦和手機(jī)定续,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)谍咆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人私股,你說(shuō)我怎么就攤上這事摹察。” “怎么了倡鲸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵供嚎,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我峭状,道長(zhǎng)克滴,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任宁炫,我火速辦了婚禮偿曙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘羔巢。我一直安慰自己,他們只是感情好罩阵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布竿秆。 她就那樣靜靜地躺著,像睡著了一般稿壁。 火紅的嫁衣襯著肌膚如雪幽钢。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,598評(píng)論 1 305
  • 那天傅是,我揣著相機(jī)與錄音匪燕,去河邊找鬼。 笑死喧笔,一個(gè)胖子當(dāng)著我的面吹牛帽驯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播书闸,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼尼变,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了浆劲?” 一聲冷哼從身側(cè)響起嫌术,我...
    開(kāi)封第一講書(shū)人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎牌借,沒(méi)想到半個(gè)月后度气,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡膨报,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年磷籍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了哲虾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡择示,死狀恐怖束凑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情栅盲,我是刑警寧澤汪诉,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站谈秫,受9級(jí)特大地震影響扒寄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拟烫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一该编、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧硕淑,春花似錦课竣、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至拇囊,卻和暖如春迂曲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背寥袭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工路捧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人传黄。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓杰扫,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親尝江。 傳聞我的和親對(duì)象是個(gè)殘疾皇子涉波,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容