AOP筆記2-spring AOP API
Spring AOP隻實作了針對方法調用的攔截及增強,在j2ee應用中,攔截到方法級的操作已經足夠。spring AOP讓Spring支援聲明式事務。為了使用spring AOP,首先要了解它的API結構
AOP聯盟API
一套用于規範AOP實作的底層API,String的AOP架構也是直接以這些API為基礎建構的。
Aop包:定義了增強(Advice)接口和AOP運作時異常AspectException
Intercept包:攔截器包,規範了連接配接點(join point)及增強(advice)的類型
Instrument和reflect包:切面與應用子產品如何內建在一起
切入點(point cut):即要在哪裡切入代碼。
Spring使用Pointcut接口表示切入點,并預定義了幾個切入點實作類:
(1)NameMathMethodPointcut:方法名稱比對切入點,它的mappedname和 mappedNames屬性表示比對的方法名,名稱隻支援“*”通配符,代表0個或多個字元
(2)JdkPegexpMethodPointcut:正規表達式切入點,如果是JDK1.4以下版本,使用Perl5RegexpMethodPointcut,這時要導入jakarta-oro-xx.jar包。它的patternt和patterns表示比對方法名稱的正規表達式,excludePattern和excludePatterns表示要排除的方法名稱正規表達式。
(3)expression_r_r_rPointcut:描述式切入點接口,用表達語言來描述切入點,spring提供了一個實作類,即AspectJexpression_r_r_rPointcut,它的expression_r_r_r屬性表示要描述的切入點。使用這個類要用于AspectJ中的文法解析處理器,這時要引入aspectjweaver.jar包。
增強(advice):也就是要切入什麼代碼。
Spirng Aop增強類型是圍繞方法調用連接配接點展開的,提供了以下四種類型;
(1)MethodBeforAdvice:方法調用前增強接口。使用者要實作它的before()方法
(2)AfterReturningAdvice:傳回後增強接口。使用者要實作它的afterReturning()方法。
(3)ThrowsAdvice:異常增強接口。這是個辨別接口,但在實際應用中,使用者要學現afterThrowing()方法。
(4)MethodInterceptor:環繞增強接口。又稱攔截器,是個辨別接口,在實際應用中,使用者要學現它的invoke()方法。
引介(Introduction):在不更改源代碼的情況下,給一個類增加屬性、方法以及讓它實作其它接口或其它父類。spring使用引介攔截器IntroductionInterceptor定義引介,它的implementsInterface屬性用來指定要實作的某個接口,spring提供該接口的兩個實作:
(1)DelegatingIntroductionInterceptor:執行個體化時要引入接口實作作為參數
(2)DelegatePerTargetObjectDelegatingIntroductionInterceptor:實作化時要引入一個接口及實作類作為參數。
增強器(Advisor):一個切面的子產品化封裝(如把切入點和增強封裝為一個整體,它們是無法單獨使用的),簡稱切面。有以下兩大類:
(1)由切入點(point cut)及增強(advice)組合的切面。
(2)組合引介的切面
Spring Aop最底層的切面封裝是Advisor接口,其下面還有兩個接口IntroductionAdvisor(引介增強器)及PointcutAdvisor(切入點增強器),它們有幾下幾種實作:
(1)DefaultPointcutAdvisor:預設的切面封裝。它的advice及pointcut屬性分别指增強和切入點。
(2)NameMatchMethodPointcutAdvisor:方法比對切入點切面。不用專門定義切入點,隻要指定增強。它的mappedName屬性指定切入點比對的方法名稱,advice屬性指定增強。
(3)RegexpMethodPointcutAdvisor:正規表達式切入點切面。不用專門定義切入,隻要指定增強。它的advice屬性表示要包裝的增強,pattern和patterns屬性表示要設定的切入點
(4)AspectJexpression_r_r_rPointcutAdvisor:AspectJ表達式切入點切面。不要專門定義切入點,隻要指定增強。它的advice屬性表示要包裝的增強,expression_r_r_r表示要生成切入點的表達式。
(5)DefultIntroductionAdvisor:引介增強器(IntroductionInterceptor)的實作
代理工廠(ProxyFactory):spring AOP是基于代理實作的,代理工廠用來建立代理對象。Spring的AOP提供了以下幾個代理工廠實作。
(1) ProxyFactoryBean:一般代理工廠
(2) TransactionProxyFactoryBean:事務代理工廠
(3) LocalStatelessSessionProxyFactoyBean:用于建立EJB代理的代理工廠
(4) BeanNameAutoProxyCreator:根據名稱自動建立代理
(5) DefaultAdvisorAutoProxyCreator:根據切面自動建立代理
AOP筆記3-spring AOP執行個體
假設有以下業務元件,我們使用AOP攔截它的兩個業務方法,在方法執行前加入使用者驗證子產品,在方法執行完成後,加入日志記錄子產品。
public interface Component{
void business1();//業務方法1
void business2();
}
public class ComonentImpl implements Component{
public void business1(){
System.out.println(“執行業務處理方法1”);
}
public void business2(){
System.out.println(“執行業務處理方法2”);
在Spring使用AOP有三種方式:
(1) 基于API方式。這種方式加入了Spring AOP API,入侵性較強。
一、建立增強,即要加入的代碼
//實作spring提供的增強類
public class AdviceBean implements MethodBeforeAdvice,AfterReturningAdvice{
//目标對象業務方法執行前要執行的代碼。
public void befor(Method method,Object[]args,Object target)throws Throwable{
validaterUser();//驗證使用者合法性
public void afterReturning(Object return Value,Method method,Object[] args,
Object target)throws Throwable{
writeLogInfo();//寫入日志
public void validateUser(){
System.out.println(“使用者驗證通過!”);
public void writeLogInfo(){
System.out.println(“日志寫入成功!”);
二、建立切入點類,即要在哪裡加入增強,這裡直接使用spring提供的切入點實作類,如:NameMatchMethodPointcut
三、建立切面封裝類,包裝切入點和增強,這裡直接使用spring提供的實作類,如:
DefaultPointcutAdvisor
四、建立代理類,這裡直接使用spring提供的代理工廠類負責建立。
五、配置以上資源
<!—以下例子的類省略了包路徑,實際中要加入-->
<bean id="targetBean" class="...ComponentImpl"/>
<bean id="adviceBean" class="...AdviceBean"/>
<!--使用sping AOP API定義切入點 -->
<bean id="pointcutBean"
class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedName" value="business*"/>
</bean>
<!--使用sping AOP API定義切面,封裝切入點和增強-->
<bean id="aspectBean"
class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="adviceBean"/>
<property name="pointcut" ref="pointcutBean"/>
<!--使用sping AOP API定義工廠,建立代理-->
<bean id="component" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="targetBean"/>
<property name="interceptorNames" >
<list>
<value>aspectBean</value>
</list>
</property>
六、測試
ApplicationContext context=new ClassPathXmlApplicationContext(aop.xml);
Component cp=(Component)context.getBean(“component”);
cp.business1();//測試aop運作結果
(2)基于Schema方式。這種方式使用普通的java對象表示切入子產品,易于移植。它使用配置檔案定義增強、切入點、切面。這種方式需要AspectJ架構的支援,要在lib中加入aspectjweaver.jar包(spring-aop.jar包含了該包)
一、建立要切入的子產品
public class AspectBean{
二、使用配置檔案定義切入點、增強、切面
<!-- 定義代表切面的java對象-->
<bean id="aspectBean" class="….AspectBean"/>
<aop:config>
<!-- 定義切面-->
<aop:aspect id="aspectDemo" ref="aspectBean">
<!--定義切入點-->
<aop:pointcut id="somePointcut" expression_r_r_r=
"execution(* com.acon.aop.domain.Component.business*(..))"/>
<!--定義切入點上的增強-->
<aop:before pointcut-ref="somePointcut" method="validateUser"/>
<aop:after-returning pointcut-ref="somePointcut"
method="writeLogInfo"/>
</aop:aspect>
</aop:config>
<!--定義元件-->
<bean id="component" class="com.acon.aop.domain.ComponentImpl"/>
三、測試(内容同使用上一節,略)
注意:
a.由于使用了<aop>元素,要修改此檔案聲明,即:
在<beans>中加入“xmlns:aop="http://www.springframework.org/schema/aop"”
并在”xsi:shemaLocation”中指定AOP配置的schema位址:
“http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd”
b. execution(* )”*”号後面是空格,否則出” Pointcut is not well-formed: expecting”錯誤
(3)使用AspectJ注解支援。基于注解需要jdk1.5支援,由于切面封裝子產品是POJO,這種方式不依賴Spring架構。這種方式要引入AspectJ架構相關包-aspectjweaver.jar,由于spring底層使用運作時位元組碼生成機制,還要相入asm-x.jar和asm-commons-x.jar等(這些包都包含在spring.aop.jar中了,在這裡說明,隻是告訴大家這些包是用來幹什麼用的)
一、定義切面
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.After;
@Aspect
public class AspectAnnotationBean{
//定義切入點
@Pointcut(“execution(*com.acon.aop.domain.Component.business*(..))”)
public void somePointcut(){}
//在切入點上加入增強,”*”後有空格
@Pointcut("execution(* com.acon.aop.domain.Component.business*(..))")
@After(“somePointcut()”)
System.out.println(“寫入日志成功!”);
二、配置切面
<!—定義切面子產品-->
<bean id=”aspectBean” class=”….AspectAnnotationBean”/>
<!—使用@AspectJ自動代理-->
<aop:aspectj-autoproxy/>
三、測試同上一節,略