一.AOP

  1. AOP:中文名称面向切面编程

  2. 英文名称:(Aspect Oriented Programming)

  3. 正常程序执行流程都是纵向执行流程
    3.1 又叫面向切面编程,在原有纵向执行流程中添加横切面
    3.2 不需要修改原有程序代码
    3.2.1 高扩展性
    3.2.2 原有功能相当于释放了部分逻辑.让职责更加明确.

  4. 面向切面编程是什么?
    4.1 在程序原有纵向执行流程中,针对某一个或某一些方法添加通知,形成横切面过程就叫做面向切面编程.

  5. 常用概念
    5.1 原有功能: 切点, pointcut
    5.2 前置通知: 在切点之前执行的功能. before advice
    5.3 后置通知: 在切点之后执行的功能,after advice
    5.4 如果切点执行过程中出现异常,会触发异常通知.throws advice
    5.5 所有功能总称叫做切面. 5.6 织入: 把切面嵌入到原有功能的过程叫做织入

  6. spring 提供了 2 种 AOP 实现方式
    6.1 Schema-based
    6.1.1 每个通知都需要实现接口或类
    6.1.2 配置 spring 配置文件时在<aop:config>配置
    6.2 AspectJ
    6.2.1 每个通知不需要实现接口或类
    6.2.2 配置 spring 配置文件是在<aop:config>的子标签<aop:aspect>中配置

二. Schema-based 实现步骤

  1. 导入 jar

  2. 新建通知类
    2.1 新建前置通知类
    2.1.1 arg0: 切点方法对象 Method 对象
    2.1.2 arg1: 切点方法参数
    2.1.3 arg2:切点在哪个对象中

public class MyBeforeAdvice implements  MethodBeforeAdvice {@Overridepublic void before(Method arg0, Object[] arg1, Object  arg2) throws Throwable {System.out.println("执行前置通知");}
}

2.2 新建后置通知类
2.2.1 arg0: 切点方法返回值
2.2.2 arg1: 切点方法对象
2.2.3 arg2: 切点方法参数
2.2.4 arg3: 切点方法所在类的对象

public class MyAfterAdvice implements  AfterReturningAdvice {@Overridepublic void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {System.out.println("执行后置通知");}
}
  1. 配置 spring 配置文件
    3.1 引入 aop 命名空间
    3.2 配置通知类的<bean>
    3.3 配置切面
    3.4 * 通配符,匹配任意方法名,任意类名,任意一级包名
    3.5 如果希望匹配任意方法参数 (…)
<?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/sc
hema/beans
http://www.springframework.org/schema/beans/spring-be
ans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.
xsd"><!-- 配置通知类对象,在切面中引入 --><bean id="mybefore"  class="com.bjsxt.advice.MyBeforeAdvice"></bean><bean id="myafter"  class="com.bjsxt.advice.MyAfterAdvice"></bean><!-- 配置切面 --><aop:config><!-- 配置切点 --><aop:pointcut expression="execution(*com.bjsxt.test.Demo.demo2())" id="mypoint"/><!-- 通知 --><aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/><aop:advisor advice-ref="myafter"  pointcut-ref="mypoint"/></aop:config><!-- 配置 Demo 类,测试使用 --><bean id="demo" class="com.bjsxt.test.Demo"></bean>
</beans>
  1. 编写测试代码
public class Test {public static void main(String[] args) {// Demo demo = new Demo();// demo.demo1();// demo.demo2();// demo.demo3();ApplicationContext ac = newClassPathXmlApplicationContext("applicationContext.xml");Demo demo = ac.getBean("demo",Demo.class);demo.demo1();demo.demo2();demo.demo3();}
}
  1. 运行结果:

三. 配置异常通知的步骤(AspectJ 方式)

  1. 只有当切点报异常才能触发异常通知
  2. 在 spring 中有 AspectJ 方式提供了异常通知的办法. 2.1 如果希望通过 schema-base 实现需要按照特定的要求自己编写方法.
  3. 实现步骤:
    3.1 新建类,在类写任意名称的方法
public class MyThrowAdvice{public void myexception(Exception e1){System.out.println("执行异常通知"+e1.getMessage());}
}

3.2 在 spring 配置文件中配置
3.2.1 <aop:aspect>的 ref 属性表示:方法在哪个类中.
3.2.2 <aop: xxxx/> 表示什么通知
3.2.3 method: 当触发这个通知时,调用哪个方法
3.2.4 throwing: 异常对象名,必须和通知中方法参数名相同(可以不在通知中声明异常对象)

<bean id="mythrow"  class="com.bjsxt.advice.MyThrowAdvice"></bean><aop:config><aop:aspect ref="mythrow"><aop:pointcut expression="execution(*com.bjsxt.test.Demo.demo1())" id="mypoint"/><aop:after-throwing method="myexception" pointcut-ref="mypoint" throwing="e1"/></aop:aspect></aop:config>
<bean id="demo" class="com.bjsxt.test.Demo"></bean>

四. 异常通知(Schema-based 方式)

  1. 新建一个类实现 throwsAdvice 接口
    1.1 必须自己写方法,且必须叫 afterThrowing
    1.2 有两种参数方式
    1.2.1 必须是 1 个或 4 个
    1.3 异常类型要与切点报的异常类型一致
public class MyThrow implements ThrowsAdvice{// public void afterThrowing(Method m, Object[] args,Object target, Exception ex) {// System.out.println("执行异常通知");// }public void afterThrowing(Exception ex) throws Throwable {System.out.println("执行异常通过-schema-base 方式");}
}
  1. 在 ApplicationContext.xml 配置
<bean id="mythrow"  class="com.bjsxt.advice.MyThrow"></bean>
<aop:config><aop:pointcut expression="execution(*com.bjsxt.test.Demo.demo1())" id="mypoint"/><aop:advisor advice-ref="mythrow"  pointcut-ref="mypoint" />
</aop:config>
<bean id="demo" class="com.bjsxt.test.Demo"></bean>

五.环绕通知(Schema-based 方式)

  1. 把前置通知和后置通知都写到一个通知中,组成了环绕通知
  2. 实现步骤
    2.1 新建一个类实现 MethodInterceptor
public class MyArround implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation arg0) throwsThrowable {System.out.println("环绕-前置");Object result = arg0.proceed();//放行,调用切点方式System.out.println("环绕-后置");return result;}
}

2.2 配置 applicationContext.xml

<bean id="myarround"
class="com.bjsxt.advice.MyArround"></bean>
<aop:config>
<aop:pointcut expression="execution(*
com.bjsxt.test.Demo.demo1())" id="mypoint"/>
<aop:advisor advice-ref="myarround"
pointcut-ref="mypoint" />
</aop:config>
<bean id="demo" class="com.bjsxt.test.Demo"></bean>

六.使用 AspectJ 方式实现

  1. 新建类,不用实现
    1.1 类中方法名任意
public class MyAdvice {public void mybefore(String name1,int age1){System.out.println("前置"+name1 );}public void mybefore1(String name1){System.out.println("前置:"+name1);}public void myaftering(){System.out.println("后置 2");}public void myafter(){System.out.println("后置 1");}public void mythrow(){System.out.println("异常");}public Object myarround(ProceedingJoinPoint p) throwsThrowable{System.out.println("执行环绕");System.out.println("环绕-前置");Object result = p.proceed();System.out.println("环绕后置");return result;}
}

1.2 配置 spring 配置文件
1.2.1 <aop:after/> 后置通知,是否出现异常都执行
1.2.2 <aop:after-returing/> 后置通知,只有当切点正确执行时
执行
1.2.3 <aop:after/><aop:after-returing/><aop:after-throwing/>执行顺序和配置顺序有关
1.2.4 execution() 括号不能扩上 args
1.2.5 中间使用 and 不能使用&& 由 spring 把 and 解析成&&
1.2.6 args(名称) 名称自定义的.顺序和 demo1(参数,参数)对应
1.2.7 <aop:before/> arg-names=” 名 称 ” 名 称 来 源 于expression=”” 中 args(),名称必须一样
1.2.7.1 args() 有几个参数,arg-names 里面必须有几个参数
1.2.7.2 arg-names=”” 里面名称必须和通知方法参数名对应

<aop:config><aop:aspect ref="myadvice"><aop:pointcut expression="execution(*com.bjsxt.test.Demo.demo1(String,int)) andargs(name1,age1)" id="mypoint"/><aop:pointcut expression="execution(*com.bjsxt.test.Demo.demo1(String)) and args(name1)" id="mypoint1"/><aop:before method="mybefore" pointcut-ref="mypoint" arg-names="name1,age1"/><aop:before method="mybefore1" pointcut-ref="mypoint1" arg-names="name1"/><!-- <aop:after method="myafter"pointcut-ref="mypoint"/><aop:after-returning method="myaftering"pointcut-ref="mypoint"/><aop:after-throwing method="mythrow"pointcut-ref="mypoint"/><aop:around method="myarround"pointcut-ref="mypoint"/>--></aop:aspect>
</aop:config>

七. 使用注解(基于 Aspect)

  1. spring 不会自动去寻找注解,必须告诉 spring 哪些包下的类中可能有注解
    1.1 引入 xmlns:context
<context:component-scan
base-package="com.bjsxt.advice"></context:component-scan>
  1. @Component
    2.1 相当于****
    2.2 如果没有参数,把类名首字母变小写,相当于<bean id=””/>
    2.3 @Component(“自定义名称”)
  2. 实现步骤:
    3.1 在 spring 配置文件中设置注解在哪些包中
<context:component-scan
base-package="com.bjsxt.advice,com.bjsxt.test"></context:component-scan>

3.2 在 Demo 类中添加@Componet
3.2.1 在方法上添加@Pointcut(“”) 定义切点

@Component
public class Demo {@Pointcut("execution(*com.bjsxt.test.Demo.demo1())")public void demo1() throws Exception{// int i = 5/0;System.out.println("demo1");}
}

3.3 在通知类中配置
3.3.1 @Component 类被 spring 管理
3.3.2 @Aspect 相当于<aop:aspect/>表示通知方法在当前类中

@Component
@Aspect
public class MyAdvice {@Before("com.bjsxt.test.Demo.demo1()")public void mybefore(){System.out.println("前置");}@After("com.bjsxt.test.Demo.demo1()")public void myafter(){System.out.println("后置通知");}@AfterThrowing("com.bjsxt.test.Demo.demo1()")public void mythrow(){System.out.println("异常通知");}@Around("com.bjsxt.test.Demo.demo1()")public Object myarround(ProceedingJoinPoint p) throwsThrowable{System.out.println("环绕-前置");Object result = p.proceed();System.out.println("环绕-后置");return result;}
}

AOP 详解 、AOP 中通知类型 、AOP 两种实现方式(Schema-base 和 AspectJ)相关推荐

  1. sh执行文件 参数传递_详解shell中脚本参数传递的两种方式

    方式一:$0,$1,$2.. 采用$0,$1,$2..等方式获取脚本命令行传入的参数,值得注意的是,$0获取到的是脚本路径以及脚本名,后面按顺序获取参数,当参数超过10个时(包括10个),需要使用${ ...

  2. java中字符串的创建_【转载】 Java中String类型的两种创建方式

    本文转载自 https://www.cnblogs.com/fguozhu/articles/2661055.html Java中String是一个特殊的包装类数据有两种创建形式: String s ...

  3. 集合详解(三)----Map的两种遍历方式

    第一种取值方式 第二种取值方式 Map是以键值对(key-value)的方式来存取值的,那么该怎么把Map中的值取出来的,有两种方式,往下看.先定义一个Map,向里面存放一些数据. HashMap m ...

  4. python中list[1啥意思_详解Python中list[::-1]的几种用法

    本文主要介绍了Python中list[::-1]的几种用法,分享给大家,具体如下: s = "abcde" list的[]中有三个参数,用冒号分割 list[param1:para ...

  5. 【JNU】网络配置大题详解(E口与G口两种类型)

    [JNU]网络配置大题详解(E口与G口两种类型) E口与G口的不同之处 E口的SW1配置 G口的SW1配置 RT1配置 RT2配置 RT3配置 E口运行结果 G口运行结果 E口与G口的不同之处 如果你 ...

  6. java 调用枚举种方法_Java中枚举类型的一种使用方式

    今天改同事的代码发现同事的代码中有大量的if else语句.很不美观而且可读性太差. 因为需要给前端一个key,value的列表.这个列表写死.然而同事的代码. 放几张图,大家自己感受.我都不知道以后 ...

  7. python解释器在哪里_详解查看Python解释器路径的两种方式

    进入python的安装目录, 查看python解释器 进入bin目录 # ls python(看一下是否有python解释器版本) # pwd (查看当前目录) 复制当前目录即可 1. 通过脚本查看 ...

  8. js定义全局变量 vue页面_详解Vue.js 定义全局变量的几种实现方式

    详解Vue.js 定义全局变量的几种实现方式 发布于 2020-8-11| 复制链接 本篇文章主要介绍了VUE 全局变量的几种实现方式,小妖觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小妖 ...

  9. java map遍历_Java中Map集合的两种遍历方式

    Java中的map遍历有多种方法,从最早的Iterator,到java5支持的foreach,再到java8 Lambda,让我们一起来看下Java中Map集合的两种遍历方式! 关于遍历Map集合的几 ...

  10. java中两种遍历集合的方式_Java中Map集合的两种遍历方式

    Java中的map遍历有多种方法,从最早的Iterator,到java5支持的foreach,再到java8 Lambda,让我们一起来看下Java中Map集合的两种遍历方式! 关于遍历Map集合的几 ...

最新文章

  1. Windows Server 2003 : 服务器群集
  2. jni和java之间字符串的转换
  3. FFTW、Eigen库在VisualStudio中的导入和使用
  4. QDU第一届程序设计大赛——E到I题解法(非官方题解)
  5. Node.js—简介
  6. 数据结构与算法笔记(十三)—— 树与树的算法
  7. 空间刚架matlab_Matlab绘制空间几何图
  8. 中国网络出版产业盈利模式与投资前景形势研究报告2022版
  9. [LeetCode]Count of Range Sum
  10. 如何学人工智能的思考
  11. SQL(二)- 基础查询语句
  12. 机器学习中的数学基础相关知识总结
  13. Ubuntu的奇技淫巧
  14. silverlight中datagrid数据到处excel
  15. 数据库学习----MySQL(二)
  16. linux网络子系统分析(三)—— 设备无关层
  17. md5算出来不一样_西安美发培训学校:为什么我看到的色卡上的颜色和染出来的颜色会不一样呢?...
  18. 【图像重建】基于matlab主成分分析图像压缩重建【含Matlab源码 1173期】
  19. easyMule-VeryCD-src---VS2010调试笔记
  20. python代码编程教学无限循环_代码陷入无限循环

热门文章

  1. 数据结构Java版之查找算法(三)
  2. Oracle 中启用 scott 用户 的方法
  3. 使用PDO连接数据库 查询和插入乱码的解决方法
  4. CMS系统模板引擎设计(5):Label应用初探
  5. 有段时间没更新了。。。放上我在做的东东的截图
  6. jQuery——入门(三)JQuery DOM操作(核心处理和文档处理)
  7. 【ES6】Set Map数据结构、Iterator遍历器
  8. 7-2 图形卡片分组游戏 (60 分)
  9. 6-4 单链表插入排序 (15分)
  10. eclipse设置jsp文件编码默认为UTF-8