本文目录
- AspectJ 框架概述
- 基于XML配置实现
- 创建Spring工程
- 创建目标接口和实现类
- 创建切面类
- Spring配置文件
- 测试代码和运行结果
- 基于注解实现
- 目标接口和实现类
- 切面类
- Spring配置文件
- 测试代码
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();
}
}
运行结果: