spring aop LoadTimeWeaving(LTW), 可以debug的agent

详解 Spring AOP LoadTimeWeaving (LTW)  https://blog.csdn.net/c39660570/article/details/106791365/

官方文档 https://docs.spring.io/spring-framework/docs/5.3.x/reference/html/core.html#aop-aj-ltw

SpringBoot中使用LoadTimeWeaving技术实现AOP功能  https://juejin.cn/post/6844903873748926472

LTW 可以解决的问题

  • 非 spring 管理的类依赖注入和切面不生效的问题。

  • 调用类内方法切面不生效的问题。 (private方法等)

  • 本质是agent,开发方式与sdk一致,可以方便地debug

切面织入时机分类

编译期织入

使用特殊的编译器在编译期将切面织入目标类,这种比较少见,因为需要特殊的编译器的支持。

加载时织入

通过字节码编辑技术在类加载期将切面织入目标类中。

它的核心思想是:在目标类的class文件被JVM加载前,通过自定义类加载器或者类文件转换器将横切逻辑织入到目标类的class文件中,然后将修改后class文件交给JVM加载。

这种织入方式可以简称为LTW(LoadTimeWeaving)。

运行期织入

这是最常见的,比如在运行期通过为目标类生成动态代理的方式实现AOP就属于运行期织入,这也是Spring AOP中的默认实现,

并且提供了两种创建动态代理的方式: JDK自带的针对接口的动态代理 和 使用CGLib动态创建子类的方式创建动态代理。

LTW使用

LTW使用与aop动态代理方式可以共存,但是使用方式是不同的。(使用方式不能混用,容易出现一些非预期的现象

引入依赖

       <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
</dependency>

开启功能

@Configuration

/**开启LTW, 有aop.xml文件配置才会生效**/
@EnableLoadTimeWeaving

/**LTW切面支持spring bean注入**/ 
@EnableSpringConfigured
public class AopConfig {

}

增加一个切面

aop.xml

<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>

    <!-- Add this argument to options to make AspectJ logs use the Spring logging framework. -->
    <!-- -XmessageHandlerClass:org.springframework.aop.aspectj.AspectJWeaverMessageHandler -->
    <weaver options="-verbose -showWeaveInfo">
        <!--
            Only weave classes in our application-specific packages.
            This should encompass any class that wants to utilize the aspects,
            and does not need to encompass the aspects themselves.
        -->
<!--        <include within="org.apache.dubbo.rpc.protocol.dubbo..*" />
-->
     </weaver>

    <aspects>
        <!-- declare aspects to the weaver -->
        <aspect name="com.myhexin.devops.qa.mock.stub.infrastructure.aop.DubboDecodeAspect"/>
    </aspects>
    
</aspectj>

切面类

不能声明为spring的bean

@Aspect

/**切面支持spring bean注入**/
@Configurable
public class DubboDecodeAspect {

    @Autowired
    public  Aaxx aaxx;

    @Around("execution(* org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(..))")
    public Object decode(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("dubbo test");
        System.out.println(aaxx);
        System.out.println(HexinInnerSpringContextContainer.getBeanByType(Aaxx.class));
        return pjp.proceed();
    }
}

启动进行测试

java -javaagent:{path}/spring-instrument.jar  -jar main.jar

spring-instrument.jar, 可以使用maven-dependency-plugin在打包阶段拷贝到项目中

发表评论 / Comment

用心评论~