You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用AspectJ在带自定义注解的类上触发方法与构造器前置切面?

非Spring项目下AspectJ实现注解切面的可行方案

问题根源分析

你当前的切面逻辑无效,核心问题是切点表达式匹配范围错误:

  • 原表达式要求方法/构造器自身标注@RunAdivceBeforeCall,但你的需求是类标注注解后,触发该类下所有方法、构造器的通知
  • 未单独匹配构造器调用场景
  • 非Spring环境下,无法依赖Spring的AOP自动代理,必须使用原生AspectJ的织入机制

修正后的代码实现

1. 修正自定义注解类

注意导入正确的Java注解包,原代码的import com.stackoverflow是错误的:

import java.lang.annotation.*;

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RunAdviceBeforeCall {
    // 注解无需额外属性,保留空即可
}

2. 编写正确的AspectJ切面类

调整切点表达式,覆盖类标注注解的所有实例方法、静态方法、构造器:

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

@Aspect
public class HandleAspect {

    // 匹配:类上标注@RunAdviceBeforeCall的所有实例方法和静态方法调用
    @Before("execution(* (@RunAdviceBeforeCall *).*(..))")
    public void beforeMethodCall(JoinPoint joinPoint) {
        System.out.println("方法调用前触发通知:" + joinPoint.getSignature().getName());
        // 你的业务逻辑
    }

    // 匹配:类上标注@RunAdviceBeforeCall的构造器调用
    @Before("execution(new(@RunAdviceBeforeCall *)(..))")
    public void beforeConstructorCall(JoinPoint joinPoint) {
        System.out.println("构造器调用前触发通知:" + joinPoint.getSignature().getName());
        // 你的业务逻辑
    }
}

3. 目标类保持不变(确保类上标注注解)

@RunAdviceBeforeCall
public class NavigationBar {

    public NavigationBar() {
    }

    public void navigateToHomePage() {
    }

    public void navigateToUserAccount() {
    }

    public void navigateToHelp() {
    }

    // 新增静态方法测试
    public static void staticTestMethod() {
    }
}

非Spring环境下的AspectJ织入配置

原生AspectJ需要手动配置织入,常用两种方式:

方式1:编译时织入(CTW)

通过Maven插件在编译阶段将切面代码织入目标类,适合打包前确定织入范围的场景:

  1. 在pom.xml中添加AspectJ插件依赖:
<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.14.0</version>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjtools</artifactId>
                    <version>1.9.9.1</version>
                </dependency>
            </dependencies>
            <configuration>
                <source>1.8</source> <!-- 匹配你的JDK版本 -->
                <target>1.8</target>
                <complianceLevel>1.8</complianceLevel>
                <aspectLibraries>
                    <aspectLibrary>
                        <groupId>你的项目groupId</groupId>
                        <artifactId>你的项目artifactId</artifactId>
                    </aspectLibrary>
                </aspectLibraries>
            </configuration>
        </plugin>
    </plugins>
</build>
  1. 执行mvn clean compile,插件会自动将切面织入目标类。

方式2:加载时织入(LTW)

在JVM加载类时动态织入切面,适合需要动态调整织入范围的场景:

  1. 引入AspectJ依赖:
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.9.1</version>
</dependency>
  1. 创建META-INF/aop.xml配置文件,指定需要织入的切面和目标类:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
    <weaver>
        <!-- 指定需要织入的包,*表示所有包 -->
        <include within="你的目标类包路径..*"/>
    </weaver>
    <aspects>
        <!-- 指定你的切面类 -->
        <aspect name="com.yourpackage.HandleAspect"/>
    </aspects>
</aspectj>
  1. 启动JVM时添加JavaAgent参数:
java -javaagent:/path/to/aspectjweaver-1.9.9.1.jar -jar your-app.jar

内容的提问来源于stack exchange,提问作者gamelover

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 05:10:55