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
完毕!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律