Spring

Spring - AOP - AspectJ annotatio

2020-01-18  本文已影响0人  HRocky

原文地址:https://mkyong.com/spring3/spring-aop-aspectj-annotation-example/

在本教程中,我们向您展示如何将AspectJ注释与Spring AOP框架集成在一起。
简单来说,Spring AOP + AspectJ使您可以轻松地拦截方法。

常见的AspectJ注释:

注意:对于没有AspectJ支持的Spring AOP,请阅读。Spring - AOP - Advice

1.目录结构

请参阅本示例的目录结构。

目录结构.png

2.项目依赖

要启用AspectJ,您需要aspectjrt.jar,aspectjweaver.jar和spring-aop.jar。
请参阅以下Maven pom.xml文件

从Spring 2.0开始支持AspectJ
此示例使用的是Spring 3,但自Spring 2.0开始支持AspectJ功能。

文件:pom.xml

<project ...>

    <properties>
        <spring.version>3.0.5.RELEASE</spring.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- Spring AOP + AspectJ -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.11</version>
        </dependency>
        
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.11</version>
        </dependency>
        
    </dependencies>
</project>

3. Spring Beans

package com.mkyong.customer.bo;

public interface CustomerBo {

    void addCustomer();
    
    String addCustomerReturnValue();
    
    void addCustomerThrowException() throws Exception;
    
    void addCustomerAround(String name);
}
package com.mkyong.customer.bo.impl;

import com.mkyong.customer.bo.CustomerBo;

public class CustomerBoImpl implements CustomerBo {

    public void addCustomer(){
        System.out.println("addCustomer() 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);
    }
}

4.启用AspectJ

在Spring配置文件中,放入“ <aop:aspectj-autoproxy />”,然后定义您的Aspect(拦截器)和普通bean。

文件:Spring-Customer.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/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

    <aop:aspectj-autoproxy />

    <bean id="customerBo" class="com.mkyong.customer.bo.impl.CustomerBoImpl" />

    <!-- Aspect -->
    <bean id="logAspect" class="com.mkyong.aspect.LoggingAspect" />

4. AspectJ @Before

在下面的示例中,将在执行customerBo接口addCustomer()方法之前执行logBefore()方法。

文件:LoggingAspect.java

package com.mkyong.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class LoggingAspect {

    @Before("execution(* com.mkyong.customer.bo.CustomerBo.addCustomer(..))")
    public void logBefore(JoinPoint joinPoint) {

        System.out.println("logBefore() is running!");
        System.out.println("hijacked : " + joinPoint.getSignature().getName());
        System.out.println("******");
    }

}

运行

CustomerBo customer = (CustomerBo) appContext.getBean("customerBo");
    customer.addCustomer();

输出

logBefore() is running!
hijacked : addCustomer
******
addCustomer() is running 

5. AspectJ @After

在下面的示例中,将在执行customerBo接口addCustomer()方法之后执行logAfter()方法。

文件:LoggingAspect.java

```
package com.mkyong.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.After;

@Aspect
public class LoggingAspect {

    @After("execution(* com.mkyong.customer.bo.CustomerBo.addCustomer(..))")
    public void logAfter(JoinPoint joinPoint) {

        System.out.println("logAfter() is running!");
        System.out.println("hijacked : " + joinPoint.getSignature().getName());
        System.out.println("******");

    }

}

运行

CustomerBo customer = (CustomerBo) appContext.getBean("customerBo");
customer.addCustomer();

输出

addCustomer() is running 
logAfter() is running!
hijacked : addCustomer
******

6. AspectJ @AfterReturning

在下面的示例中,将在执行customerBo接口addCustomerReturnValue()方法之后执行logAfterReturning()方法。
另外,您可以使用“returning”属性截取返回的值。

要拦截返回的值,“returning”属性(结果)的值必须与方法参数(结果)相同。

文件:LoggingAspect.java

package com.mkyong.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;

@Aspect
public class LoggingAspect {

   @AfterReturning(
      pointcut = "execution(* com.mkyong.customer.bo.CustomerBo.addCustomerReturnValue(..))",
      returning= "result")
   public void logAfterReturning(JoinPoint joinPoint, Object result) {

    System.out.println("logAfterReturning() is running!");
    System.out.println("hijacked : " + joinPoint.getSignature().getName());
    System.out.println("Method returned value is : " + result);
    System.out.println("******");

   }

}

运行

CustomerBo customer = (CustomerBo) appContext.getBean("customerBo");
customer.addCustomerReturnValue();

输出

addCustomerReturnValue() is running 
logAfterReturning() is running!
hijacked : addCustomerReturnValue
Method returned value is : abc
******

7. AspectJ @AfterThrowing

在下面的示例中,如果customerBo接口addCustomerThrowException()方法引发异常,则将执行logAfterThrowing()方法。

文件:LoggingAspect.java

package com.mkyong.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;

@Aspect
public class LoggingAspect {

   @AfterThrowing(
      pointcut = "execution(* com.mkyong.customer.bo.CustomerBo.addCustomerThrowException(..))",
      throwing= "error")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {

    System.out.println("logAfterThrowing() is running!");
    System.out.println("hijacked : " + joinPoint.getSignature().getName());
    System.out.println("Exception : " + error);
    System.out.println("******");

    }
}

运行

CustomerBo customer = (CustomerBo)appContext.getBean("customerBo");
customer.addCustomerThrowException();

输出

addCustomerThrowException() is running 
logAfterThrowing() is running!
hijacked : addCustomerThrowException
Exception : java.lang.Exception: Generic Error
******
Exception in thread "main" java.lang.Exception: Generic Error
    //...

8.AspectJ @Around

在下面的示例中,logAround()方法将在customerBo接口,addCustomerAround()方法之前执行,并且您必须定义“ joinPoint.proceed();”以控制拦截器何时应将控件返回到原始addCustomerAround()方法。

文件:LoggingAspect.java

package com.mkyong.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;

@Aspect
public class LoggingAspect {

   @Around("execution(* com.mkyong.customer.bo.CustomerBo.addCustomerAround(..))")
   public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {

    System.out.println("logAround() is running!");
    System.out.println("hijacked method : " + joinPoint.getSignature().getName());
    System.out.println("hijacked arguments : " + Arrays.toString(joinPoint.getArgs()));
        
    System.out.println("Around before is running!");
    joinPoint.proceed(); //continue on the intercepted method
    System.out.println("Around after is running!");
        
    System.out.println("******");

   }
    
}

运行

CustomerBo customer = (CustomerBo)appContext.getBean("customerBo");
customer.addCustomerAround("mkyong");

输出

logAround() is running!
hijacked method : addCustomerAround
hijacked arguments : [mkyong]
Around before is running!
addCustomerAround() is running, args : mkyong
Around after is running!
******

总结

始终建议使用功耗最低的AsjectJ注解。

上一篇下一篇

猜你喜欢

热点阅读