什么是 AOP
AOP – Aspect Oriented Programming 的缩写,面向切面编程。
面向切面编程 AOP 是面向对象程序设计 OOP 的一个补充或扩大,是为了解决 OOP 在一些共性问题上的有余应运而生的。比方记录日志、事务处理、性能剖析等等与业务无关的需要,须要产生在很多类的很多办法上,而需要是一样的:比方日志解决就是在办法执行前或执行后记录日志,事务处理须要在办法执行前开启事务、在办法执行完结后提交或回滚事务。
AOP 呈现之前,老程序员应该都有记忆(亲身经历),咱们须要在每一个须要事务处理的办法中都增加逻辑截然不同的代码:获取连贯、开启事务。而后在办法执行实现后也须要增加截然不同的代码:如果办法执行胜利则提交事务、执行失败或产生异样则回滚事务。
这些代码写多了(其实不可能少、必定会很多),能让程序员痛苦不堪、狐疑人生!
而后,AOP 横空出世。
AOP 其实最终要实现的性能就是:不侵入代码的前提下,实现上述这些公共逻辑。
我艹,几乎不要太爽 ……
当然,横空出世的不是 Spring AOP,那个时候还没有 Spring。AOP 横空出世之后,为了对立 AOP 的概念、属于以及接口,呈现了 AOP 联盟,Spring AOP 也遵循 AOP 联盟的相干标准。之后,AOP 江湖逐步被 AspectJ 统治,Spring 从 2.0 开始就无缝集成了 AspectJ。
AOP 的底层逻辑其实不简单,就是通过代理:须要实现这些公共逻辑的类,咱们能够称之为指标类,不批改指标类、却要扭转(或者叫加强)其执行逻辑,用脚指头都能想到是通过代理。
AOP 的晚期版本(AspectJ 1.0)通过动态代理实现,动态代理是在编译期批改指标类代码、生成代理类代码的形式,运行会比拟快(因为在编译器就生成代理对象代码了),然而显著的毛病就是稍有批改就须要从新编译打包,不堪称不繁琐。
之后的 AOP 版本通过动静代理实现,动静代理咱们也很相熟,后面专门剖析过,是在运行期动静生成指标类的代理对象的,无非两种形式:
- JDK 动静代理,基于接口实现。
- Cglib 动静代理,生成指标类的扩大类实现。
具体请参考动静代理 java 原生 vs Cglib
所以咱们当初应该明确,AOP 是什么,为什么会有 AOP,以及 AOP 的底层原理。
AOP 术语
我始终在想,对于 AOP 的初学者,是通过间接上手练习的形式入门,还是依照惯例的形式:先学习 AOP 的实践,把握 AOP 的概念和术语,而后再通过简略示例增强了解。
惯例学习路线应该是后者,然而,尽管 AOP 的概念和底层逻辑很好了解,然而 AOP 的术语却极具迷惑性、十分不敌对,很难了解。
然而的确没有方法,要学习 AOP,那么 AOP 的术语就是迈不过来的一道坎,无论如何也是要有所理解的。
所以,来吧,看看 AOP 相干术语,咱们尽量用简单明了的语言来解释。
- Target object: 指标对象,指的就是咱们的业务对象,咱们要通过 AOP 技术加强指标对象的办法(对于 Spring Aop 来说,只加强指标对象的办法,对于 AOP 联盟来说,还能够加强属性)。
- AOP proxy:AOP 代理对象,后面曾经说过 AOP 的底层逻辑就是通过代理实现的,AOP proxy 指的就是指标对象的代理对象。
- Join point:连接点,其实是 AOP 要加强的点,对于 Spring AOP 来说,咱们要加强的其实就是指标对象的办法执行过程,所以连接点就是办法执行。
- Pointcut:切点,指的是满足条件的连接点,或者能够了解为满足切入连接点的条件。切点通过表达式的形式定义条件,满足切点条件的时候,执行切入动作、加强连接点规定的办法。
- Advice:加强逻辑,是 AOP 要实现的目标的体现,比方实现事务管理的 AOP,Advice 就是开启及提交或回滚事务,日志解决的 AOP,Advice 就是在连接点办法执行前后打印日志。
- Aspect: 切面,简略说就是体现连接点 Join point 定义、Pointcut 定义、以及 Advice 逻辑实现的模块(能够简略了解为:一组类)。Spring Aop 中通过 xml 配置文件指定、或者通过注解 @Aspect 指定。
- Introduction:推荐(其实不翻译最好,AOP 的这些术语其实都是这样,不翻译、直呼其英文名最好),能够这么了解:AOP 切面类中,除为了实现目标类办法加强之外,还能够定义其余的属性或办法,去帮忙实现 AOP 之外的额定的性能。
- Weaving:织入,就是依据 Aspect 的定义,对符合条件的指标对象,通过动静代理技术加强其办法逻辑、生成代理对象的过程。生成代理对象之后,就相当于咱们把 Advice“织入”到代理对象中了。
Spring AOP 的 Advice 类型:
- Before advice: 在 join point 执行前失效,然而 advice 没有拦挡阻止 join point 的能力,起因是 Spring Aop 的 Before advice 对指标对象的 join point 的调用控制权并不在切面类中,而是交给了框架,所以除非有异样产生、否则无奈拦挡或阻止 join point 办法的执行。
- After returning advice: join point 失常执行实现并返回后失效。
- After throwing advice: join point 调用异样后失效。
- After (finally) advice: join point 调用后失效,不论失常完结或抛出异样。
- Around advice: Spring AOP 性能最为弱小的 advice,功能强大的起因是:对 join point 的调用是在切面实现的,所以,切面编写者有权对 join point 调用前、调用后的逻辑做全面的管制,比方能够在调用前进行逻辑判断后阻止 join point 的调用,返回后面自定义的返回值或者抛出异样,也能够在 join point 调用后依据其返回值做任意的解决。
既然 Around advice 能够对 join point 做调用前、调用后的加强,而且其性能最为弱小,那是不是就意味着 before 和 after 加强就没有存在的意义了呢?无关这一点,Spring 官网其实也给出了一些倡议:
Around advice is the most general kind of advice. Since Spring AOP, like AspectJ, provides a full range of advice types, we recommend that you use the least powerful advice type that can implement the required behavior. For example, if you need only to update a cache with the return value of a method, you are better off implementing an after returning advice than an around advice, although an around advice can accomplish the same thing. Using the most specific advice type provides a simpler programming model with less potential for errors. For example, you do not need to invoke the proceed() method on the JoinPoint used for around advice, and, hence, you cannot fail to invoke it.
一句话:抉择刚好能满足本人需要的 Advice、而不倡议抉择性能远超出本人需要的 Advice,一方面简化切面逻辑,另一方面,缩小调用谬误的产生概率。
Spring AOP vs AspectJ
Spring AOP 仅反对对办法的切入,而 AspectJ 反对属性切入。
无关 Spring AOP 的能力和指标,其实 Spring 官网有专门的阐明:
Spring AOP’s approach to AOP differs from that of most other AOP frameworks. The aim is not to provide the most complete AOP implementation (although Spring AOP is quite capable). Rather, the aim is to provide a close integration between AOP implementation and Spring IoC, to help solve common problems in enterprise applications.
Spring AOP 与大部分的 AOP 框架不同,Spring AOP 的指标并不是提供一个功能强大的 AOP 实现(尽管说 Spring AOP 曾经比拟弱小了)。反而,Spring AOP 的髰提供一个将 AOP 和 Spring IoC 严密集成的框架从而对企业级利用的开发提供帮忙。
Thus, for example, the Spring Framework’s AOP functionality is normally used in conjunction with the Spring IoC container. Aspects are configured by using normal bean definition syntax (although this allows powerful “auto-proxying” capabilities). This is a crucial difference from other AOP implementations. You cannot do some things easily or efficiently with Spring AOP, such as advise very fine-grained objects (typically, domain objects). AspectJ is the best choice in such cases. However, our experience is that Spring AOP provides an excellent solution to most problems in enterprise Java applications that are amenable to AOP.
Spring AOP 的性能通常能够通过 Spring Ioc 容器提供,切面能够通过失常的 bean definition 实现配置,这是与其余 AOP 框架的显著不同点。咱们不太容易通过 Spring 框架实现细粒度的 AOP 管制。如果你有这样的需要,AspectJ 是更好的抉择。其实,Spring AOP 曾经能够解决企业应用开发中碰到的绝大部分 AOP 相干的问题。
Spring AOP never strives to compete with AspectJ to provide a comprehensive AOP solution. We believe that both proxy-based frameworks such as Spring AOP and full-blown frameworks such as AspectJ are valuable and that they are complementary, rather than in competition. Spring seamlessly integrates Spring AOP and IoC with AspectJ, to enable all uses of AOP within a consistent Spring-based application architecture. This integration does not affect the Spring AOP API or the AOP Alliance API. Spring AOP remains backward-compatible. See the following chapter for a discussion of the Spring AOP APIs.
Spring AOP 素来没想与 AspectJ 竞争、去提供一个弱小的 AOP 解决方案。咱们置信基于代理的框架比方 Spring AOP、以及全功能的框架比方 AspectJ,都是有价值的,是互补的关系,而不是竞争的关系。Spring 框架很好的继承了 Spring Aop、Spring IoC、以及 AspectJ,从而使用户能够在 Spring 框架下、基于 Spring 框架来应用 Aop。这种集成并没有影响 Spring Aop API 以及 AOP 联盟的 API,Spring AOP 确保向下兼容。
Spring AOP 与 AspectJ 反对的连接点的区别:
上一篇 Spring FrameWork 从入门到 NB – ApplicationContext