java · 2022-07-11 0

AspectJ 使用

一、织入时机

AspectJ 作为 AOP 编程的完全解决方案

  • compile-time:编译期织入,在编译的时候一步到位,直接编译出包含织入代码的 .class 文件
  • post-compile:编译后织入,增强已经编译出来的类,如我们要增强依赖的 jar 包中的某个类的某个方法
  • load-time:在 JVM 进行类加载的时候进行织入

二、Compile-Time Weaving

编译期织入,在编译的时候一步到位,直接编译出包含织入代码的 .class 文件

1.maven 依赖

<?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>

    <groupId>org.example</groupId>
    <artifactId>compile-time-weaving-student</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- 编译期织入 -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.14.0</version>
                <configuration>
                    <complianceLevel>11</complianceLevel>
                    <source>11</source>
                    <target>11</target>
                    <showWeaveInfo>true</showWeaveInfo>
                    <verbose>true</verbose>
                    <Xlint>ignore</Xlint>
                    <encoding>UTF-8</encoding>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

2.java 代码

StudentService.java 被代理的类

package org.example.service;

public class StudentService{

    public void say() {
        System.out.println("- - - StudentService say - - -");
    }

    public static void walk() {
        System.out.println("- - - StudentService static walk - - -");
    }
}

StudentAspect.java 切面类

package org.example.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class StudentAspect {

    @Pointcut("execution(public * org.example.service.StudentService.*(..))")
    public void pointcut1(){};

    @Before("pointcut1()")
    public void beforeAdvice(JoinPoint joinPoint){
        System.out.println("- - - - - StudentAspect beforeAdvice  - - - - -");
    }
}

Main.class

package org.example;

import org.example.service.StudentService;

public class Main {

    public static void main(String[] args) {
        StudentService studentService = new StudentService();
        studentService.say();
        StudentService.walk();
    }
}

3.编译

使用 mvn compile 编译

编译后

StudentService.class

package org.example.service;

import org.aspectj.lang.JoinPoint;
import org.aspectj.runtime.reflect.Factory;
import org.example.aspect.StudentAspect;

public class StudentService {
    public StudentService() {
    }

    public void say() {
        JoinPoint var1 = Factory.makeJP(ajc$tjp_0, this, this);
        StudentAspect.aspectOf().beforeAdvice(var1);
        System.out.println("- - - StudentService say - - -");
    }

    public static void walk() {
        JoinPoint var0 = Factory.makeJP(ajc$tjp_1, (Object)null, (Object)null);
        StudentAspect.aspectOf().beforeAdvice(var0);
        System.out.println("- - - StudentService static walk - - -");
    }

    static {
        ajc$preClinit();
    }
}

StudentAspect.class

package org.example.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.NoAspectBoundException;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class StudentAspect {
    public StudentAspect() {
    }

    @Before("pointcut1()")
    public void beforeAdvice(JoinPoint joinPoint) {
        System.out.println("- - - - - StudentAspect beforeAdvice  - - - - -");
    }

    public static StudentAspect aspectOf() {
        if (ajc$perSingletonInstance == null) {
            throw new NoAspectBoundException("org.example.aspect.StudentAspect", ajc$initFailureCause);
        } else {
            return ajc$perSingletonInstance;
        }
    }

    public static boolean hasAspect() {
        return ajc$perSingletonInstance != null;
    }

    static {
        try {
            ajc$postClinit();
        } catch (Throwable var1) {
            ajc$initFailureCause = var1;
        }

    }
}

Main.class

package org.example;

import org.example.service.StudentService;

public class Main {
    public Main() {
    }

    public static void main(String[] args) {
        StudentService studentService = new StudentService();
        studentService.say();
        StudentService.walk();
    }
}

三、Post-Compile Weaving

编译后织入,增强已经编译出来的类,如我们要增强依赖的 jar 包中的某个类的某个方法

1.maven 依赖

<?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>

    <groupId>org.example</groupId>
    <artifactId>post-compile-weaving-teacher</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.example</groupId>
            <artifactId>teacher-service</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!--编译后织入-->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.14.0</version>
                <configuration>
                    <complianceLevel>11</complianceLevel>
                    <source>11</source>
                    <target>11</target>
                    <showWeaveInfo>true</showWeaveInfo>
                    <verbose>true</verbose>
                    <Xlint>ignore</Xlint>
                    <encoding>UTF-8</encoding>
                    <weaveDependencies>
                        <weaveDependency>
                            <groupId>org.example</groupId>
                            <artifactId>teacher-service</artifactId>
                        </weaveDependency>
                    </weaveDependencies>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

2.java 代码

TeacherAspect.java

package org.example.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class TeacherAspect {

    @Pointcut("execution(public * org.example.service.TeacherService.*(..))")
    public void pointcut1(){};

    @Before("pointcut1()")
    public void beforeAdvice(JoinPoint joinPoint){
        System.out.println("- - - - - StudentAspect beforeAdvice  - - - - -");
    }
}

Main.java

package org.example;

import org.example.service.TeacherService;

public class Main {

    public static void main(String[] args) {
        TeacherService teacherService = new TeacherService();
        teacherService.say();
        TeacherService.walk();
    }
}

3.编译

使用 mvn compile 编译

编译后

TeacherService.class

package org.example.service;

import org.aspectj.lang.JoinPoint;
import org.aspectj.runtime.reflect.Factory;
import org.example.aspect.TeacherAspect;

public class TeacherService {
    public TeacherService() {
    }

    public void say() {
        JoinPoint var1 = Factory.makeJP(ajc$tjp_0, this, this);
        TeacherAspect.aspectOf().beforeAdvice(var1);
        System.out.println("- - - TeacherService say - - -");
    }

    public static void walk() {
        JoinPoint var0 = Factory.makeJP(ajc$tjp_1, (Object)null, (Object)null);
        TeacherAspect.aspectOf().beforeAdvice(var0);
        System.out.println("- - - TeacherService static walk - - -");
    }

    static {
        ajc$preClinit();
    }
}

TeacherAspect.class

package org.example.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.NoAspectBoundException;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class TeacherAspect {
    public TeacherAspect() {
    }

    @Before("pointcut1()")
    public void beforeAdvice(JoinPoint joinPoint) {
        System.out.println("- - - - - StudentAspect beforeAdvice  - - - - -");
    }

    public static TeacherAspect aspectOf() {
        if (ajc$perSingletonInstance == null) {
            throw new NoAspectBoundException("org.example.aspect.TeacherAspect", ajc$initFailureCause);
        } else {
            return ajc$perSingletonInstance;
        }
    }

    public static boolean hasAspect() {
        return ajc$perSingletonInstance != null;
    }

    static {
        try {
            ajc$postClinit();
        } catch (Throwable var1) {
            ajc$initFailureCause = var1;
        }

    }
}

Main.class

package org.example;

import org.example.service.TeacherService;

public class Main {
    public Main() {
    }

    public static void main(String[] args) {
        TeacherService teacherService = new TeacherService();
        teacherService.say();
        TeacherService.walk();
    }
}