当我在其他项目中使用该方面时,如何更改已编译的方面内的 pointCut 表达式?

问题描述 投票:0回答:1

我有一个这样的日志记录方面,它会打印参数、结果或任何其他异常。我使用 aspectj-maven-plugin 来编译这方面。然后,将编译结果打包成一个jar。我会将这个 jar 提供给我们的 maven 存储库,这样他们就可以在他们的项目中依赖这个 jar。如果他们需要记录任何请求信息,他们只需要在方法定义处写一个注解@Log。我还想提供“包分配能力”:我的同事可以在编译他们的项目时设置一个包参数,然后在该包内调用的所有方法都将被删除。

综上所述,就像下面代码中的customPointCut,当我在另一个项目中需要这个编译的asject时,我想改变切入点定义。

@Aspect
public class LogAspect {

    static private final Logger log = Logger.getLogger(LogAspect.class);

    @Pointcut("execution(@com.stellariver.milky.aspectj.tool.log.Log * *(..))")
    private void annoPointCut() {}

    @Pointcut("execution(* com.project.package..*.*(..))")
    private void customPointCut() {}

    @Around("annoPointCut() || customPointCut()")
    public Object valid(ProceedingJoinPoint pjp) throws Throwable {
        Object result = null;
        try {
            result = pjp.proceed();
        } catch (Throwable throwable) {
            throw throwable;
        } finally {
            log(xx,xx);
        }
        return result;
    }

}

我在方面项目或 aspect-maven-plugin 项目中找不到任何参数化的方面解决方案

java aspectj aspect aspectj-maven-plugin
1个回答
0
投票

在 Java 中,注释值必须是编译时常量,因此您不能更改它们。这不是 AspectJ 问题,而是 Java 限制。

所以你在 AspectJ 中所做的就是将你的日志方面定义为抽象的,并将包切入点也定义为抽象的:

@Aspect
public abstract class AutoLogAspect {
    // (...)

    @Pointcut("")
    public abstract void packagePC();

    // (...)
}

然后,在您的演示项目中,您覆盖抽象方面,定义一个具体的切入点:

package com.example.log.demo;

import com.stellariver.milky.aspectj.tool.log.AutoLogAspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class MyLogAspect extends AutoLogAspect {
    @Pointcut("within(com.example.log..*) && execution(* *(..))")
    public void packagePC() {}
}

现在,您可以从示例类中删除

@Log
注释:

package com.example.log.demo;

public class Main {
    public static void main(String[] args) {
        Fool fool = new Fool();
        fool.testLogOfPackage("Hello World");
    }

    public static class Fool {
        public void testLogOfPackage(String str) {
            System.out.println(str);
        }
    }
}

使用Maven编译时,你会看到:

[INFO] --- aspectj-maven-plugin:1.14.0:compile (default) @ log-demo ---
[INFO] Showing AJC message detail for messages of types: [error, warning, fail]
[INFO] Join point 'method-execution(void com.example.log.demo.Main$Fool.testLogOfPackage(java.lang.String))' in Type 'com.example.log.demo.Main$Fool' (Main.java:10) advised by around advice from 'com.example.log.demo.MyLogAspect' (aspectj-tool-0.1.8-SNAPSHOT.jar!AutoLogAspect.class(from AutoLogAspect.java))
[INFO] Join point 'method-execution(void com.example.log.demo.Main.main(java.lang.String[]))' in Type 'com.example.log.demo.Main' (Main.java:4) advised by around advice from 'com.example.log.demo.MyLogAspect' (aspectj-tool-0.1.8-SNAPSHOT.jar!AutoLogAspect.class(from AutoLogAspect.java))

运行示例程序时,输出将是:

Hello World

=====msg: execution(Main.Fool.testLogOfPackage(..))
==header: 09:12:00.329 [main-INFO ] com.stellariver.milky.aspectj.tool.log.AutoLogAspect:386 : [success:true] [cost:0] [result:]
===milky: [class:com.stellariver.milky.aspectj.tool.log.AutoLogAspect] [method:log] [line:66]
====args: [arg0:Hello World] [arg1:] [arg2:] [arg3:] [arg4:] [arg5:]

=====msg: execution(Main.main(..))
==header: 09:12:00.334 [main-INFO ] com.stellariver.milky.aspectj.tool.log.AutoLogAspect:386 : [success:true] [cost:7] [result:]
===milky: [class:com.stellariver.milky.aspectj.tool.log.AutoLogAspect] [method:log] [line:66]
====args: [arg0:[Ljava.lang.String;@4ff4357f] [arg1:] [arg2:] [arg3:] [arg4:] [arg5:]

看到了吗?无需复制和粘贴整个方面。您只需将包切入点抽象化并强制使用项目覆盖它。干净简单。

P.S.:如果消费项目使用加载时织入而不是编译时织入,您可以直接在 aop.xml 中定义覆盖方面,根本不需要编译源方面或使用 AspectJ Maven 插件消费项目。但是 CTW 或 LTW,两者都很好用,剩下的就看你了。

© www.soinside.com 2019 - 2024. All rights reserved.