当前位置: 首页 > news >正文

SpringAOP实现

1、导入依赖

        <!--SpringAOP的织入包--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.19</version></dependency>

2、创建AppConfig配置类

@Configuration:配置类注解,使用该注解的类为一个配置类,其中用于定义交给Spring管理的各个方法@ComponentScan("com.jiazhong.dao.impl"):组件扫描器注解- 该注解会自动扫描指定包中的所有类,并将扫描到的类中带有@Component注解的类管理起来
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration //配置注解
@ComponentScan({"com.jiazhong.service","com.jiazhong.aspects"}) //组件扫描器注解
//@ComponentScan("com.jiazhong") 扫描com.jiazhong包下的所有类
public class AppConfig {
}

3、创建UserService接口及其实现类UserServiceImpl

public interface UserService {void add();void queryAll();String queryByName(String name);void del(int id);
}
@Service("userService"):Spring的服务层对象注解,它和@Component注解功能一样,只是语义更加明确- 在Service层使用该注解
import com.jiazhong.service.UserService;
import org.springframework.stereotype.Service;@Service("userService") //Spring的服务层对象注解,@Component注解功能一样
public class UserServiceImpl implements UserService {@Overridepublic void add() {System.out.println("执行UserServiceImpl---->add方法......");}@Overridepublic void queryAll() {System.out.println("执行UserServiceImpl---->queryAll方法......");}@Overridepublic String queryByName(String name) {System.out.println("执行UserServiceImpl---->queryByName方法......");//throw new RuntimeException();return "java"+name;}@Overridepublic void del(int id) {System.out.println("执行UserServiceImpl---->del方法......");}
}

4、创建切面类MyAspect

切入点定义,需要定义两个元素:1.切入点声明(private void myPointCut(){})- 在SpringAOP中切入点的声明其实就是方法定义,但无参数和方法体- 切入点的名称为方法名,在引用切入点时需要使用"方法名()"2.定义切入点表达式,由 @Pointcut注解定义@Pointcut:切入点表达式注解,通过切入点表达式对要拦截的方法描述execution:在其中编写切入点表达式- 切入点表达式是用于描述方法
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
@Aspect //切面注解
@Component //当前类扔给Spring管理
@EnableAspectJAutoProxy //启用springAOP的自动代理功能
//切入点声明
public class MyAspect {//切入点表达式注解@Pointcut("execution(void com.jiazhong.service.impl.UserServiceImpl.add())")//切入点声明    private void myPointCut(){}
}

对于切入点表达式还有以下写法,并分别注释了其意思

    //切入点定义拦截add方法@Pointcut("execution(void com.jiazhong.service.impl.UserServiceImpl.add())")//切入点定义拦截queryByName方法@Pointcut("execution(String com.jiazhong.service.impl.UserServiceImpl.queryByName(String))")//切入点定义拦截UserServiceImpl类中的所有方法,第一个*是所有类型,第二个*是类中所有方法,(..)是方法中的任意类型的任意参数@Pointcut("execution(* com.jiazhong.service.impl.UserServiceImpl.*(..))")//切入点定义拦截com.jiazhong.service包及其子包中的任意类任意方法@Pointcut("execution(* com.jiazhong.service..*.*(..))")//切入点定义不拦截指定的方法queryAll@Pointcut("!execution(void com.jiazhong.service.impl.UserServiceImpl.queryAll())")
切面类,切面中包含两个元素:1.切入点,用于定义连接点的2.通知,拦截到连接点后要做的具体事情- 前置通知,在目标方法执行前执行- 后置通知,在目标方法执行后执行- 异常通知,在目标方法出现异常后执行- 最终通告,无论目标方法是否出现异常都会执行

 ①前置通知

    /*** @Before("myPointCut()"):前置通知注解,myPointCut()指定切入点*/@Before("myPointCut()")public void beforeAdvice(){System.out.println("前置通知被执行......");}

② 后置通知

    /*** 后置通知,当目标方法调用后执行,但如果目标方法出现异常则不执行*/@AfterReturning("myPointCut()")public void afterReturningAdvice(){System.out.println("后置通知被执行......");}

③异常通知

    /*** 异常通知,在目标方法出现异常时执行*/@AfterThrowing("myPointCut()")public void throwAdvice(){System.out.println("异常通知被执行......");}

④最终通知

    /*** 最终通知,无论是否出现异常都被执行*/@After("myPointCut()")public void afterAdvice(){System.out.println("最终通知被执行......");}

⑤环绕通知

环绕通知可以替换前面的所有通知原则:在环绕通知内部必须手动调用目标方法环绕通知带有参数ProceedingJoinPoint(处理连接点),使用该参数可以发起对目标方法的调用
    /*** 环绕通知,可以在目标方法调用前、调用后、出现异常后自定义要执行的内容*/@Around("myPointCut()")public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint){try {System.out.println("环绕通知:前置通知。。。。。");//调用目标方法//目标方法的返回值就是proceed方法的返回值String msg = (String) proceedingJoinPoint.proceed();System.out.println(msg);System.out.println("环绕通知:后置通知。。。。。");} catch (Throwable e) {e.printStackTrace();System.out.println("环绕通知:异常通知。。。。。");}finally {System.out.println("环绕通知:最终通知。。。。。");}}

此处的实例是:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
@Aspect
@Component
@EnableAspectJAutoProxy
public class MyAspect {@Pointcut("execution(void com.jiazhong.service.impl.UserServiceImpl.add())")private void myPointCut(){}@Before("myPointCut()")public void beforeAdvice(){System.out.println("前置通知被执行......");}

5、UserTest测试类

public class UserTest {@Testpublic void test(){ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);UserService userService = (UserService) context.getBean("userService");userService.add();}
}
----SpringAOP注解
@Aspect:切面注解,在类上使用,表示该类为一个切面类
@EnableAspectJAutoProxy:启用SpringAOP的自动代理注解
@Pointcut:定义切入点表达式注解
@Before("切入点"):前置通知注解
@AfterReturning("切入点"):后置通知注解
@AfterThrowing("切入点"):异常通知注解
@After("切入点"):最终通知注解
@Around("切入点"):环绕通知注解
http://www.dtcms.com/a/305929.html

相关文章:

  • 图像处理中级篇 [1]—— 彩色照相机的效果与预处理
  • RHEL 9.5 离线安装 Ansible 完整教程
  • 【自动化运维神器Ansible】Ansible常用模块之user模块详解
  • 【自动化运维神器Ansible】Ansible常用模块之group模块详解
  • Vite 模块动态导入之Glob导入
  • 一款基于 ReactNative 最新发布的`Android/iOS` 新架构文档预览开源库
  • Three.js + AI:结合 Stable Diffusion 生成纹理贴图
  • 关于项目的一些完善功能
  • 【BUUCTF系列】[极客大挑战 2019] EasySQL 1
  • 性能优化(一):时间分片(Time Slicing):让你的应用在高负载下“永不卡顿”的秘密
  • Django常见模型字段
  • 【从零实践Onvif】01、Onvif详细介绍(从Onvif客户端开发的角度认识Onvif、Web Servies、WSDL、SOAP)
  • ECMAScript2021(ES12)新特性
  • Python深度挖掘:openpyxl与pandas高效数据处理实战指南
  • 网络编程-(网络计算机和网络通信)
  • Orange的运维学习日记--18.Linux sshd安全实践
  • CUDA编程9 - 卷积实践
  • String模拟实现的补充说明
  • 工业计算机ARM-如何实现工业数字化升级EC100!
  • QT跨平台应用程序开发框架(13)—— 绘图API
  • Linux设备驱动架构相关文章
  • @Scope(value = WebApplicationContext.SCOPE_REQUEST)和@Scope(“prototype“)区别
  • SQL 连接类型示例:内连接与外连接
  • 分布式系统:一致性
  • 二叉树(全)
  • InspireFace SDK gRPC 开发详细指导
  • 大厂主力双塔模型实践与线上服务
  • 嵌入式——C语言:内存管理、位运算符、构造数据类型(共用体、枚举)
  • NVIDIA Isaac平台推动医疗AI机器人发展研究
  • 【LeetCode 热题 100】33. 搜索旋转排序数组——(解法二)一次二分