【Spring】AOP实现之AspectJ框架
程序员文章站
2022-07-12 14:10:05
...
本文目录
推荐阅读: 【Spring】AOP详解
AspectJ 框架概述
AspectJ
是基于Java的一个AOP框架,其实现方式比起Java动态代理更为简捷,使用更为方便,而且还支持注解式开发。在Spring
中使用AOP开发时,一般推荐使用AspectJ
的实现方式。
AspectJ中的通知类型
通知 | 描述 |
---|---|
前置通知 | 在一个方法执行之前,执行通知。 |
后置通知 | 在一个方法执行之后,不考虑其结果,执行通知。 |
返回后通知 | 在一个方法执行之后,只有在方法成功完成时,才能执行通知 |
抛出异常后通知 | 在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。 |
环绕通知 | 在建议方法调用之前和之后,执行通知。 |
使用AspectJ实现AOP有两种方式:一种是基于XML的声明式AspectJ,另一种是基于注解的声明式AspectJ
基于XML配置实现
基于XML的声明式AspectJ是指通过XML文件来定义切面、切入点及通知,所有的切面、切入点和通知都必须定义在aop:config元素内。
创建Spring工程
首先创建Spring
工程:【Spring】Spring入门案例
在pom.xml
中加入Spring aop
和AspectJ
相关的包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
创建目标接口和实现类
public interface UserService {
public void selectUser();
}
public class UserServiceImpl implements UserService{
@Override
public void selectUser() {
System.out.println("UserServiceImpl -> selectUser");
}
}
创建切面类
package com.lucas;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAspect {
//前置通知
public void myBefore(JoinPoint joinPoint){
System.out.println("MyAspect ->前置通知:"+joinPoint);
System.out.println("MyAspect ->前被植入增强处理的目标方法:"+joinPoint.getSignature().getName());
}
//后置通知
public void myAfterReturrning(JoinPoint joinPoint, Object ret){
System.out.println("MyAspect ->前后置通知:"+joinPoint);
System.out.println("MyAspect ->前被植入增强处理的目标方法:"+joinPoint.getSignature().getName() +" ret =" +ret);
}
/*
* 环绕通知
* proceedingJoinPoint是JoinPoint子接口,表示可以执行目标方法
* 1.必须是Object类型的返回值
* 2.必须接收一个参数,类型为ProceedingJoinPoint
* 3.必须throws Throwable
*/
public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("MyAspect ->前环绕前通知");
//执行当前目标方法
Object obj = proceedingJoinPoint.proceed();
System.out.println("MyAspect ->前环绕后通知");
return obj;
}
//异常通知
public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
System.out.println("MyAspect ->前异常通知:"+e.getMessage());
}
//最终通知
public void myAfter(){
System.out.println("MyAspect ->前最终通知");
}
}
Spring配置文件
<?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 https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 目标类 -->
<bean id="userService" class="com.lucas.UserServiceImpl"></bean>
<!-- 切面 -->
<bean id="myAspect" class="com.lucas.MyAspect"></bean>
<aop:config>
<!-- 配置切面 -->
<aop:aspect ref="myAspect">
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.lucas.*.*(..))" id="myPointCut"/>
<!-- 前置通知 -->
<aop:before method="myBefore" pointcut-ref="myPointCut"/>
<!-- 后置通知 returning属性:用于设置后置通知的第二个参数的名称,类型是Object -->
<aop:after-returning method="myAfterReturrning" pointcut-ref="myPointCut" returning="ret"/>
<!-- 环绕通知 -->
<aop:around method="myAround" pointcut-ref="myPointCut"/>
<!-- 异常通知:如果没有异常,将不会执行增强
throwing属性:用于设置通知第二个参数的的名称、类型-->
<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>
<!-- 最终通知 -->
<aop:after method="myAfter" pointcut-ref="myPointCut"/>
</aop:aspect>
</aop:config>
</beans>
测试代码和运行结果
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.selectUser();
}
}
基于注解实现
目标接口和实现类
public interface UserService {
public void selectUser();
}
@Service("userService")
public class UserServiceImpl implements UserService {
@Override
public void selectUser() {
System.out.println("UserServiceImpl -> selectUser");
}
}
切面类
package com.lucas;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAspect {
@Pointcut("execution(* com.lucas.*.*(..))")
public void myPointCut() {
}
//前置通知
@Before("myPointCut()") //注解里面的值为上面的方法名
public void myBefore(JoinPoint joinPoint){
System.out.println("MyAspect ->前置通知:"+joinPoint);
System.out.println("MyAspect ->前被植入增强处理的目标方法:"+joinPoint.getSignature().getName());
}
//后置通知
@AfterReturning(value = "myPointCut()", returning = "ret")
public void myAfterReturrning(JoinPoint joinPoint, Object ret){
System.out.println("MyAspect ->前后置通知:"+joinPoint);
System.out.println("MyAspect ->前被植入增强处理的目标方法:"+joinPoint.getSignature().getName() +" ret =" +ret);
}
/*
* 环绕通知
* proceedingJoinPoint是JoinPoint子接口,表示可以执行目标方法
* 1.必须是Object类型的返回值
* 2.必须接收一个参数,类型为ProceedingJoinPoint
* 3.必须throws Throwable
*/
@Around("myPointCut()")
public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("MyAspect ->前环绕前通知");
//执行当前目标方法
Object obj = proceedingJoinPoint.proceed();
System.out.println("MyAspect ->前环绕后通知");
return obj;
}
//异常通知
@AfterThrowing(value = "myPointCut()", throwing = "e")
public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
System.out.println("MyAspect ->前异常通知:"+e.getMessage());
}
//最终通知
@After("myPointCut()")
public void myAfter(){
System.out.println("MyAspect ->前最终通知");
}
}
Spring配置文件
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.lucas"/>
<!-- 开启AspectJ 注解的支持-->
<aop:aspectj-autoproxy/>
</beans>
测试代码
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.selectUser();
}
}
运行结果:
上一篇: 基于@AspectJ注解的AOP实现
推荐阅读
-
spring AOP的Around增强实现方法分析
-
详解Spring Boot实战之Filter实现使用JWT进行接口认证
-
使用Spring Boot和AspectJ实现方法跟踪基础结构
-
laravel框架学习笔记之组件化开发实现方法
-
CI框架入门示例之数据库取数据完整实现方法
-
原理解密 → Spring AOP 实现动态数据源(读写分离),底层原理是什么
-
Spring AOP 实现原理与 CGLIB 应用
-
Spring AOP AspectJ使用及配置过程解析
-
Spring MVC 学习总结(十一)——IDEA+Maven+多模块实现SSM框架集成
-
mvc框架打造笔记之wsgi协议的优缺点以及接口实现