spring之AOP

本文详细解析了AOP(面向切面编程)的基本概念,包括切面、切点、增强等核心术语,并介绍了如何利用Java注解和XML配置在Spring框架中实现AOP。此外,还对比了JDK动态代理和CGLib动态代理的不同之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、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的代码。


二、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动态代理:

  • 通过实现InvocationHandlet接口创建自己的调用处理器
  • 通过为Proxy类指定ClassLoader对象和一组interface来创建动态代理
  • 通过反射机制获取动态代理类的构造函数,其唯一参数类型就是调用处理器接口类型
  • 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数参入

    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"/>

 


参考资料:[url]https://docs.spring.io/spring/docs/2.5.x/reference/aop.html#aop-using-aspectj[/url]

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值