【Spring】AOP实现之AspectJ框架
程序员文章站
2022-09-16 21:17:04
本文目录AspectJ 框架概述基于XML配置实现创建Spring工程创建目标接口和实现类创建切面类Spring配置文件测试代码和运行结果基于注解实现目标接口和实现类切面类Spring配置文件测试代码推荐阅读: 【Spring】AOP详解AspectJ 框架概述AspectJ 是基于Java的一个AOP框架,其实现方式比起Java动态代理更为简捷,使用更为方便,而且还支持注解式开发。在Spring中使用AOP开发时,一般推荐使用AspectJ的实现方式。aspectJ中的通知类型通知描述...
本文目录
推荐阅读: 【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();
}
}
运行结果:
本文地址:https://blog.csdn.net/huweiliyi/article/details/107699495
推荐阅读
-
CI框架入门示例之数据库取数据完整实现方法
-
原理解密 → Spring AOP 实现动态数据源(读写分离),底层原理是什么
-
Spring AOP 实现原理与 CGLIB 应用
-
Spring AOP AspectJ使用及配置过程解析
-
Spring MVC 学习总结(十一)——IDEA+Maven+多模块实现SSM框架集成
-
mvc框架打造笔记之wsgi协议的优缺点以及接口实现
-
Spring AOP简介与底层实现机制——动态代理
-
spring框架中@PostConstruct的实现原理
-
spring-boot-2.0.3之redis缓存实现,不是你想的那样哦!
-
一起学Spring之注解和Schema方式实现AOP