article/java/使用LoadTimeWeaving技术实现AOP功能.md

6.8 KiB
Raw Blame History

使用LTW(LoadTimeWeaving)技术实现AOP功能

aop增强分类

编译时:

使用特殊的编译器在编译期将切面织入目标类,这种比较少见,因为需要特殊的编译器的支持。例如AspectJ编译 器,很少有到,目前我还没有用到。

加载时:

通过字节码编辑技术在类加载期将切面织入目标类中,它的核心思想是在目标类的class文件被JVM加 载前,通过自定义类加载器或者类文件转换器将横切逻辑织入到目标类的class文件中然后将修改后class文件交给JVM加载 这种织入方式可以简称为LTW(LoadTimeWeaving)AspectJ的LoadTimeWeaving (LTW)

运行时:

运行期通过为目标类生成动态代理的方式实现AOP就属于运行期织入这也是Spring AOP中的默认实现,并且提供了两种创建动态代理的方式JDK自带的针对接口的动态代理和使用CGLib动态创建子类的方式创建动态代理。

优劣势

编译时:需要特殊的编译器

加载时:需要特殊的类加载器

运行时:功能有限

使用LTW 切面第三方JAR 包普通maven项目

配置文件

pom 文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.x47.blog</groupId>
        <artifactId>LoadTimeWeaving-demo</artifactId>
        <version>1.0</version>
    </parent>

    <artifactId>java-aspectj-agent</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>cn.x47.ltw.Main</mainClass><!--这里改成自己的主类位置-->
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

aop.xml

放在META-INF/aop.xml

<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
    <weaver>
        <!-- 注意 目标类 和使用目标类方法的类都要配置 -->
        <include within="cn.x47.ltw..*"/>
        <include within="com.alibaba.fastjson.*"/>
    </weaver>
    <aspects>
        <!-- 切面 -->
        <aspect name="cn.x47.ltw.ProfilingAspect"/>
    </aspects>

</aspectj>

目录结构

image-20220828130642183

执行方法

开发环境

可以通过添加jvm参数的方式来启动

image-20220828123756596

springboot 使用 LTW切面第三方JAR包

配置文件

pom配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.x47.blog</groupId>
        <artifactId>LoadTimeWeaving-demo</artifactId>
        <version>1.0</version>
    </parent>

    <artifactId>springboot-aspectj-agent</artifactId>
    <version>1.0</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.12</version>
        </dependency>

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

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.9</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
oop配置
<?xml version="1.0" encoding="UTF-8" ?>
<aspectj>
    <weaver options="-XnoInline -Xset:weaveJavaxPackages=true -Xlint:ignore -verbose -XmessageHandlerClass:org.springframework.aop.aspectj.AspectJWeaverMessageHandler">
        <!--在编织时导入切面类和需要被切入的目标类-->
        <include within="cn.x47.ltw..*"/>
        <include within="com.alibaba.fastjson..*"/>
    </weaver>
    <aspects>
        <!--指定切面类-->
        <aspect name="cn.x47.ltw.springboot.aop.TestAspect"/>
    </aspects>
</aspectj>

目录结构

image-20220828135835641

源码地址

https://git.dr1997.com/chenkuangwei/LoadTimeWeaving-demo