天天看點

基于AspectJ的注解AOP開發

AspectJ簡介

基于AspectJ的注解AOP開發

環境搭建

使用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 注解提供的通知類型

  1. @Before => 相當于BeforeAdvice(前置通知)
  2. @AfterReturning => 相當于AfterReturningAdvice(後置通知)
  3. @Around => 相當于MethodInterceptor(環繞通知)
  4. @AfterThrowing=> 相當于ThrowAdvice(異常通知)
  5. @After => 相當于try-catch語句的finally,不管是否異常都會通知

value屬性定義切點

在為一個方法寫通知類型時,需要使用value屬性來配置方法對應的切點(也就是攔截的方法)

基于AspectJ的注解AOP開發

前置通知的例子

com.aspectJ建了2個類,ProductDao是被代理類,MyAspectAnno是代理類。

基于AspectJ的注解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/>

    <!-- 配置被代理對象 -->

    <bean id="productDao" class="com.aspectJ.ProductDao"></bean>

    <!-- 配置切面 -->

    <bean class="com.aspectJ.MyAspectAnno"></bean>

</beans>

2個類結構:

基于AspectJ的注解AOP開發
基于AspectJ的注解AOP開發

編寫測試類

    @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);

    }