AspectJ簡介
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2Lc1DOGFGd4dUY0hnMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DO1kTM1YjMxIDMzcDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
環境搭建
使用AspectJ之前需要在pom.xml中引入Spring AOP和AspectJ的相關jar包
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!--aspectj的包依賴以上2個包-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
配置檔案
按以下内容配置好applicationContext.xml檔案,即可開始AOP的注解開發。
<?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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--開啟AspectJ的自動代理-->
<aop:aspectj-autoproxy/>
</beans>
@AspectJ 注解提供的通知類型
- @Before => 相當于BeforeAdvice(前置通知)
- @AfterReturning => 相當于AfterReturningAdvice(後置通知)
- @Around => 相當于MethodInterceptor(環繞通知)
- @AfterThrowing=> 相當于ThrowAdvice(異常通知)
- @After => 相當于try-catch語句的finally,不管是否異常都會通知
value屬性定義切點
在為一個方法寫通知類型時,需要使用value屬性來配置方法對應的切點(也就是攔截的方法)
前置通知的例子
com.aspectJ建了2個類,ProductDao是被代理類,MyAspectAnno是代理類。
配置檔案
<?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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--開啟AspectJ的自動代理-->
<aop:aspectj-autoproxy/>
<!-- 配置被代理對象 -->
<bean id="productDao" class="com.aspectJ.ProductDao"></bean>
<!-- 配置切面 -->
<bean class="com.aspectJ.MyAspectAnno"></bean>
</beans>
2個類結構:
編寫測試類
@org.junit.Test
public void test() {
// 加載配置檔案
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext1.xml");
// 擷取bean
ProductDao productDao = (ProductDao) context.getBean("productDao");
productDao.save();
productDao.delete();
}
運作結果:
前置增強...execution(void com.aspectJ.ProductDao.save())
儲存商品...
删除商品...
其它類型通知
後置通知
// 後置通知,攔截update方法
@AfterReturning(value="execution(* com.aspectJ.ProductDao.update(..))",returning="ret")
public void afterReturning(Object ret) {
// ret是攔截的方法傳回值
System.out.println("後置增強" + ret);
}
環繞通知
// 環繞通知,攔截所有方法
@Around(value="execution(* *(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("環繞前增強");
// 執行攔截到的方法
Object object = joinPoint.proceed();
System.out.println("環繞後增強");
return object;
}
異常抛出通知
// 異常抛出通知
@AfterThrowing(value="execution(* *(..))", throwing="e")
public void throwing(Throwable e) {
System.out.println("異常抛出通知" + e.getMessage());
}
最終通知(類似finally)
// 最終通知
@After(value="execution(* *(..))")
public void after() {
System.out.println("最終通知");
}
起别名:給要攔截的方法起别名,這樣在一個方法需要在多處産生通知時使用别名有利于代碼的維護.
value後面寫要起别名的方法,下面寫一個 private void 别名() {},這樣就産生了别名,在使用攔截的地方,把value寫成value="别名()"就可以了。
// 給攔截的方法起别名
@Pointcut(value="execution(* com.aspectJ.ProductDao.update(..))")
private void myPointCut() {}
// 後置通知,使用别名
@AfterReturning(value="myPointCut()",returning="ret")
public void afterReturning(Object ret) {
// ret是攔截的方法傳回值
System.out.println("後置增強" + ret);
}