您的位置:首页 > 编程语言 > Java开发

spring-Aop切面编程

2016-09-24 11:43 393 查看
** 什么是面向切面编程?

面向切面编程主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。定义还挺邪乎的,其实我个人目前的理解就是把一个方法中重复使用的代码提取出来[类似于代理],建立一个专门的类来处理,并且是一种非侵入式的方式实现[比代理高端]。

 

** 熟悉AOP编程中的几个关键术语

         AOP编程中术语主要有:通知(advice)、切点(pointcut)、连接点(joinpoint)、切面(aspect)、织入(weaving)等。

         >>通知(advice)

                 通知定义了切面是什么以及何时使用。Spring切面定义了五种类型的通知。

                 #1. Before –>
在方法前被调用

                   #2.After ->在方法完成后被调用

                   #3.After-returning ->在方法执行成功后被调用

                   #4.After-throwing ->在方法抛出异常后调用

                   #5.Around ->环绕通知,在方法执行前后调用通知

         >>切点(pointcut)

                   切点会匹配通知要织入的一个或者多个连接点。其实就是指定切面在哪里执行。

         >>连接点(joinpoint)

                 连接点是在应用程序执行过程中能够插入切面的一个点。

         >>切面(aspect)

                   切面等于通知[要做什么、何时做]+切点[哪里做]

         >> 织入(weaving)

                   织入就是将切面应用到目标对象来创建新的代理对象的过程。

 

** XML方式配置切面

Xml配置:

顺便说一下当多个切面作用与一个目标时可以用order指定先后顺序

<beanid="_program"class="program.Program"></bean>
<beanid="_programAop"class="program.ProgramAop"></bean>
<aop:config>
    <aop:pointcutexpression="execution(*
program.Program.orderProgram(String))"id="order"/>                                                        
    <aop:aspectref="_programAop">
       <aop:beforemethod="before"pointcut-ref="order"/>
    </aop:aspect>
</aop:config>

目标对象:

publicclass Program {
    // ordertv program
    publicvoid orderProgram(Stringp){
       System.out.println("thinks! your are successd order tv program: "
+ p);                                                                                          
    }
}

切面类

publicclass ProgramAop {
    //前置通知
    publicvoid before(JoinPointjoinpoint){
       System.out.println("前置通知\n链接点:"
+ joinpoint.getSignature()+" |参数:"
+ Arrays.asList(joinpoint.getArgs()).toString());   
    }
}

>> 切入点表达式

         [访问类型] [返回类型]
[全类名方法]([方法参数])

         比如:拦截指定包及其子包下的所有方法

<aop:pointcutexpression="execution(* com..*(..))"id="pt"/>                                                                                                                   
         #带参数的切入点表达式

         args:用于对连接点的参数类型进行限制,要求参数的类型时指定类型的实例。args版本只匹配运行时动态传入的参数。

         在xml中使用&&来组合切入点表达式会报错!因为是特殊字符,所以需要用转义字符替换:&替换成&或者直接用and[注意在注解配置的时候又不能用and只能用&&],还有||和!意思和平常的一样。

<aop:config>
       <aop:pointcutexpression="execution(*
program.Program.orderProgram(..)) and args(p)"id="order"/>                                          
       <aop:aspectref="_programAop">
           <aop:beforemethod="before"pointcut-ref="order"arg-names="p"/>
       </aop:aspect>
    </aop:config>

// 前置通知
    publicvoid before(JoinPointjoinpoint,
Stringp){
       System.out.println("前置通知\n链接点:"
+ joinpoint.getSignature()+" |参数:"
+p);
    }
         #target、this、within指示符

within:用于匹配指定类型内的方法执行

this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配

      target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配[看了也不太理解,反正用的不多]

>> 返回通知

         返回通知可以获取目标方法的返回值

<aop:after-returningmethod="afterReturning"pointcut-ref="order"returning="result"/>                                                                         
// 返回通知
publicvoid afterReturning(JoinPointjoinpoint,booleanresult){
    System.out.println("返回通知\n连接点:"
+ joinpoint.getSignature()+" |返回值:"
+result);
}
>> 环绕通知

         环绕通知类似于代理吧,关键字around,配置如下:顺便说一下几个通知的大致的区域

// 环绕通知
public Object around(ProceedingJoinPointjoinPoint){
       System.out.println("环绕通知\n连接点:"
+ joinPoint.getSignature());                                                                                             
       Object
obj = null;
       try{
           /**
            *
前置通知区域
           */
          
           //连接点,执行目标方法
           try {
              obj =joinPoint.proceed();//获取返回值
           } catch (Throwablee) {
              e.printStackTrace();
           }
          
           /**
            *
返回通知区域
           */
       }catch(Exceptione){
           /**
            *
异常通知区域
           */
       }finally{
           /**
            *
后置通知区域
           */
       }
       System.out.println("===========================");
       returnobj;//返回通知控制着返回值哦
}

 

** 注解实现切面编程

Xml如果会的话,注解的方式就更加简单的了,其实现在注解的方式越来越流行了!其实步骤都是差不多的。

         >>把切面类和目标对象注入到Aop容器中,切面类声明为切面

@Component
publicclass Program {……}                                                                                                                                                                    
 
@Aspect
@Component
publicclass ProgramAop {……}
>> 开启注解扫描

<context:component-scanbase-package="program"></context:component-scan>                                                                                

         >>开启aspectj自动代理

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>                                                                                                                                 
         >>在切面类中指定pointcut,通知时机等

@Pointcut("execution(* program.Program.orderProgram(..))")
    publicvoid pt() {}
   
    //前置通知
    @Before("pt()")
    publicvoid before(JoinPointjoinpoint){
       System.out.println("前置通知\n链接点:"
+ joinpoint.getSignature()+" |参数:"
+ Arrays.asList(joinpoint.getArgs()).toString());   
    }

 

** 了解JoinPoint

【JoinPoint内容转载自】http://blog.csdn.net/a9529lty/article/details/7031070

         AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口。任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。

我们先来了解一下这两个接口的主要方法: 

>>  JoinPoint 

java.lang.Object[] getArgs():获取连接点方法运行时的入参列表
Signature getSignature()
:获取连接点的方法签名对象
java.lang.Object getTarget()
:获取连接点所在的目标对象
java.lang.Object getThis()
:获取代理对象本身;
>>  ProceedingJoinPoint 

ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法: 

java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法
java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参



Thinks KG,再见青春,你好未来!——致即将毕业的自己
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息