javascript
Spring3系列12-Spring AOP AspectJ
本文講述使用AspectJ框架實現(xiàn)Spring AOP。
再重復一下Spring AOP中的三個概念,
AspectJ是基于注釋(Annotation)的,所以需要JDK5.0以上的支持。
AspectJ支持的注釋類型如下:
?
首先定義一個簡單的bean,CustomerBo實現(xiàn)了接口ICustomerBo
ICustomerBo.java如下:
package com.lei.demo.aop.aspectj;public interface ICustomerBo {void addCustomer();void deleteCustomer();String AddCustomerReturnValue();void addCustomerThrowException() throws Exception;void addCustomerAround(String name);}?
?CustomerBo.java如下:
?
package com.lei.demo.aop.aspectj;public class CustomerBo implements ICustomerBo {public void addCustomer() {System.out.println("addCustomer() is running ...");}public void deleteCustomer() {System.out.println("deleteCustomer() is running ...");}public String AddCustomerReturnValue() {System.out.println("AddCustomerReturnValue() is running ...");return "abc";}public void addCustomerThrowException() throws Exception {System.out.println("addCustomerThrowException() is running ...");throw new Exception("Generic Error");}public void addCustomerAround(String name) {System.out.println("addCustomerAround() is running ,args:"+name);}}?
一、????? 簡單的AspectJ,Advice和Pointcut結(jié)合在一起
首先沒有引入Pointcut之前,Advice和Pointcut是混在一起的
步驟,只需要兩步,如下:
?
第一步,創(chuàng)建Aspect類
LoggingAspect.java如下:
package com.lei.demo.aop.aspectj;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before;@Aspect public class LoggingAspect {@Before("execution(public * com.lei.demo.aop.aspectj.CustomerBo.addCustomer(..))")public void logBefore(JoinPoint joinPoint){System.out.println("logBefore() is running ...");System.out.println("hijacked:"+joinPoint.getSignature().getName());System.out.println("**********");}@After("execution(public * com.lei.demo.aop.aspectj.CustomerBo.deleteCustomer(..))")public void logAfter(JoinPoint joinPoint){System.out.println("logAfter() is running ...");System.out.println("hijacked:"+joinPoint.getSignature().getName());System.out.println("**********");} }?
解釋:
1.??必須使用@Aspect在LoggingAspect聲明之前注釋,以便被框架掃描到
2.? 此例Advice和Pointcut結(jié)合在一起,類中的具體方法logBefore和logAfter即為Advice,是要注入的代碼,Advice方法上的表達式為Pointcut表達式,即定義了切入點,上例中@Before注釋的表達式代表執(zhí)行CustomerBo.addCustomer方法時注入logBefore代碼。
3.??在LoggingAspect方法上加入@Before或者@After等注釋
4.??"execution(public * com.lei.demo.aop.aspectj.CustomerBo.addCustomer(..))"是Aspect的切入點表達式,其中,*代表返回類型,后邊的就要定義要攔截的方法名,這里寫的的是com.lei.demo.aop.aspectj.CustomerBo.addCustomer表示攔截CustomerBo中的addCustomer方法,(..)代表參數(shù)匹配,此處表示匹配任意數(shù)量的參數(shù),可以是0個也可以是多個,如果你確定這個方法不需要使用參數(shù)可以直接用(),還可以使用(*)來匹配一個任意類型的參數(shù),還可以使用?(* , String),這樣代表匹配兩個參數(shù),第二個參數(shù)必須是String?類型的參數(shù)
5.??AspectJ表達式,可以對整個包定義,例如,execution(* com.lei.service..*.*(..))表示切入點是com.lei.sevice包中的任意一個類的任意方法,具體的表達式請自行百度。
?
第二步,配置Spring配置文件,
配置Spring-AOP-AspectJ.xml文件,如下:
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd"><aop:aspectj-autoproxy/><bean id="customerBo" class="com.lei.demo.aop.aspectj.CustomerBo"/><bean id="logAspect" class="com.lei.demo.aop.aspectj.LoggingAspect" /></beans>?
解釋:
1.??????<aop:aspectj-autoproxy/>啟動AspectJ支持,這樣Spring會自動尋找用@Aspect注釋過的類,其他的配置與spring普通bean配置一樣。
?
測試:
執(zhí)行App.java如下:
package com.lei.demo.aop.aspectj;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String[] args) {ApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] { "Spring-AOP-AspectJ.xml" });ICustomerBo customer=(ICustomerBo)appContext.getBean("customerBo");customer.addCustomer();System.out.println("-------------------------------------------");customer.deleteCustomer();} }?
結(jié)果:
logBefore() is running ...
hijacked:addCustomer
**********
addCustomer() is running ...
-------------------------------------------
deleteCustomer() is running ...
logAfter() is running ...
hijacked:deleteCustomer
**********
?
二、????? 將Advice和Pointcut分開
需要三步,
?
第一步,PointcutsDefinition.java定義了Pointcut,如下:
package com.lei.demo.aop.aspectj;import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut;@Aspect public class PointcutsDefinition {@Pointcut("execution(* com.lei.demo.aop.aspectj.CustomerBo.*(..))")public void customerLog() {} }?
解釋:
1. 類聲明前加入@Aspect注釋,以便被框架掃描到。
2. @Pointcut是切入點聲明,指定需要注入的代碼的位置,如上例中指定切入點為CustomerBo類中的所有方法,在實際業(yè)務中往往是指定切入點到一個邏輯層,例如?execution (* com.lei.business.service.*.*(..)),表示aop切入點為service包中所有類的所有方法,具體的表達式后邊會有介紹。
3. 方法customerLog是一個簽名,在Advice中可以用此簽名代替切入點表達式,所以不需要在方法體內(nèi)編寫實際代碼,只起到助記功能,例如此處代表操作CustomerBo類時需要的切入點。
?
第二步,創(chuàng)建Advice類
LoggingAspect.java如下:
package com.lei.demo.aop.aspectj;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before;@Aspect public class LoggingAspect {@Before("com.lei.demo.aop.aspectj.PointcutsDefinition.customerLog()")public void logBefore(JoinPoint joinPoint){System.out.println("logBefore() is running ...");System.out.println("hijacked:"+joinPoint.getSignature().getName());System.out.println("**********");}@After("com.lei.demo.aop.aspectj.PointcutsDefinition.customerLog()")public void logAfter(JoinPoint joinPoint){System.out.println("logAfter() is running ...");System.out.println("hijacked:"+joinPoint.getSignature().getName());System.out.println("**********");} }?
注釋:
1.???????@Before和@After使用PointcutsDefinition中的方法簽名代替Pointcut表達式找到相應的切入點,即通過簽名找到PointcutsDefinition中customerLog簽名上的Pointcut表達式,表達式指定切入點為CustomerBo類中的所有方法。所以此例中Advice類LoggingAdvice,為CustomerBo中的所有方法都加入了@Before和@After兩種類型的兩種操作。
2.???????對于PointcutsDefinition來說,主要職責是定義Pointcut,可以在其中第一多個切入點,并且可以用便于記憶的方法簽名進行定義。
3.???????單獨定義Pointcut的好處是,一是通過使用有意義的方法名,而不是難讀的Pointcut表達式,使代碼更加直觀;二是Pointcut可以實現(xiàn)共享,被多個Advice直接調(diào)用。若有多個Advice調(diào)用某個Pointcut,而這個Pointcut的表達式在將來有改變時,只需修改一個地方,維護更加方便。
?
第三步,配置Spring配置文件,配置文件并沒有改變
配置Spring-AOP-AspectJ.xml文件,如下:
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd"><aop:aspectj-autoproxy/><bean id="customerBo" class="com.lei.demo.aop.aspectj.CustomerBo"/><bean id="logAspect" class="com.lei.demo.aop.aspectj.LoggingAspect" /></beans>?
App.java不變,運行測試代碼App.java
輸出結(jié)果:
logBefore() is running ...
hijacked:addCustomer
**********
addCustomer() is running ...
logAfter() is running ...
hijacked:addCustomer
**********
-------------------------------------------
logBefore() is running ...
hijacked:deleteCustomer
**********
deleteCustomer() is running ...
logAfter() is running ...
hijacked:deleteCustomer
**********
?
三、???? 切入點表達式
Spring3.0.5幫助文檔中的切入點表達式如下:
?
Some examples of common pointcut expressions are given below.
?
the execution of any public method:
execution(public * *(..))
the execution of any method with a name beginning with "set":
execution(* set*(..))
the execution of any method defined by the AccountService interface:
execution(* com.xyz.service.AccountService.*(..))
the execution of any method defined in the service package:
execution(* com.xyz.service.*.*(..))
the execution of any method defined in the service package or a sub-package:
execution(* com.xyz.service..*.*(..))
any join point (method execution only in Spring AOP) within the service package:
within(com.xyz.service.*)
any join point (method execution only in Spring AOP) within the service package or a sub-package:
within(com.xyz.service..*)
any join point (method execution only in Spring AOP) where the proxy implements the AccountService interface:
this(com.xyz.service.AccountService)
'this' is more commonly used in a binding form :- see the following section on advice for how to make the proxy object available in the advice body.
?
any join point (method execution only in Spring AOP) where the target object implements the AccountService interface:
target(com.xyz.service.AccountService)
'target' is more commonly used in a binding form :- see the following section on advice for how to make the target object available in the advice body.
?
any join point (method execution only in Spring AOP) which takes a single parameter, and where the argument passed at runtime is Serializable:
args(java.io.Serializable)
'args' is more commonly used in a binding form :- see the following section on advice for how to make the method arguments available in the advice body.
Note that the pointcut given in this example is different to execution(* *(java.io.Serializable)): the args version matches if the argument passed at runtime is Serializable, the execution version matches if the method signature declares a single parameter of type Serializable.
?
any join point (method execution only in Spring AOP) where the target object has an @Transactional annotation:
@target(org.springframework.transaction.annotation.Transactional)
'@target' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.
?
any join point (method execution only in Spring AOP) where the declared type of the target object has an @Transactional annotation:
@within(org.springframework.transaction.annotation.Transactional)
'@within' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.
?
any join point (method execution only in Spring AOP) where the executing method has an @Transactional annotation:
@annotation(org.springframework.transaction.annotation.Transactional)
'@annotation' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.
?
any join point (method execution only in Spring AOP) which takes a single parameter, and where the runtime type of the argument passed has the@Classified annotation:
@args(com.xyz.security.Classified)
'@args' can also be used in a binding form :- see the following section on advice for how to make the annotation object(s) available in the advice body.
?
any join point (method execution only in Spring AOP) on a Spring bean named 'tradeService':
bean(tradeService)
any join point (method execution only in Spring AOP) on Spring beans having names that match the wildcard expression '*Service':
bean(*Service)
轉(zhuǎn)載于:https://www.cnblogs.com/jcomet/p/5570460.html
總結(jié)
以上是生活随笔為你收集整理的Spring3系列12-Spring AOP AspectJ的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: css静态网页设计 北京旅游(1页) 北
- 下一篇: 一些微信小程序demo源码