目录

  • 基于 `XML` 方式实现
    • 使用 `xml` 配置文件(不使用注解)
      • `Maven` 依赖
      • 目标接口
      • 目标实现类
      • 通知切面类
      • `spring` 的配置文件
      • 测试
      • 测试结果
    • 使用注解的方式
      • `spring` 的配置文件
  • `springboot` 实现 `AOP`
    • `Maven` 依赖
    • 通知类

基于 XML 方式实现

使用 xml 配置文件(不使用注解)

Maven 依赖

<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.10.RELEASE</version>
</dependency>
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.9</version>
</dependency>

目标接口

public interface IUserManagerService {// 查找用户public String findUser();// 添加用户public void addUser();
}

目标实现类

public class UserManagerServiceImpl implements IUserManagerService{private String name;public void setName(String name){this.name=name;}public String getName(){return this.name;}public String findUser(){System.out.println("============执行业务方法findUser,查找的用户是:"+name+"=============");return name;}public void addUser(){System.out.println("============执行业务方法addUser=============");//throw new RuntimeException();}
}

通知切面类

public class AopAspect {/*** 前置通知:目标方法调用之前执行的代码*/public void doBefore(JoinPoint jp){System.out.println("===========执行前置通知============");}/*** 最终通知:目标方法调用之后执行的代码(无论目标方法是否出现异常均执行)* 因为方法可能会出现异常,所以不能获取方法的返回值*/public void doAfter(JoinPoint jp){System.out.println("===========执行最终通知============");}/*** 后置通知:目标方法正常结束后执行的代码* 后置通知是可以获取到目标方法的返回值的*/public void doAfterReturning(JoinPoint jp,String result){System.out.println("===========执行后置返回通知============");System.out.println("返回值result==================="+result);}/*** 异常通知:目标方法抛出异常时执行的代码* 可以访问到异常对象*/public void doAfterThrowing(JoinPoint jp,Exception ex){System.out.println("===========执行异常通知============");}/*** 环绕通知:目标方法调用前后执行的代码,可以在方法调用前后完成自定义的行为。* 包围一个连接点(join point)的通知。它会在切入点方法执行前执行同时方法结束也会执行对应的部分。* 主要是调用proceed()方法来执行切入点方法,来作为环绕通知前后方法的分水岭。* 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。* 而且环绕通知必须有返回值,返回值即为目标方法的返回值*/public Object doAround(ProceedingJoinPoint pjp) throws Throwable{System.out.println("======执行环绕通知开始=========");// 调用方法的参数Object[] args = pjp.getArgs();// 调用的方法名String method = pjp.getSignature().getName();// 获取目标对象Object target = pjp.getTarget();// 执行完方法的返回值// 调用proceed()方法,就会触发切入点方法执行Object result=pjp.proceed();System.out.println("输出,方法名:" + method + ";目标对象:" + target + ";返回值:" + result);System.out.println("======执行环绕通知结束=========");return result;}
}

spring 的配置文件

<bean id="userManager" class="com.spring.service.impl.UserManagerServiceImpl"><property name="name" value="lixiaoxi"></property>
</bean>  <!-- 通知类 -->
<bean id="aspectBean" class="com.spring.aop.AopAspect" /><aop:config><aop:aspect ref="aspectBean"><!-- 配置切点 --><aop:pointcut id="pointcut" expression="execution(* com.spring.service.impl.UserManagerServiceImpl..*(..))"/><!-- 前置通知 --><aop:before method="doBefore" pointcut-ref="pointcut"/><!-- 后置返回通知 --> <aop:after-returning method="doAfterReturning" pointcut-ref="pointcut" returning="result"/><!-- 后置通知 --><aop:after method="doAfter" pointcut-ref="pointcut" /><!-- 环绕通知 --><aop:around method="doAround" pointcut-ref="pointcut"/><!-- 异常通知 --> <aop:after-throwing method="doAfterThrowing" pointcut-ref="pointcut" throwing="ex"/></aop:aspect>
</aop:config>
  • <aop:pointcut> 如果位于 <aop:aspect>元素中,则命名切点只能被当前 <aop:aspect> 内定义的元素访问到,为了能被整个<aop:config>元素中定义的所有增强访问,则必须在<aop:config>下定义切点
  • 如果在<aop:config>元素下直接定义<aop:pointcut>,必须保证<aop:pointcut><aop:aspect>之前定义。<aop:config>下还可以定义<aop:advisor>,三者在<aop:config> 中的配置有先后顺序的要求:首先必须是<aop:pointcut>,然后是<aop:advisor>,最后是<aop:aspect>。而在<aop:aspect>中定义的<aop:pointcut>则没有先后顺序的要求,可以在任何位置定义
  • <aop:pointcut>:用来定义切入点,该切入点可以重用;<aop:advisor> 用来定义只有一个通知和一个切入点的切面;<aop:aspect>:用来定义切面,该切面可以包含多个切入点和通知,而且标签内部的通知和切入点定义是无序的;和 advisor 的区别就在此,advisor只包含一个通知和一个切入点

测试

public class TestAop {public static void main(String[] args) throws Exception{ApplicationContext act =  new ClassPathXmlApplicationContext("applicationContext3.xml");IUserManagerService userManager = (IUserManagerService)act.getBean("userManager");userManager.findUser();System.out.println("\n");userManager.addUser();}
}

测试结果

使用注解的方式

采用注解来做 aop,主要是将写在 spring 配置文件中的连接点写到注解里面
业务接口和业务实现与上边一样,具体切面类如下

@Aspect
public class AopAspectJ {/*** 切点表达式*/@Pointcut("execution(* com.spring.service.impl.UserManagerServiceImpl..*(..))")public void myPointcut() {}    /*** 前置通知:即方法执行前拦截到的方法* 在目标方法执行之前的通知*/@Before("myPointcut()")public void doBefore(JoinPoint jp){System.out.println("=========执行前置通知==========");}/*** 最终通知:目标方法调用之后执行的通知(无论目标方法是否出现异常均执行)* 因为方法可能会出现异常,所以不能获取方法的返回值*/@After(value="myPointcut()")public void doAfter(JoinPoint jp){System.out.println("===========执行最终通知============");}/*** 后置通知:在方法正常执行通过之后执行的通知叫做返回通知* 可以获取到目标方法的返回值 */@AfterReturning(value="myPointcut()",returning="result")public void doAfterReturning(JoinPoint jp,String result){System.out.println("===========执行后置通知============");}/*** 环绕通知:目标方法调用前后执行的通知,可以在方法调用前后完成自定义的行为。*/@Around("myPointcut()")public Object doAround(ProceedingJoinPoint pjp) throws Throwable{System.out.println("======执行环绕通知开始=========");// 调用方法的参数Object[] args = pjp.getArgs();// 调用的方法名String method = pjp.getSignature().getName();// 获取目标对象Object target = pjp.getTarget();// 执行完方法的返回值// 调用proceed()方法,就会触发切入点方法执行Object result=pjp.proceed();System.out.println("输出,方法名:" + method + ";目标对象:" + target + ";返回值:" + result);System.out.println("======执行环绕通知结束=========");return result;}/*** 异常通知:在目标方法非正常执行完成, 抛出异常的时候会走此方法*/@AfterThrowing(value="myPointcut()",throwing="ex")public void doAfterThrowing(JoinPoint jp,Exception ex) {System.out.println("===========执行异常通知============");}
}

spring 的配置文件

<!-- spring 对 @AspectJ 的支持 -->
<aop:aspectj-autoproxy/>    <!-- 业务类 -->
<bean id="userManager" class="com.spring.service.impl.UserManagerServiceImpl"><property name="name" value="lixiaoxi"></property>
</bean>   <!-- 通知类 -->
<bean id="aspectBean" class="com.spring.aop.AopAspectJ" />

springboot 实现 AOP

Maven 依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

通知类

@Component
@Aspect
public class Demo16 {// 前置通知:在目标方法执行之前的通知@Before("execution (* com.zsg.demo..*.*(..))")public void beforeMethod(JoinPoint joinPoint) {String methodName = joinPoint.getSignature().toString();Object result = Arrays.asList(joinPoint.getArgs());System.out.println("The method name:" + methodName + "--value:" + result);}// 最终通知:目标方法调用之后执行的通知(无论目标方法是否出现异常均执行)// 因为方法可能会出现异常,所以不能获取方法的返回值@After("execution (* com.xxx.demo..*.*(..))")public void afterMethod(JoinPoint joinPoint) {String methodName = joinPoint.getSignature().getName();System.out.println("The method name:" + methodName + " ends");}// 后置通知:在方法正常执行通过之后执行的通知叫做返回通知,可以获取到目标方法的返回值@AfterReturning(value = "execution (* com.xxx.demo..*.*(..))", returning = "result")public void afterReturningMethod(JoinPoint joinPoint, Object result) {String methodName = joinPoint.getSignature().getName();System.out.println("The method name:" + methodName + " ends and result=" + result);}// @AfterThrowing: 异常通知@AfterThrowing(value = "execution (* com.xxx.demo..*.*(..))", throwing = "e")public void afterReturningMethod(JoinPoint joinPoint, Exception e) {String methodName = joinPoint.getSignature().getName();System.out.println("The method name:" + methodName + " ends and result=" + e);}
}

Spring之AOP的实现相关推荐

  1. Spring.Net Aop

    Spring.Net 有四种通知: IMethodBeforeAdvice,IAfterReturningAdvice,IMethodInterceptor,IThrowsAdvice BeforeA ...

  2. [Spring 深度解析]第4章 Spring之AOP

    第4章 ◄Spring之AOP► 在上一章节中,我们大致了解了Spring核心容器,了解了IOC思想在Spring中的具体应用Bean容器以及Bean的配置与使用,这一章我们将开始学习AOP在Spri ...

  3. Spring对AOP的支持

     Spring对AOP的支持<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" ...

  4. Spring 容器AOP的实现原理——动态代理

    本文来自极客学院 Spring 容器AOP的实现原理--动态代理 之前写了一篇关于IOC的博客--<Spring容器IOC解析及简单实现>,今天再来聊聊AOP.大家都知道Spring的两大 ...

  5. Spring的AOP使用xml配置

    需要使用spring的包,大家自己全部导入进去即可.省4........ 用户管理接口 package com.rx.spring; public interface UserManager { pu ...

  6. 【SSM框架系列】Spring 的 AOP(面向切面编程)

    什么是 AOP AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP 是 OOP ...

  7. Spring实现AOP的4种方式

    Spring实现AOP的4种方式 先了解AOP的相关术语: 1.通知(Advice): 通知定义了切面是什么以及何时使用.描述了切面要完成的工作和何时需要执行这个工作. 2.连接点(Joinpoint ...

  8. Spring的AOP原理

    AOP是什么? 软件工程有一个基本原则叫做"关注点分离"(Concern Separation),通俗的理解就是不同的问题交给不同的部分去解决,每部分专注于解决自己的问题.这年头互 ...

  9. Spring中AOP相关的API及源码解析,原来AOP是这样子的

    前言 之所以写这么一篇文章主要是因为下篇文章将结束Spring启动整个流程的分析,从解析配置到创建对象再到属性注入最后再将创建好的对象初始化成为一个真正意义上的Bean.因为下篇文章会涉及到AOP,所 ...

  10. spring教程--AOP详解

    1 Spring中的AOP 1.1 Spring的传统AOP : AOP:不是由Spring定义.AOP联盟的组织定义. Spring中的通知:(增强代码) 前置通知 org.springframew ...

最新文章

  1. 配置Android开发环境(fedora)
  2. 【Android视图效果】共享元素实现仿微信查看大图效果
  3. oracle em配置报错,oracle em 启动报错OC4J Configuration issue
  4. 代码安全_弱点(脆弱性)分析 CWE
  5. 【接口测试】FitNesse中文指南
  6. filter过滤后重新添加_Kibana基本使用---使用Flight Dashboard过滤数据
  7. CCL“中国法研杯”相似案例匹配评测竞赛 - TOP队伍攻略分享
  8. python另存为excel_python 将数据保存为excel的xls格式(实例讲解)
  9. String相关知识点
  10. Mac上的GIF制作软件推荐
  11. diskgenius克隆硬盘无法启动_用Diskgenius克隆分区到另一个磁盘上
  12. word:如何从第三页插入目录
  13. IDA反汇编/反编译静态分析iOS模拟器程序(六)交叉引用
  14. 【Python】列表生成式应用的八重境界
  15. MySQL的my-innodb-heavy-4G.ini配置文件的翻译
  16. win10 系统更新后,插入移动硬盘忽然不认盘了
  17. 机器学习案例之Python中通过RF预测红酒质量
  18. 使用meb工具在线热备,将单实例切换为主从
  19. 【关于打印errno]
  20. 二分图(Bipartite Graph)

热门文章

  1. 自动驾驶3-2 安全保证和测试的行业方法 Industry Methods for Safety Assurance and Testing
  2. 价值连城 知名深度强化学习Pieter Abbeel的采访 给机器学习 深度学习 和机器人学研究者从业者的建议
  3. 图像分类数据集(Fashion-MNIST)
  4. ajax谷歌浏览器没缓存,从缓存AJAX请求会导致Chrome(Prevent Chrome from caching AJA
  5. Ubuntu 16.04安装Docker
  6. Model Representation--machine learning
  7. 类的加载器ClassLoader及其示例
  8. python 环形图_Python通过matplotlib画双层饼图及环形图简单示例
  9. “按字典序输出方案” 解决方法
  10. window下开启mysql慢查询和分割慢查询日志