AOP原理

AOP原理


  AOP全名Aspect-Oriented Programming,中文直译为面向切面(方面)编程,当前已经成为一种比较成熟的编程思想,可以用来很好的解决应用系统中分布于各个模块的交叉关注点问题。在轻量级的J2EE中应用开发中,使用AOP来灵活处理一些具有横切性质的系统级服务,如事务处理、安全检查、缓存、对象池管理等,已经成为一种非常适用的解决方案。 AOP中比较重要的概念有:Aspect、JoinPoint、PonitCut、Advice、Introduction、Weave、Target Object、Proxy Object等
  引介(Introduction)是指给一个现有类添加方法或字段属性,引介还可以在不改变现有类代码的情况下,让现有的Java类实现新的接口,或者为其指定一个父类从而实现多重继承。相对于增强(Advice)可以动态改变程序的功能或流程来说,引介(Introduction)则用来改变一个类的静态结构。比如我们可以让一个现有为实现java.lang.Cloneable接口,从而可以通过clone()方法复制这个类的实例。
拦截器是用来实现对连接点进行拦截,从而在连接点前或后加入自定义的切面模块功能。在大多数JAVA的AOP框架实现中,都是使用拦截器来实现字段访问及方法调用的拦截(interception)。所用作用于同一个连接点的多个拦截器组成一个连接器链(interceptor chain),链接上的每个拦截器通常会调用下一个拦截器。Spring AOP及JBoos AOP实现都是采用拦截器来实现的。
  面向对象编程(OOP)解决问题的重点在于对具体领域模型的抽象,而面向切面编程(AOP)解决问题的关键则在于对关注点的抽象。也就是说,系统中对于一些需要分散在多个不相关的模块中解决的共同问题,则交由AOP来解决;AOP能够使用一种更好的方式来解决OOP不能很好解决的横切关注点问题以及相关的设计难题来实现松散耦合。因此,面向方面编程 (AOP) 提供另外一种关于程序结构的思维完善了OOP,是OOP的一种扩展技术,弥补补了OOP的不足。
  AOP概念详解:注意以下实例aop:'开头的AspectJ的概念,Spring没有分的这么细.
  (1)方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是一个很好的横切关注点例子。方面用Spring的Advisor或拦截器实现, 然后可以通过@Aspect标注或在applictionContext.xml中进行配置:

      <aop:aspect id="fourAdviceAspect" ref="fourAdviceBean" order="2"> 


  (2)连接点(Joinpoint):程序执行过程中的行为,如方法的调用或特定的异常被抛出,在代码上有JoinPoint类和ProceedingJoinPoint类,如下所示,可以通过JoinPoint获取很多参数,JoinPoint一般用在Advice实现方法中作为参数传入,ProceedingJoinPoint用于实现围绕Advice的参数传入。   通过下面JoinPoint的接口可以看出通过JoinPoint可以得到代理对象和Target对象。

package org.aspectj.lang;  
import org.aspectj.lang.reflect.SourceLocation;  
public interface JoinPoint {  
    String toString();         //连接点所在位置的相关信息  
    String toShortString();     //连接点所在位置的简短相关信息  
    String toLongString();     //连接点所在位置的全部相关信息  
    Object getThis();         //返回AOP代理对象  
    Object getTarget();       //返回目标对象  
    Object[] getArgs();       //返回被通知方法参数列表  
    Signature getSignature();  //返回当前连接点签名  
    SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置  
    String getKind();        //连接点类型  
    StaticPart getStaticPart(); //返回连接点静态部分  
}  
  
public interface ProceedingJoinPoint extends JoinPoint {  
    public Object proceed() throws Throwable;  
    public Object proceed(Object[] args) throws Throwable;  
}  


  (3)切入点(Pointcut):指定一个Adivce将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点,例如,使用正则表达式。
1.xml中配置:

 <aop:pointcut id="myPointcut" expression="execution(*   com.wicresoft.app.service.impl.*.*(..))" method="release" /> 

2.使用Annoation :

    @pointcut("execution * transfer(..)")
并用一个返回值为void,方法体为空的方法来命名切入点如:  private void anyOldTransfer(){}
 之后就可以在Advice中引用,如: @AfterReturning(pointcut="anyOldTransfer()", returning="reVal")
package org.springframework.aop;  
public interface Pointcut {  
    ClassFilter getClassFilter();  
    MethodMatcher getMethodMatcher();  
    Pointcut TRUE = TruePointcut.INSTANCE;  
}  
package org.springframework.aop;  
public interface ClassFilter {  
     boolean matches(Class<?> clazz);//如果clazz与我们关注的现象相符时返回true,负责返回false  
     ClassFilter TRUE = TrueClassFilter.INSTANCE;//静态参数 如果类型对于要扑捉的Pointcut来说无所谓,可将此参数传递给Pointcut  
}  
package org.springframework.aop;  
public interface MethodMatcher {  
   boolean matches(Method method, Class<?> targetClass);  
  
 /** 
  * 是否对参数值敏感 
  * 如果为false表明匹配时不需要判断参数值(参数值不敏感),称之为StaticMethodMatcher,这时只有 
  * matches(Method method, Class<?> targetClass); 被执行,执行结果可以缓存已提高效率。 
  * 如果为true表明匹配时需要判断参数值(参数值敏感),称之为DynamicMethodMatcher,这时先执行 
  * matches(Method method, Class<?> targetClass);如果返回true,然后再执行 
  * boolean matches(Method method, Class<?> targetClass, Object[] args);已做进一步判断 
  *  
  */  
 boolean isRuntime();  
 boolean matches(Method method, Class<?> targetClass, Object[] args);  
 MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;  
}  

(4)通知(Advice):在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Advice中必须用到PointCut
在xml中配置,配置中的method为Aspect实现类中的方法名,使用pointcut自定义或pointcut-ref进行引用已有pointcut

 <aop:before pointcut="execution(* com.wicresoft.app.service.impl.*.*(..))" method="authority" /> 
       <aop:after pointcut="execution(* com.wicresoft.app.service.impl.*.*(..))" method="release" /> 
       <aop:after-returning pointcut="execution(* com.wicresoft.app.service.impl.*.*(..))" method="log" />
       <aop:around pointcut="execution(* com.wicresoft.app.service.impl.*.*(..))" method="processTx" /> 
       <aop:after-throwing pointcut-ref="myPointcut" method="doRecovertyActions" throwing="ex" />   

或使用Annoation:


       @AfterReturning(returning="rvt", pointcut="execution(* com.wicresoft.app.service.impl.*.*(..))")
       @AfterThrowing(throwing="ex", pointcut="execution(* com.wicresoft.app.service.impl.*.*(..))")
       @After("execution(* com.wicresoft.app.service.impl.*.*(..))")
       @Around("execution(* com.wicresoft.app.service.impl.*.*(..))")  

注意:
AfterReturning 增强处理处理只有在目标方法成功完成后才会被织入。
After 增强处理不管目标方法如何结束(保存成功完成和遇到异常中止两种情况),它都会被织入。

(5)引入(Introduction):添加方法或字段到被通知的类,引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现IsModified接口,来简化缓存。使用introduction要有三个步骤
  (1)声明新接口
  (2)创建自己的IntrouductionInterceptor通过Implements IntroductionInterceptor或extends DelegatingIntroductionInterceptor 并同时implements(1)中声明的接口
  (3)将新接口和自定义的IntroductionInterceptor配置到DefaultIntroductionAdvisor中,然后将前三者配置到ProxyFactoryBean中。

public interface IOtherBean {  
    public void doOther();  
}  
  
public class SomeBeanIntroductionInterceptor implements IOtherBean, IntroductionInterceptor {  
  
    public void doOther() {  
        System.out.println("doOther!");  
    }  
  
    public Object invoke(MethodInvocation invocation) throws Throwable {  
          
        //判断调用的方法是否为指定类中的方法  
        if ( implementsInterface(invocation.getMethod().getDeclaringClass()) ) {  
            return invocation.getMethod().invoke(this, invocation.getArguments());  
        }  
          
        return invocation.proceed();  
    }  
      
    /** 
     * 判断clazz是否为给定接口IOtherBean的实现 
     */  
    public boolean implementsInterface(Class clazz) {  
          
        return clazz.isAssignableFrom(IOtherBean.class);  
    }  
}  

xml 配置

<!-- 目标对象 -->  
<bean id="someBeanTarget" class="aop.spring.introduction.SomeBeanImpl" />  
<!-- 通知 -->  
<bean id="someBeanAdvice" class="aop.spring.introduction.SomeBeanIntroductionInterceptor" />  
<!-- 通知者,只能以构造器方法注入-->  
<bean id="introductionAdvisor" class="org.springframework.aop.support.DefaultIntroductionAdvisor">  
    <constructor-arg ref="someBeanAdvice" />  
    <constructor-arg value="aop.spring.introduction.IOtherBean" />      
</bean>  
<!-- 代理 (将我们的切面织入到目标对象)-->  
<bean id="someBeanProxy" class="org.springframework.aop.framework.ProxyFactoryBean">  
    <!-- 若目标对象实现了代理接口,则可以提供代理接口的配置 -->  
    <property name="proxyInterfaces"  value="aop.spring.introduction.ISomeBean" />  
    <!-- 配置目标对象 -->  
    <property name="target" ref="someBeanTarget" />  
    <!-- 配置切面 -->  
    <property name="interceptorNames">  
        <list>  
            <value>introductionAdvisor</value>  
        </list>  
    </property>  
</bean>  


  (六)拦截器(Advisor )常用的有PointCutAdvisor和IntroudtionAdvisor。前者Advisor有PointCut和Advice组成,满足Poincut(指定了哪些方法需要增强),则执行相应的Advice(定义了增强的功能),后者由Introduction构成。PointCutAdvisor主要是根据PointCut中制定的Target Objects的方法在调用(前,后,around,throws, after-return等)时引入新的Aspect中的methods, 而IntroductionAdvisor主要是引入新的接口到Targets对象中。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 树欲静而风不止,子欲养而亲不待。多少子女对亲人的想念与缅怀。 今天是个值得让人纪念的日子,一个伟人的纪念日。一个亲...
    福之龙阅读 164评论 0 3
  • 有些事情,一旦开始,就一发不可收拾,跑步就是这样一件事情。 慢热的我,是慢慢爱上跑步的。 在今年年初,我的体重快接...
    Sunny晴儿阅读 1,023评论 9 8
  • 文╱雅芩 在知乎上,总是有很多人问我,送女朋友什么礼物。 今天,我将给你们揭晓答案! 1.护护品或化妆品。每一个女...
    雅芩阅读 793评论 0 3