在看了很多网上的资料和记录之后,我大概捋了下SpringAOP的各种阶段:

  1. 基本的advice编程,利用ProxyFactory拿代理类
  2. 利用spring把ProxyFactory,advice等bean化
  3. 切面编程,在advisor中编写advice和pointcut
  4. SpringAOP实现自动代理,也就是说不用闲式地配置ProxyFactory,和从ProxyFactory中拿代理类了,SpringAOP帮你解决了这些东西。
  5. AspectJ风格的注解式的Aspect编程

先记录一下AOP的几个概念:

AOP:

首先,AOP是Aspect-Originted Programming,即面向切面编程。我觉得可以这样地简单理解,aop就是为了你更清楚的逻辑,让你的业务逻辑代码更清晰,不用去想其他事,像日志啊,权限啊这些和业务逻辑无关的东西。那要怎么用这些又很重要的功能呢?我们不用改变原来的代码,只要在另一个个地方,把这些要附加的功能打包好,然后运行的时候切进你要用这些功能的地方,aop其实大概就是这样。好的那就来看看下面的几个名词:

advice:

翻译成增强、通知,其实就是你要做的东西,你要切到你的代码中的功能。aop框架会把advice模拟成拦截器interceptor。

Join Point:

连接点,就是你可以加入功能,加入advice的地方。Spring只支持在方法或者是抛出异常的地方建立使用通知,也就是说这些地方都可以是joinpoint,像其他aop像aspectJ还可以让你在构造器或属性注入时加入advice。

Pointcut:

刚刚JoinPoint我们说了哪些地方可以用advice,但不是所有地方都要用advice啊,所以就有了这个pointcut,就是加上条件的joincut。在写代码的时候,会用类似正则表达式的方式去选择那些joinpoint来作为pointcut。

Aspect:

切面,这个可是个很重要的概念哦。其实就是advice+pointcut。Spring AOP就是负责实施切面的框架, 它将切面所定义的横切逻辑织入到切面所指定的连接点中.

AOP的工作重心在于如何将增强织入目标对象的连接点上, 这里包含两个工作:

  1. 如何通过 pointcut 和 advice 定位到特定的 joinpoint 上
  2. 如何在 advice 中编写切面代码.

Introduction:

翻译成引入,就是引入允许我们向现有的类添加新方法或属性,从而无需修改这些现有类的情况下,让他们具有新的行为和状态。Spring AOP 允许我们为 目标对象 引入新的接口(和对应的实现). 例如我们可以使用 introduction 来为一个 bean 实现 IsModified 接口, 并以此来简化 caching 的实现.

Target:

目标,要加入新功能,新advice的目标类。就是不知道什么情况然后等等要被我们切入新功能的那个类。

AOP proxy:

一个类被 AOP 织入 advice, 就会产生一个结果类, 它是融合了原类和增强逻辑的代理类. 在 Spring AOP 中, 一个 AOP 代理是一个 JDK 动态代理对象或 CGLIB 代理对象.   可以说,spring aop就是用动态代理来实现的,我理解的,就是我们要在一个target类中加入新功能嘛,就通过一个代理类来实现,代理类是原来目标类+advice的结合,可以想象成变强了的target类的替身。那么要怎样才能成为这个替身呢?要么就实现一样的接口(jdk动态代理的原理),要么就继承target类称为它的子类(CGLIB的原理)。

Weaving:

织入,将aspect和其他对象连接起来,并创建adviced object的过程。(可以把weaving理解成动词,introduction理解成名词)。根据不同的技术,weaving的方式有三种:编译器织入,要求有特制的编译器;类装载期织入,这需要特殊的类装载期器;动态代理织入,在运行期间为target添加advice的方式。

一、先是非常原始的advice实现

这里我们写一个非常原始的,连spring bean都不用的例子来帮助理解aop。写的是advice增强,用的是jdk代理的方式,也就是接口代理。但要先引入Spring aop的相关jar包

思路就是,要加强的类实现一个接口,然后advice作为加强类,要实现SpringAOP提供的Advice相关接口。然后通过ProxyFactory来拿代理类,往代理类中addAdvice来达到加强的效果。

这里我们有个Greeting接口。

package com.stuPayment.aopTest;public interface Greeting {public void sayHello(String name);public int saySth();
}

然后它的实现:

package com.stuPayment.aopTest;public class GreetingImpl implements Greeting {@Overridepublic void sayHello(String name) {// TODO Auto-generated method stubSystem.out.println("hello, " + name);}@Overridepublic int saySth() {// TODO Auto-generated method stubSystem.out.println("this is say sth");return 213;}public int sayMorning(String name) {System.out.println("good morning, " + name);return 123;}public void sayAfternoon(String name) {System.out.println("good afternoon, " + name);}
}

然后是我们的advice增强类,要这里我们用的是MethodBeforeAdvice接口和AfterReturningMethod,表示着advice是加在方法调用前还是方法返回之后。

package com.stuPayment.aopTest.advice;import java.lang.reflect.Method;import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;public class GreetingBeforeAndAfterAdvice implements MethodBeforeAdvice, AfterReturningAdvice{@Overridepublic void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {// TODO Auto-generated method stubSystem.out.println("this is after");}@Overridepublic void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {// TODO Auto-generated method stubSystem.out.println("this is before");}}

然后测试类:

package com.stuPayment.aopTest;import org.junit.Test;
import org.springframework.aop.framework.ProxyFactory;import com.stuPayment.aopTest.advice.GreetingAroundAdvice;
import com.stuPayment.aopTest.advice.GreetingBeforeAndAfterAdvice;public class Test1 {@Testpublic void demo1() {ProxyFactory proxyFactory = new ProxyFactory();//创建代理工厂proxyFactory.setTarget(new GreetingImpl());//注入目标类对象proxyFactory.addAdvice(new GreetingBeforeAndAfterAdvice());//添加前置加强和后置加强//proxyFactory.addAdvice(new GreetingAroundAdvice());//添加前置加强和后置加强Greeting greeting = (Greeting)proxyFactory.getProxy();//从代理工厂中获取代理greeting.sayHello("Ben");//调用代理的方法
        greeting.saySth();}
}

结果:

所以大概思路就是,编写一个增强类去实现Spring aop提供的几个advice的接口(其实这些接口就是决定在接入点的哪个位置加入新advice),然用aop给的ProxyFactory,先设定一个target,然后addAdvice来加入你要切入的功能,然后你就可以通过这个代理工厂来获得一个代理类(对应接口的),一个加强后的adviced object,调用它里面方法就会看到advice的效果。

然后SpringAop给了好几种Advice的增强接口:

二、一般,到了后面,我们会把这个Proxy的配置加入Spring的配置文件中

这个greetingAroundAdvice就像我们刚刚那个GreetingBeforeAndAfterAdvice一样是个实现了一个advice接口的增强类。

这里再介绍一下一个Introduction Advice,来看看jdk动态代理和CGLIB类代理的区别。

上面说到,这个引介增强Introduction Advice是一种特殊的增强,之前的连接点都是方法级别的,而这个是类级别的,也就是对类的加强。

引入增强Introduction Advice的概念:一个Java类,没有实现A接口,在不修改Java类的情况下,使其具备A接口的功能。

先定义一个新接口Love:

然后定义授权引入增强类:

这个DelegatingIntroductionInterceptor就是一个引入的advice类,继承它就有这种advice的能力。

然后是Proxy的配置:

proxyTargetClass属性表示是否代理目标类,默认是false,也就是代理接口,上面一个例子的配置就是没有这一项属性所以用JDK动态代理,现在是true即使用CGLib动态代理。

然后看测试方法里面:

首先看到,从代理里面拿这个GreetingImpl的时候,不是像以前一样:Greeting greeting = (Greeting).......

而是直接用实现类GreetingImpl来拿。因为现在是代理目标类而不是接口类。

然后是这里的Love love = (Love)greetingImpl是将目标类强制向上转换成了Love接口,但注意,我们并没有把这个greetingImpl实现这个Love接口哦,这就是引用增强(DelegatingIntroductionInterceptor)的特性——“接口动态实现的”功能。所以display()方法可以由GreetingImpl的对象来调用,只需要强行转换接口就行了。

三、好了,在advice的层次下的编程之后,就到了后面aspect切面的编程了:

所谓切面,其实就是advice+pointcut,我们在切面中一般要做的就是定义要加的功能还有正则表达式确定要拦截的方法。

这里开始内容就很多了,也有点乱,这里稍微捋一下,迟点会通过阅读相关的书籍来理清楚关系。

切面编程一开始,我们可以通过springAOP提供的切面类RegexpMethodPointcutAdvisor来配置切面。一样还是刚刚的实现了Greeting的GreetingImpl作为target,配置文件如下:

这上面的proxy中的配置中的InterceptorNames,不再是之前的advice加强了,而是一个定义好的切面。我们看这个greetingAdvisor的bean的配置,可以看到一个属性是advice,而另一个是pattern,其实就相当于要加强的功能和pointcut。

再往后发展,proxy也不用怎么写配置了,有了个叫aop自动代理的东西,大概就是spring框架自动生成代理:

配置文件:(属性optimize为true,表示,如果target有接口,就用jdk动态代理,若谷target没有接口,就用CGLib动态代理)

还有测试代码:

此时因为是自动代理,getBean()的值不再是原来的代理id(greetingProxy),而是目标类GreetingImpl的bean的id,这同样也是个代理类,只是自动代理,隐藏了代理的工作和代码。

再往后,就到了AspectJ风格的切面编程,用注解就可以完成切面的编程,大大节省了配置的时间。

 

 

先是利用<aop:config>元素声明切面的方法,配置文件类似于下图的xml:

也可以直接使用@Aspect注解,只需要配置文件中简单得配置一下自动代理:

<context:component-scan base-package="demo.spring"/>  <!-- 用@Component自动发布bean,需要配置这个元素。 --><aop:aspectj-autoproxy />     <!-- 使用@AspectJ及其它AOP注解需要配置,否则无法使用注解;@AspectJ注解,将@Component自动发布出来的"interceptor" bean转换为一个aspectj切面,而@Pointcut、@Before、@After、@Around等注解,功能与在xml文件中配置是一样的;@Pointcut注解下面的方法内容无意义,只是要求一个相应方法提供注解依附。 -->

注解只能在使用能获得源码的场景,如果不能获取源码,则只能通过xml配置的形式,将指定的对象配置成拦截器,对指定的目标进行拦截;因此,通过xml文件配置,而不是注解,是更加通用的方式。

然后再下一篇博客,会记录如何在Springboot用AspectJ风格的注解来用SpringAOP实现一个日志记录的功能。

参考过的博客:

https://blog.csdn.net/h525483481/article/details/79625718

https://blog.csdn.net/icarus_wang/article/details/51737474 讲增强类型的

https://www.cnblogs.com/jacksonshi/p/5863313.html

转载于:https://www.cnblogs.com/wangshen31/p/9375231.html

梳理一下我理解的aop相关推荐

  1. 从面向对象设计思想出发理解Spring AOP编程

    都说AOP是OOP(面向对象)的继承与延续,我觉得理解AOP还是得从OOP出发,经历从暴露问题到解决问题的过程. 目录 一. 面向对象设计思想(OOP) (1)概述 1. POP编程 2. OOP的优 ...

  2. 彻底理解Spring AOP

    目录 前言 1. AOP概念 2. AOP的实现 3. Spring的IoC理解: 4. Sping知识整理 前言 AOP英文名为Aspect Oriented Programming,意为面向切面编 ...

  3. 正确理解Spring AOP中的Around advice

    Spring AOP中,有Before advice和After advice,这两个advice从字面上就可以很容易理解,但是Around advice就有点麻烦了. 乍一看好像是Before ad ...

  4. 如何理解 Spring AOP 以及使用 AspectJ?

    作者 | 阿文 责编 | 屠敏 出品 | CSDN(ID:CSDNnews) 在 Spring 中 AOP 是一个非常非常重要的概念,那么什么是AOP呢? AOP 即面向切面编程,也可以叫做面向方向编 ...

  5. java @around_正确理解Spring AOP中的Around advice

    Spring AOP中,有Before advice和After advice,这两个advice从字面上就可以很容易理解,但是Around advice就有点麻烦了. 乍一看好像是Before ad ...

  6. 结合代码彻底理解Spring AOP的术语

    每本Spring的书在介绍AOP之前,总能有一箩筐的术语,看半天似懂非懂,也就没兴趣再继续学习下去,其实并没有这么复杂. 难懂的定义我们就不贴了,就说说咱们通俗的解释,下面让我们结合代码来理清楚各个术 ...

  7. 面试官:谈谈你对IOC和AOP的理解及AOP四种实现方式

    目录 一.IOC与AOP介绍 二.实现AOP的四种方式 方式1:基于经典代理来实现 方式2:使用Spring AOP的API接口 方式3:自定义类来实现AOP 方式4:基于注解实现 一.IOC与AOP ...

  8. IOC的理解,整合AOP,解耦对Service层和Dal层的依赖

    DIP依赖倒置原则:系统架构时,高层模块不应该依赖于低层模块,二者通过抽象来依赖 依赖抽象,而不是细节 贯彻依赖倒置原则,左边能抽象,右边实例化的时候不能直接用抽象,所以需要借助一个第三方 高层本来是 ...

  9. 深入理解Spring AOP思想

    什么是AOP?AOP解决了什么问题? 在传统的开发模式中,以下层次的是非常常见的一种,业务层每一个方法都要有重复的事务代码 如何改善这个问题? AOP希望将A.B 这些分散在各个业务逻辑中的相同代码, ...

最新文章

  1. 阿里与腾讯人的区别,就是明教与武当的反差
  2. 开源日志系统log4cplus(三)
  3. [html] 回到页首
  4. 面试题整理 | 45道CSS面试题
  5. 如何查看oracle客户端的版本,如何查看Oracle客户端版本
  6. LDO芯片数据手册怎么看?
  7. 物联网轻松上云实践 之 HaaS样板间
  8. C#多线程和线程池 【转】
  9. [小白slam攻略]ROVIO安装运行及保存轨迹用evo评估
  10. 数据结构的小知识点(初学者使用)“朝闻道”知识分享大赛
  11. Java核心技术卷一笔记
  12. 信息安全的前景如何?就业渠道有哪些?
  13. AtCoder Beginner Contest 163 A Circle Pond 圆周率
  14. MyOS(三):软盘读写
  15. 竞选班长的演讲稿_1500字
  16. 抖音多帧延迟教你前端实现方式
  17. 想教小学计算机面试报哪个,小学教师资格证面试,建不建议考信息技术?
  18. 使用JAVA对接跨境贸易电子商务数据交换接口拼接xml
  19. 对智博教育的midia-class(奥义多媒体教室)(0ss-midia-class)的破解②(共两部分)
  20. Spring的Environment类的使用

热门文章

  1. linux安装redis 完整步骤
  2. 268. Missing Number
  3. JAVA课程设计——“小羊吃蓝莓”小游戏
  4. web设计页面跳转的方法
  5. 《JS权威指南学习总结--第九章 类和模板》
  6. 关于navicat连接oracle 报 ORA-12737 set CHS16GBK错误的解决方法
  7. java集合框架(Framework)的性能
  8. 解决grub引导错误的问题
  9. 架构师书单 2nd Edition
  10. 今天写了个Win32服务设置软件,呵呵,纯绿色软件