AOP深刻理解

来源:互联网 发布:ubuntu 17.04 iso安装 编辑:程序博客网 时间:2024/05/16 12:56

AOP(Aspect-Oriented Programming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。

使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”

举个例:我口渴啦,要拿杯子接水,这是一系列动作过程,我口渴的时间点和口渴的事件,拿杯子到饮水机接水的时间点和接水的事件,等等如此之类的逻辑事物点都作记录

未完待续。。。。。


关于AOP相关概念理解

    联接点(Jointpoint)是一个程序执行过程中的特定时刻。例如方法调用的时候,类初始化的时候,之类的。但是Spring的联结点就一个——方法调用。另外,要注意的是,程序执行的过程本身,也可以抽象成一个联接点,只不过Spring不支持罢了。联结点,说白了,就是一个事件,它告诉AOP什么时候调用通知。在Spring中就联接点就意味这一件事,出现方法调用的时候,就该通知出场执行AOP业务逻辑了。

    通知(Advice),就是下面大括号所指向的部分哦。说白了,所谓通知就是实现AOP业务逻辑的地方,也就是说,通知是你应该实现的,具体如何处理AOP业务逻辑的类。根据通知出现位置的不同,即其业务逻辑所覆盖的范围不同,称呼也不同。Spring中一共五种通知:

    前置通知(MethodBeforeAdvice)
    后置通知(AfterReturningAdvice)
    包围通知(MethodIntercepter)
    抛出通知(ThrowAdvice)
    引入(IntroductionIntercepter)


怎么理解这5中通知呢?不妨打个比喻,假设你是老板,你手下有个高参(AOP)。

    现在,你要投资一个项目了(联接点,这里比喻方法调用)。你的高参会在你投资前,提前给你一份企划书,其中包括了这个投资(方法调用)之前应该怎么准备 (在联接点之前应该做些什么预处理AOP逻辑)、投资过程和投资后应该注意些什么(方法调用结束之后做些什么)。这个企划书事关全局,整个就是围绕这你的 投资展开的,你的投资(方法调用)只是其中的一部分,那么这个建议就相当于Spirng AOP中的包围通知.

   它可以在目标方法(投资)执行之前或之后运行,也可以自定义什么时候调用目标方法(别忘了出企划的是高参,它自身可以考虑什么时候帮助你执行企划中的特别部分),当然也可以自己编写逻辑嗲用完全不同的目标方法(如果以前的企划不成立,就重新确立一个吧)。

    当然,企划和具体实施是两码事。当要具体实施的时候(投资前,即方法调用之前),发生了一些变数,要针对这些变数进行修正,并使其朝着有利于投资的方面发展,这些工作即提前建议,(Advice这个词,在Spring AOP中被翻译为通知),换成Spring的AOP术语就是前置通知。

    前置通知可以访问被调用的目标方法(高参当然首先要知道你要干什么,然后才能告诉你该怎么干)和参数(高参给你准备的一些额外的关系和投资建议等等,帮助 你决策如何投资),但是它不能影响方法调用本身(因为高参不是你,所以它不是老板,自然不能决定是否要投资,它只能提建议——advice)。

貌似一切顺利的执行了投资,但是在投资过程中你这个老板发现,有些问题是你之前没有预料到的,这些确实是个意外。所以你将这些意外告诉了你的高参(抛出异 常)。高参不愧是高参,人家早就想到了(但是“我就是不说”——《电梯》,姜昆相声中的台词)。于是立即调用了特别准备的应急预案,对异常进行处理。换作 Spring AOP的术语就是抛出通知。

    抛出通知使得我们可以根据需要只接受到特定的异常(高参关心的是某些严重问题,一般问题老板都可以自己摆平了~~),这样,就可以知道哪里出了异常——出现异常的方法、目标方法和其参数。

投资结束了,你的盈利或许会比预期的多,或许少于预期。你让高参帮忙分析,此时高参手里早就握有你投资前的准备,还有你投资的过程以及投资的结果,高参会根据这些资料分析你的得失,做出进一布调整的建议,帮你调整决策。这个么,就是后置通知。

    显然,方法调用已经完成。它可以访问的有被调用的目标方法(投资项目),该方法的参数(投资的准备工作和使用的决策等)和返回值(当然是投资的结果)。因 为方法调用已经完成,所以后置通知完全不能影响方法调用本身的事情。(对于既定的事实,无论是成功还是失败,高参都只能根据过去向前看,当然不能改变过去 了)

    关于引入通知。Spring其实将引入过程当成一个特殊的拦截器,就是一旦发生引入了,Spring就给他拦截下来,并执行相应的处理。就好比,一旦有人要入关,那么就会接到海关的盘查一样。关于引入通知的内容,以后会详述。


    正像定义中所说的那样,切入点其实就是一组联接点。在Spring中就可以理解为某个类实例的所有方法的调用(图中紫色实心圆)。我们不关心方法被调用的时间,只关心它是否是即将被调用的这个事件。因为Spring中的联接点只有一种——方法调用,所以切入点也只能有一种,方法调用这个事件所组成的集合。

    继续用高参来解释。就是说高参给你建议的前提是,不在乎你做出什么时候决策(投资、会见客人或者其他),而是,当你做出决策这件事情的发生。当高参看到你 要做决策了,他就会在你做决策前给你建议(Advice,通知)。也正式因为有了这个机制,所以你才能在做每件商业活动的时候都能精确的受到来自高参的建 议,也就是Spring AOP中所讲的,精确的控制程序中什么组件(操作)接到什么通知。
 
    所谓方面(Aspect), 就是通知和切入点的组合。换言之,它是一揽子解决方案,即你的商业决策(投资、会见客人或者其他)和高参根据这些决策给你的不同的建议(Advice,通 知)。呵呵,到这里说AOP就更明白了。你,老板,执行的是线性商业(business,业务)逻辑,而你的高参(AOP),则在你身旁,根据你的决策提 建议,帮你从即要自己提自己的建议又要执行商业逻辑的苦恼中解脱出来,好让你可以专心的经营生意。这个不就是AOP的真谛么!它不在于取代你(OOP)的 位置,它只是帮助你,让你少点烦心事,更能关注你自己的业务。另外AOP本身不也是OOP写的么(难道老板是人类,高参就不是人类)。虽然,你缺少高参一 样能干活,但是累。正像OOP没有AOP也一样能工作。但是AOP没了OOP的基础就不成(因为首先是人类才有肯能成为你的高参,动物没这个能力吧;另一 方面,也说明了高参这个群体没有老板群体,也就失去了存在的意义,失业了)。

织入(Weaving),可以理解成为高参的建议是如何被你采纳的方式(过程)。如果 是你事先就把高参的建议背的滚瓜乱熟、了然于胸,那么遇到相应的情况自然会采取相应的对策。这个就是静态AOP的意义,将AOP逻辑直接写入到目标类的字 节码中,好让目标类的字节码文件可以像调用自身方法一样调用AOP业务逻辑,所以效率高。但是遇到高参也没有预料的情况,就只能傻眼了(回去问高参的话, 那个是动态AOP了)。但是如果你开始根本就没有看高参的建议,那么遇到了相应的情况自然临时抱佛脚,赶紧去看高参的建议,自然效率低。这个就是动态的 AOP,可以勉强这么理解。缺点是效率低,优点是,可能有些情况高参原来也没有遇到,所以你这个时候求助于高参,也会得到解答。
 
目标(Target),当然就是高参提供建议给他的对象了,也就是你,老板了。
 
引入(Introduction)。OK,终于遇到你自己无法解决的问题了,而且这个问题用 高参的建议也不成,怎么办?这个时候高参亲自出面代替你了,帮你摆平,当然铲事儿的手段是你所不具备的,这个就是引入。引入的目的就是在一个对象中加入新 的方法或者属性,以改变它的结构,帮助你完成原来不能完成的事情。


而AOP的概念用的最好的框架就是SPRING,下面附属谈谈SPRING-AOP

AOP:面向切面编码:
1、AOP学习目标:
使所需要的功能能够加在任何类中,而不需要调用。
①借助于Spring编写一个自己的切面,加到任何一个Java中;
②Spring本身也提供了编写好的切面功能。
切面有最大程度的复用性,耦合度趋于零。在事务方面,AOP用得较成功。
2、代理的两种方式:
 静态代理:
 针对每个具体类分别编写代理类;
 针对一个接口编写一个代理类;
 动态代理:
 针对一个方面编写一个InvocationHandler,然后借用JDK反射包中的Proxy类为各种接口动态生成相应的代理类
AOP的主要原理:动态代理  研究一下动态代理的写法。
3、AOP中思想和名词术语:
 Aspect:方面,层面
 Joinpoint:结合点、联结点;加入业务流程的点或时机
 Pointcut:切入点、作用点;指定某个方面在哪些联结点织入到应用程序中
 Advice:通知、行为;某个方面的具体实现,代表了一个动作. 
 Advisor:由Pointcut和Advice共同构成
 Pointcut:Spring根据类名称及方法名称定义Pointcut,表示Advice织入至应用程序的时机; org.springframework.aop.Pointcut
 ProxyFactoryBean:用来创建代理对象
创建代理对象需指定的三要素:
①target:设定目标对象(只能是一个);
②proxyInterfaces:设定代理接口(目标对象所实现的接口);
③interceptorNames:设定拦截器的名字(各个advice或advisor bean的列表)
Advice:五种(根据织入的时机不同而划分)
Before Advice:在目标对象的方法执行之前加入行为;
要实现的接口:org.springframework.aop.MethodBeforeAdvice
After Advice:在目标对象的方法执行之后加入行为;
要实现的接口:org.springframework.aop.AfterReturningAdvice
Throw Advice:在目标对象的方法发生异常时加入行为;
要实现的接口:org.springframework.aop.ThrowsAdvice
Around Advice:在目标对象的方法执行前后加入行为;
要实现的接口:org.aopalliance.intercept.MethodInterceptor
Introduction Advice:引入的行为(增加了可操作的方法)。
声明要添加的功能接口;
创建引入Advice;
(继承org.springframework.aop.support.DelegatingIntroductionInterceptor,并实现添加的功能接口)
在配置文件中定义一个DefaultIntroductionAdvisor的bean。
(需要两个构造方法的参数:Advice和添加的功能接口)
PointcutAdvisor:Pointcut定义了Advice的应用时机;在Spring中,使用PointcutAdvisor将Pointcut和Advice结合为一个对象。
NameMatchMethodPointcutAdvisor:可用来指定Advice所要应用的目标对象上的方法名称
RegexpMethodPointcutAdvisor:可使用Regular expression定义Pointcut,在符合Regular expression的情况下应用Advice,其pattern属性用来指定所要符合的完整类名(包括 package名称)及方法名;
AutoProxy:自动代理
BeanNameAutoProxyCreator:根据bean的名字为其自动创建代理对象,bean工厂自动返回其代理对象:

原创粉丝点击