`
ncs123
  • 浏览: 99847 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

spring之AOP

阅读更多
一、AOP术语
    Aspect(切面): aspect 由 pointcount 和 advice 组成, 它既包含了横切逻辑的定义,切面就是对横切关注点的抽象。
    pointcut(切点): 匹配 join point 的谓词(a predicate that matches join points)。
    advice(增强): 指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类。
    target(目标对象): 织入 advice 的目标对象. 目标对象也被称为 advised object。
    joinpoint(连接点): 程序运行中的一些时间点, 例如一个方法的执行, 或者是一个异常的处理。
    weave(织入): 将 aspect 和其他对象连接起来, 并创建 adviced object 的过程。也就是生成代理对象的过程。
    introduction(引入): 在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段。

    总结: Aspect,pointcut,advice是一个抽象的整体,AOP织入 advice 的目标对象生成一个代理对象,通过pointcut规则拦截target中的joinpoint,并执行advice的代码。pointcut是定义规则,joinpoint是具体的方法和异常。

二、Java注解实现AOP
   AspectJ切入点指示符如下:
         execution:用于匹配方法执行的连接点;
         within:用于匹配指定类型内的方法执行;
         this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;
         target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;
         args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;
         @within:用于匹配所以持有指定注解类型内的方法;
         @target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
         @args:用于匹配当前执行的方法传入的参数持有指定注解的执行;
         @annotation:用于匹配当前执行方法持有指定注解的方法;
         bean:Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法;
         reference pointcut:表示引用其他命名切入点,只有@ApectJ风格支持,Schema风格不支持。

       AspectJ切入点支持的切入点指示符还有: call、get、set、preinitialization、staticinitialization、initialization、handler、adviceexecution、withincode、cflow、cflowbelow、if、@this、@withincode;但Spring AOP目前不支持这些指示符,使用这些指示符将抛出IllegalArgumentException异常。这些指示符Spring AOP可能会在以后进行扩展。

// 使用 Java Configuration 方式使能@AspectJ
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
}

//定义切面
@Aspect
public class NotVeryUsefulAspect {
  // 定义切点 匹配transfer方法
  @Pointcut("execution(* transfer(..))")// the pointcut expression
  private void anyOldTransfer() {}// the pointcut signature

  // 定义advice transfer方法前执行
  @Before("com.xyz.myapp.NotVeryUsefulAspect.anyOldTransfer()")
  public void doAccessCheck() {
    // ...
  }

  //合@Pointcut合@Before一体
  @Before("execution(* transfer(..))")
  public void doAccessCheck2() {
    // ...
  }
}

三、XML实现AOP

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

        <!-- 支持AOP功能配置 -->
        <aop:aspectj-autoproxy/>        

        <!-- 目标对象 -->
        <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" />
        <!-- advice对象 -->
        <bean id="timeHandler" class="com.xrq.aop.TimeHandler" />
        
        <aop:config>
            <!-- 切面 -->
            <aop:aspect id="time" ref="timeHandler">
                <!-- 切点 -->
                <aop:pointcut id="addAllMethod" expression="execution(* com.xrq.aop.HelloWorld.*(..))" />
                <!-- advice -->
                <aop:before method="printTime" pointcut-ref="addAllMethod" />
                <aop:after method="printTime" pointcut-ref="addAllMethod" />
            </aop:aspect>
        </aop:config>
</beans>


四、AOP代理

    AOP的源码中用到了两种动态代理来实现拦截切入功能:jdk动态代理cglib动态代理
    JDK动态代理:
  1. 通过实现InvocationHandlet接口创建自己的调用处理器
  2. 通过为Proxy类指定ClassLoader对象和一组interface来创建动态代理
  3. 通过反射机制获取动态代理类的构造函数,其唯一参数类型就是调用处理器接口类型
  4. 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数参入

    JDK动态代理是面向接口的代理模式,如果被代理目标没有接口那么Spring也无能为力,
Spring通过java的反射机制生产被代理接口的新的匿名实现类,重写了其中AOP的增强方法。


    CGLib动态代理
    CGLib是一个强大、高性能的Code生产类库,可以实现运行期动态扩展java类,Spring在运行期间通过 CGlib继承要被动态代理的类,重写父类的方法,实现AOP面向切面编程呢。

    比较:
  • JDK动态代理是面向接口,在创建代理实现类时比CGLib要快,创建代理速度快。
  • CGLib动态代理是通过字节码底层继承要代理类来实现(如果被代理类被final关键字所修饰,那么抱歉会失败),在创建代理这一块没有JDK动态代理快,但是运行速度比JDK动态代理要快。


        <!-- 默认实现接口的目标对象使用动态代理,未实现接口的使用CGLIB代理 -->
        <aop:aspectj-autoproxy/>

        <!-- 强制使用CGLIB代理 -->
        <aop:aspectj-autoproxy proxy-target-class="true"/>


参考资料:https://docs.spring.io/spring/docs/2.5.x/reference/aop.html#aop-using-aspectj
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics