AspectJ框架的解析及应用

AspectJ框架的解析及应用

1、AspectJ和SpringAOP的区别

(1)面向对象不同:AspectJ是Java的独立框架,不依赖于任何框架或容器;SpringAOP依赖Spring框架实现,依赖于 Spring 框架进行实施和管理;

(2)实现方式不同:AspectJ支持编译时织入(CTW)和类加载时织入(LTW);SpringAOP通过动态代理在运行时织入;这意味着运行时AspectJ的性能会更好;

(3)支持的切面类型不同:AspectJ支持更多的切面类型,包括字段拦截器切面、构造器调用切面、注解切面。


2、AspectJ的CTW和LTW
2.1、CTW

CTW是 AspectJ 中一种将切面织入目标类的字节码的技术。相比于加载时织入和运行时织入,编译时织入在编译阶段就将切面织入到目标类的字节码中,这样在程序运行时就无需再进行切面的织入操作。

CTW的优势:

  • 性能:由于切面是在编译时加入,运行时性能较好,因为没有动态代理和反射的开销。
  • 类型安全:编译时织入可以在编译阶段检测到某些类型的错误。

CTW的过程:

  • 开发者编写包含切面定义的AspectJ源代码。
  • 使用AspectJ编译器(ajc)编译源代码,编译器将切面逻辑织入到目标类的字节码中。
  • 生成的字节码包含了原始的业务逻辑和切面逻辑。

具体的使用方法可以在Maven的项目构建中进行配置,默认是LTW。

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.11</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <complianceLevel>1.8</complianceLevel>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

2.2、LTW

LTW是一种在类加载时织入切面的方式。与CTW和RTW相比,加载时织入提供了更大的灵活性,并且可以在不修改原始源代码的情况下,将切面逻辑应用到已编译的类中。

LTW 的优势:

  • 非侵入性:不需要修改原始源代码,可以在已编译的类中动态地织入切面,因此具有非侵入性。
  • 灵活性:可以在运行时动态选择和配置切面,具有更大的灵活性,可以根据需要选择在哪些类上应用切面,以及应用哪些切面逻辑。
  • 运行时检测:与 CTW 不同,LTW 可以在运行时动态地选择和配置切面,因此更适合需要在运行时动态适配和调整切面逻辑的情况。

LTW 的过程:

  1. 配置 LTW 机制:在应用程序的配置中启用 AspectJ 的 LTW 机制。这可以通过 Java 代理机制或者专用的 LTW 框架来实现。
  2. 运行时织入切面:当类加载器加载类的时候,LTW 框架会拦截类加载事件,并根据配置将切面逻辑织入到目标类的字节码中。通常,LTW 框架会使用字节码增强技术来修改类的字节码,将切面逻辑动态地织入到目标类中。
  3. 生成的字节码包含了切面逻辑:最终生成的字节码包含了原始的业务逻辑和动态织入的切面逻辑。

使用AspectJ LTW有两个主要步骤,第一,通过JM的-javaagent参数设置LTW的织入器类包,以代理JVM默认的类加载器;第二,LTW织入器需要一个 aop.xm文件,在该文件中指定切面类和需要进行切面织入的目标类。
设置-javaagent JvM参数的方法

(1)在Eclipse下的设置:
运行类->右键单击->Run As->Run.,可以在弹出的Run设置窗口设置该类的各项运行属性,切换到ArgumentsTab页,在VM arguments中通过-javaagent指定Aspect织入器类包。javaagent:E:\workspace\lib\spring2.5\aspectjweaver.jar

(2)在Tomcat下的设置
打开<Tomcat_Home>\bin\catalina.bat,在该批处理文件头部添加以下的设置:set JAVA_OPTS=-javaagent:E:\workspace\lib\spring2.5\aspectjweaver.jar

参考:https://blog.csdn.net/wenbingoon/article/details/22888619


3、应用代码

AspectJ的使用和SpringAOP并没有很大区别,这里仅做简单展示。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({MetricsConfiguration.class})
public @interface EnableMetrics {
}

@Target表示注解的应用场景,后面参数表示表示应用在类上;@Retention(RetentionPolicy.RUNTIME)表示该注解运行时保留;@Import({MetricsConfiguration.class})表示import这个类,这个配置类会进行一些初始化操作,也是@EnableXXX这类注解的关键。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MetricsLog {
    String path() default "";
}

用来标记的切点,AspectJ和SpringAOP的注解写法都是一样的,可以携带一个属性,默认为""。

@Pointcut("@annotation(com.test.MetricsLog)")
public void pointcut() {
}

@Around("pointcut()")
public Object returnDataHandler(ProceedingJoinPoint point) throws Throwable {
    long start = System.currentTimeMillis();
    Object[] args = point.getArgs();
    String className = point.getSignature().getDeclaringType().getSimpleName();
    String methodName = point.getSignature().getName();
    MetricsLog metricsLog = (MetricsLog)((MethodSignature)point.getSignature()).getMethod().getAnnotation(MetricsLog.class);
    String path = metricsLog.path();
    if (!StringUtils.isBlank(path)) {
        path = path.substring(0, 1).equals("/") ? path.replaceFirst("/", "") : path;
    } else {
        path = methodName;
    }

    long end;
    //执行方法
    Object proceed = point.proceed(args);
    end = System.currentTimeMillis();
    log.info("{},{}.{} cost time:{}", new Object[]{path, className, methodName, end - start});
    this.metricsClient.simpleReport(path, end - start, 200, true);
    return proceed;

}

切面的代码,@Pointcut来标记切点,@Around标记通知,point.proceed(args);执行方法。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值