Spring AOP AspectJ

Spring框架建议您AOP实现上使用Spring AspectJ AOP实现,因为它为您提供了更多的控制并且易于使用。

有两种方式可以实现Spring AOP AspectJ:

  • 基于注解(下面我们将讨论)
  • 基于xml配置

Spring AspectJ AOP 实现提供了很多注解:

  • @Aspect 声明一个切面类
  • @Pointcut 声明一个切点表达式

用于创建advices的注解如下:

  • @Before 声明一个before advice,它应用在实际方法调用之前
  • @After 声明一个after advice,它应用在实际方法调用之后
  • @AfterReturning 声明一个after returning advice,它应用在实际方法返回之后
  • @Around 声明一个around advice,它应用在实际方法调用前后
  • @AfterThrowing 声明一个 after throwing advice,它应用在实际方法抛出异常后

理解Pointcut(切入点)

切入点是Spring AOP的一种表达语言。

@Pointcut批注用于定义切入点。我们也可以通过名称引用切入点表达式。让我们看一下切入点表达式的简单示例。

@Pointcut("execution(* Operation.*(..))")  
private void doSomething() {}  

切入点表达式的名称为doSomething()。无论返回类型如何,它将应用于Operation类的所有方法。

了解切入点表达式

让我们尝试通过以下示例了解切入点表达式:

 @Pointcut("execution(public * *(..))")  

它将应用于所有公共方法。

 

@Pointcut("execution(public Operation.*(..))")  

它将应用于Operation类的所有公共方法。

 

@Pointcut("execution(public Employee.set*(..))")  

它将应用于Employee类的所有公共setter方法。

 

@Pointcut("execution(int Operation.*(..))")  

它将应用于返回int值的Operation类的所有方法。

1、@Before 例子

目录结构如下:

 

 

在实际业务逻辑方法之前应用AspectJ Before Advice。您可以在此处执行任何操作,例如conversion,authentication 等。创建一个包含实际业务逻辑的类。

复制代码

import org.springframework.stereotype.Component;

/**
* @author:crelle
* @className:Operation
* @version:1.0.0
* @date:2020/9/21
* @description:XX
**/

@Component(value = "beforeOperation")
public class Operation {

public void msg(){
System.out.println("msg method invoked");
}

public int m(){
System.out.println("m method invoked");return 2;
}

public int k(){
System.out.println("k method invoked");return 3;
}
}
复制代码

现在,创建aspect类并且包含before advice。

复制代码

package crelle.test.aspectj.before;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
* @author:crelle
* @className:TrackOperation
* @version:1.0.0
* @date:2020/9/21
* @description:XX
**/
@Aspect
@Component(value = "beforeTrackOperation")
public class TrackOperation {

/**
*@author:crelle
*@date:2020/9/21
*@title:k
*@description:pointcut name
*@params:[]
*@return:void
*@throw:
*/
@Pointcut("execution(* crelle.test.aspectj.before.Operation.*(..))")
public void k(){};

/**
*@author:crelle
*@date:2020/9/21
*@title:myadvice
*@description: applying pointcut on before advice
*@params:[jp]
*@return:void
*@throw:
*/
@Before("k()")
public void myadvice(JoinPoint jp){
System.out.println("additional concern");
System.out.println("Method Signature:"+jp.getSignature());
}
}
 
复制代码
复制代码
import crelle.test.aspectj.before.Operation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy
public class SpringAopAspectjAnnotationExampleApplication implements CommandLineRunner {

    @Autowired
    private Operation operation;

    public static void main(String[] args) {
        SpringApplication.run(SpringAopAspectjAnnotationExampleApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

     System.out.println("calling msg...");
       operation.msg();
       System.out.println("calling m...");
       operation.m();
       System.out.println("calling k...");
       operation.k();


    }
}
复制代码

结果:

复制代码
calling msg...
additional concern
Method Signature:void crelle.test.aspectj.before.Operation.msg()
msg method invoked
calling m...
additional concern
Method Signature:int crelle.test.aspectj.before.Operation.m()
m method invoked
calling k...
additional concern
Method Signature:int crelle.test.aspectj.before.Operation.k()
k method invoked
复制代码

2、@After 例子

它可以用来维护log,security,notification 等。

复制代码
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;

/**
 * @author:crelle
 * @className:Operation
 * @version:1.0.0
 * @date:2020/9/21
 * @description:XX
 **/
@Component(value = "afterOperation")
public class Operation {

    public void msg(){
        System.out.println("msg method invoked");
    }

    public int m(){
        System.out.println("m method invoked");return 2;
    }

    public int k(){
        System.out.println("k method invoked");return 3;
    }
}
复制代码

现在,创建aspect类并且包含after advice。

复制代码
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * @author:crelle
 * @className:TrackOperation
 * @version:1.0.0
 * @date:2020/9/21
 * @description:XX
 **/
@Aspect
@Component(value = "afterTrackOperation")
public class TrackOperation {

    @Pointcut("execution(* Operation.*(..))")
    public void k() {
    }

    @After("k()")//applying pointcut on after advice
    public void myadvice(JoinPoint jp)//it is advice (after advice)
    {
        System.out.println("additional concern");
        //System.out.println("Method Signature: "  + jp.getSignature());
    }
}
复制代码
复制代码
package crelle.test.aspectj;

import crelle.test.aspectj.after.Operation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy
public class SpringAopAspectjAnnotationExampleApplication implements CommandLineRunner {

    @Autowired
    private Operation operation;

    public static void main(String[] args) {
        SpringApplication.run(SpringAopAspectjAnnotationExampleApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        System.out.println("calling msg...");
        operation.msg();
        System.out.println("calling m...");
        operation.m();
        System.out.println("calling k...");
        operation.k();

    }
}
复制代码

结果:

复制代码
calling msg...
msg method invoked
additional concern
calling m...
m method invoked
additional concern
calling k...
k method invoked
additional concern
复制代码

3、@AfterReturning 例子

通过@AfterReturning,我们可以在advice中获得结果。

复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * @author:crelle
 * @className:Operation
 * @version:1.0.0
 * @date:2020/9/21
 * @description:XX
 **/
@Component(value = "afterreturningOperation")
public class Operation {

    public int m(){
        System.out.println("m() method invoked");
        return 2;
    }
    public int k(){
        System.out.println("k() method invoked");
        return 3;
    }
}
复制代码

现在,创建aspect类并且包含afterreturning advice。

复制代码
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * @author:crelle
 * @className:TrackOperation
 * @version:1.0.0
 * @date:2020/9/21
 * @description:XX
 **/
@Aspect
@Component(value = "afterreturningTrackOperation")
public class TrackOperation{

    @AfterReturning(pointcut = "execution(* Operation.*(..))",returning= "result")
    public void myadvice(JoinPoint jp, Object result)//it is advice (after returning advice)
        {
            System.out.println("additional concern");
            System.out.println("Method Signature: " + jp.getSignature());
            System.out.println("Result in advice: "+result);
            System.out.println("end of after returning advice...");
        }
}
复制代码
复制代码
package crelle.test.aspectj;

import crelle.test.aspectj.afterreturning.Operation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy
public class SpringAopAspectjAnnotationExampleApplication implements CommandLineRunner {

    @Autowired
    private Operation operation;

    public static void main(String[] args) {
        SpringApplication.run(SpringAopAspectjAnnotationExampleApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        System.out.println("calling m...");
        System.out.println(operation.m());
        System.out.println("calling k...");
        System.out.println(operation.k());


    }
}
复制代码

结果:

复制代码
calling m...
m() method invoked
additional concern
Method Signature: int crelle.test.aspectj.afterreturning.Operation.m()
Result in advice: 2
end of after returning advice...
2
calling k...
k() method invoked
additional concern
Method Signature: int crelle.test.aspectj.afterreturning.Operation.k()
Result in advice: 3
end of after returning advice...
3
复制代码

4、@Around 例子

around advice的AspectJ在调用实际的业务逻辑方法之前和之后都会应用。

复制代码
import org.springframework.stereotype.Component;

/**
 * @author:crelle
 * @className:Operation
 * @version:1.0.0
 * @date:2020/9/21
 * @description:XX
 **/
@Component(value = "aroundOperation")
public class Operation {

    public void msg(){
        System.out.println("msg() is invoked");
    }
    public void display(){
        System.out.println("display() is invoked");
    }
}
复制代码

现在,创建aspect类并且包含around advice。

复制代码
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * @author:crelle
 * @className:TrackOperation
 * @version:1.0.0
 * @date:2020/9/21
 * @description:XX
 **/
@Aspect
@Component(value = "aroundTrackOperation")
public class TrackOperation {
    @Pointcut("execution(* Operation.*(..))")
    public void abcPointcut() {
    }

    @Around("abcPointcut()")
    public Object myadvice(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("Additional Concern Before calling actual method");
        Object obj = pjp.proceed();
        System.out.println("Additional Concern After calling actual method");
        return obj;
    }
}
复制代码
复制代码
package crelle.test.aspectj;

import crelle.test.aspectj.around.Operation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy
public class SpringAopAspectjAnnotationExampleApplication implements CommandLineRunner {

    @Autowired
    private Operation operation;

    public static void main(String[] args) {
        SpringApplication.run(SpringAopAspectjAnnotationExampleApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        operation.msg();
        operation.display();

    }
}
复制代码

结果:

Additional Concern Before calling actual method
msg() is invoked
Additional Concern After calling actual method
Additional Concern Before calling actual method
display() is invoked
Additional Concern After calling actual method

5、@AfterThrowing 例子

通过使用@AfterThrowing,我们可以在TrackOperation类中打印异常。让我们看一下AspectJ AfterThrowing advice的示例。

复制代码
import org.springframework.stereotype.Component;

/**
 * @author:crelle
 * @className:Operation
 * @version:1.0.0
 * @date:2020/9/21
 * @description:XX
 **/
@Component(value = "afterthrowingOperation")
public class Operation {

    public void validate(int age)throws Exception{
        if(age<18){
            throw new ArithmeticException("Not valid age");
        }else{
            System.out.println("Thanks for vote");
        }
    }
}
复制代码

现在,创建aspect类并且包含after throwing advice。

复制代码
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * @author:crelle
 * @className:TrackOperation
 * @version:1.0.0
 * @date:2020/9/21
 * @description:XX
 **/
@Aspect
@Component(value = "afterthrowingTrackOperation")
public class TrackOperation {

    @AfterThrowing(
            pointcut = "execution(* Operation.*(..))",
            throwing= "error")
    public void myadvice(JoinPoint jp, Throwable error)//it is advice
    {
        System.out.println("additional concern");
        System.out.println("Method Signature: "  + jp.getSignature());
        System.out.println("Method params:" + jp.getArgs().toString());
        System.out.println("Exception is: "+error);
        System.out.println("end of after throwing advice...");
    }
}
复制代码
复制代码
package crelle.test.aspectj;

import crelle.test.aspectj.afterthrowing.Operation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy
public class SpringAopAspectjAnnotationExampleApplication implements CommandLineRunner {

    @Autowired
    private Operation operation;

    public static void main(String[] args) {
        SpringApplication.run(SpringAopAspectjAnnotationExampleApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        try{
            operation.validate(19);
        }catch(Exception e){
            System.out.println(e);
        }

         System.out.println("calling validate again...");

        try{
            operation.validate(11);
        }catch(Exception e){
            System.out.println(e);
        }

    }
}
复制代码

结果:

Thanks for vote
calling validate again...
additional concern
Method Signature: void crelle.test.aspectj.afterthrowing.Operation.validate(int)
Method params:[Ljava.lang.Object;@6bb2d00b
Exception is: java.lang.ArithmeticException: Not valid age
end of after throwing advice...
java.lang.ArithmeticException: Not valid age

完毕!

 

posted @   我要去巴萨  阅读(191)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示