Spring AOP

基础

AOP是目前Spring框架中的核心之一,在应用中具有非常重要的作用,也是Spring其他组件的基础。它是一种面向切面编程的思想。关于AOP的基础知识,相信多数童鞋都已经了如指掌,我们就略过这部分,来讲解下AOP的核心功能的底层实现机制:如何用动态代理来实现切面拦截。

 

配置

注意:在一般整合的框架中,application是spring的配置文件,SpringMVC-servlet.xml才是SpringMVC的配置文件,我们是在SpringMVC上面配置aop,所以我们需要把配置文件都设置到SpringMVC-servlet.xml中.

一、在配置文件中配置相关的东西

1.     书写aop对象如AopDemo


2.     SpringMVC-servlet.xml


2.1开自动扫描,

必须在aop:pointcut中的匹配到类扫描到了SpringMVC中,

2.2书写:execution

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)

“?”号的部分表示可省略的,modifers-pattern表示修饰符如publicprotected等,ret-type-pattern表示方法返回类型,declaring-type-pattern代表特定的类,name-pattern代表方法名称,param-pattern表示参数,throws-pattern表示抛出的异常。在切入点表达式中,可以使用*来代表任意字符,用..来表示任意个参数。

2.3 op:after aop:after-returningaop:before中的配置:

@Override
public Object invoke(Object proxy, Method method, Object[] args) throwsThrowable {
      Object result;
   try {
       //@Before
       result = method.invoke(target, args);
       //@After
       return result;
   } catch (InvocationTargetException e) {
       Throwable targetException = e.getTargetException();
       //@AfterThrowing
       throw targetException;
   } finally {
       //@AfterReturning
   }
}

After-returning配置里面可以增强返回值,可以在配置文件中加上returning标签       <aop:after-returningreturning="ret" method="AfterDemo"pointcut-ref="test"/>

Ret就是参数名称,方法中AfterDemo(Object ret)

 

aop:around环绕参数为ProceedingJoinPoint类型

方法中接收roundDemo(ProceedingJoinPoint point)

 

二、在aop对象中使用注解,不在配置文件中配置

但是得在配置文件中打开aop注解:

<aop:aspectj-autoproxyexpose-proxy="true"></aop:aspectj-autoproxy>

 

@Component

@Aspect

public classHelloApiAspect2 {

   

   @Pointcut(value="execution(*bean.HelloApi.aspectTest(..)) &&args(a1,b2)",argNames="a1,b2")

    publicvoidpointcut1(String a1,String b2){}

   

   @Before(value="pointcut1(a,b)",argNames="a,b")

    publicvoidbeforecase1(String a,String b){

       System.out.println("1 a:" +a +" b:" + b);

    }

    //注意和beforecase1的区别是argNames的顺序交换了

   @Before(value="pointcut1(a,b)",argNames="b,a")

    publicvoidbeforecase2(String a,String b){

       System.out.println("2 a:" +a +" b:" + b);

    }

    @AfterReturning(value="pointcut1(a,b)",returning="ret")

    publicvoid AfterReturnDemo(Object ret) {

        Cbsf c = (Cbsf)ret;

        System.out.println(c.get_id() +":" + c.getAzlx());

        }

}

 

 

原理

        AOP的拦截功能是由java中的动态代理来实现的。说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常时候执行。不同的切入时机对应不同的Interceptor的种类,如BeforeAdviseInterceptor,AfterAdviseInterceptor以及ThrowsAdviseInterceptor等)。

        那么动态代理是如何实现将切面逻辑(advise)织入到目标类方法中去的呢?下面我们就来详细介绍并实现AOP中用到的两种动态代理。

        AOP的源码中用到了两种动态代理来实现拦截切入功能:jdk动态代理和cglib动态代理。两种方法同时存在,各有优劣。jdk动态代理是由java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。由此可以看出,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。

ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。ASM从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。

区别

此时代理对象和目标对象实现了相同的接口,目标对象作为代理对象的一个属性,具体接口实现中,可以在调用目标对象相应方法前后加上其他业务处理逻辑。

代理模式在实际使用时需要指定具体的目标对象,如果为每个类都添加一个代理类的话,会导致类很多,同时如果不知道具体类的话,怎样实现代理模式呢?这就引出动态代理。

JDK动态代理只能针对实现了接口的类生成代理

CGLIB(CODEGENERLIZE LIBRARY)代理是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的。

如果目标对象没有实现接口,则默认会采用CGLIB代理;

如果目标对象实现了接口,可以强制使用CGLIB实现代理(添加CGLIB库,并在spring配置中加入<aop:aspectj-autoproxyproxy-target-class="true"/>)

http://blog.csdn.net/zbuger/article/details/51011117

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值