javascript
学习 Spring (十七) Spring 对 AspectJ 的支持 (完结)
Spring入門篇 學習筆記
@AspectJ 的風格類似純 java 注解的普通 java 類
Spring 可以使用 AspectJ 來做切入點解析
AOP 的運行時仍舊是純的 Spring AOP, 對 AspectJ 的編譯器或者織入無依賴性
Spring 中配置 @AspectJ
對 @AspectJ 支持可以使用 XML 或 Java 風格的配置
<?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/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><context:component-scan base-package="com.karonda.aop.aspectj"/><aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>確保 AspectJ 的 aspectjweaver.jar (1.6.8或更高版本) 庫包含在應用程序的 classpath 中
aspect
@AspectJ 切面使用 @Aspect 注解配置,擁有 @Aspect 的任何 bean 將被 Spring 自動識別并應用
用 @Aspect 注解的類可以有方法和字段,他們也可能包括切入點、通知和引入的聲明
@Aspect 注解是不能通過類路徑自動檢測發現的,所以需要配合使用 @Component 注釋或者在 XML 配置 bean
一個類中的 @Aspect 注解標識它為一個切面,并且將自己從自動代理中排除
@Component @Aspect public class MoocAspect {}pointcut
一個切入點通過一個普通的方法定義來提供,并且切入點表達式使用 @Pointcut 注解,方法返回類型必須為 void
@Component @Aspect public class MoocAspect {@Pointcut("execution(* com.karonda.aop.aspectj.biz.*Biz.*(..))")public void pointcut() {}@Pointcut("within(com.karonda.aop.aspectj.biz.*)")public void bizPointcut() {}}組合 pointcut
切入點表達式可以通過 &&, || 和 ! 進行組合,也可以通過名字引用切入點表達式
通過組合,可以建立更加復雜的切入點表達式
定義良好的 pointcut
AspectJ 是編譯期的 AOP
檢查代碼并匹配連接點與切入點的代價是昂貴的
一個好的切入點應該包括以下幾點:
- 選擇特定類型的連接點,如:execution, get, set, call, handler
- 確定連接點范圍,如:within, withincode
- 匹配上下文信息,如:this, target, @annotation
advice
添加類:
@Service public class MoocBiz {public String save(String arg) {System.out.println("MoocBiz save : " + arg); // throw new RuntimeException(" Save failed!");return " Save success!";}}添加測試類:
@RunWith(BlockJUnit4ClassRunner.class) public class TestAspectJ extends UnitTestBase {public TestAspectJ() {super("classpath:spring-aop-aspectj.xml");}@Testpublic void test() {MoocBiz biz = getBean("moocBiz");biz.save("This is test.");}}Before advice
在 MoocAspect 類添加方法:
// @Before("execution(* com.karonda.aop.aspectj.biz.*Biz.*(..))")@Before("pointcut()")public void before() {System.out.println("Before.");}After returning advice
@AfterReturning(pointcut="bizPointcut()", returning="returnValue")public void afterReturning(Object returnValue) {System.out.println("AfterReturning : " + returnValue);}After throwing advice
@AfterThrowing(pointcut="pointcut()", throwing="e")public void afterThrowing(RuntimeException e) {System.out.println("AfterThrowing : " + e.getMessage());}After (finally) advice
最終通知必須準備處理正常和異常兩種返回情況,它通常用于釋放資源
@After("pointcut()")public void after() {System.out.println("After.");}Around advice
@Around("pointcut()")public Object around(ProceedingJoinPoint pjp) throws Throwable {System.out.println("Around 1.");Object obj = pjp.proceed();System.out.println("Around 2.");System.out.println("Around : " + obj);return obj;}advice 擴展
給 advice 傳遞參數
args
@Before("pointcut() && args(arg)")public void beforeWithParam(String arg) {System.out.println("BeforeWithParam." + arg);}annotation
可以用來判斷方法上是否加了某注解或者方法上加的注解對應的值
定義一個注解:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MoocMethod {String value();}添加注解;
@Service public class MoocBiz {@MoocMethod("MoocBiz save MoocMethod.")public String save(String arg) {System.out.println("MoocBiz save : " + arg); // throw new RuntimeException(" Save failed!");return " Save success!";}}添加通知:
@Before("pointcut() && @annotation(moocMethod)")public void beforeWithAnnotaion(MoocMethod moocMethod) {System.out.println("BeforeWithAnnotation." + moocMethod.value());}advice 的參數及泛型
public interface Sample<T>{void sampleGenericMethod (T param);void sampleGenericCollectionMethod (Collection<T> param); }@Before("execution(* ..Sample+.sampleGenericMethod(*)) && args(param)") public void beforeSampleMethod(MyType param){}@Before("execution(* ..Sample+.sampleGenericCollectionMethod(*)) && args(param)") public void beforeSampleMethod(Collection<MyType> param){ }advice 參數名稱
通知和切入點注解有一個額外的 argNames 屬性,它可以用來指定所注解的方法的參數名
@Before(value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && annotation(auditable)", argNames="bean,auditable") public void audit(Object bean, Auditable a)如果第一個參數是 JoinPoint, ProceedingJoinPoint, JoinPoint.StaticPart 那么可以忽略它
@Before(value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && annotation(auditable)", argNames="bean,auditable") public void audit(JoinPoint jp, Object bean, Auditable a)Introduction
允許一個切面聲明一個通知對象實現指定接口,并且提供了一個接口實現類來代表這些對象
introduction 使用 @DeclareParents 進行注解,這個注解用來定義匹配的類型擁有一個新的 parent
@Aspect public class UsageTracking{@DeclareParents(value="com.xyz.myapp.service.*+", defaultImpl=DefaultUsageTracked.class)public class UsageTracked mixin;@Before("com.xyz.myapp.SystemArchitecture.businessService() && this(usageTracked)")public void recordUsage(UsageTracked usageTracked) {usageTracked.incrementUseCount();} }切面實例化模型
perthis 切面通過指定 @Aspect 注解 perthis 子句實現
每個獨立的 service 對象執行時都會創建一個切面實例
service 對象的每個方法在第一次執行的時候創建切面實例,切面在 service 對象失效的同時失效
@Aspect("perthis(com.xyz.myapp.SystemArchitecture.businessService())") public class MyAspect{private int someState;@Before(com.xyz.myapp.SystemArchitecture.businessService())public void recordServiceUsage(){}}源碼:learning-spring
轉載于:https://www.cnblogs.com/victorbu/p/10528957.html
總結
以上是生活随笔為你收集整理的学习 Spring (十七) Spring 对 AspectJ 的支持 (完结)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 子组件获取父组件的值,将这个值作为状态值
- 下一篇: leetcode题解【持续更新】