Java 如何在执行带注释的方法和传递参数之前调用外部方法

Java 如何在执行带注释的方法和传递参数之前调用外部方法,java,annotations,aop,pojo,Java,Annotations,Aop,Pojo,我正在从事POJO项目,该项目使用Maven构建到一个独立的JAR中。为了可维护性,我正在考虑添加一种使用基于注释的检查的方法。在下面的代码中,我有一个带注释的方法,在调用此方法时,我希望执行另一个类中的另一个方法,并具有上下文意识,以便访问传递给原始方法的参数 public class SomeClass { public static void someClassMethod(){ ... get(new AnotherClass() {

我正在从事POJO项目,该项目使用
Maven
构建到一个独立的JAR中。为了可维护性,我正在考虑添加一种使用基于注释的检查的方法。在下面的代码中,我有一个带注释的方法,在调用此方法时,我希望执行另一个类中的另一个方法,并具有上下文意识,以便访问传递给原始方法的参数

public class SomeClass {
    public static void someClassMethod(){

        ...

        get(new AnotherClass() {
            @CustomAnnotation
            public Object handle(ArgumentClass1 arg1, ArgumentClass2 arg2) {
                ...
            }
        });

        ...

    }
}

我知道这可以通过AspectJ实现,但我找不到一个真正的工作示例来说明如何实现这种功能。因此,我想询问一个示例代码,或指向工作示例的链接。

我真的无法向您解释AOP基础知识。如果你不愿意至少阅读AOP教程并掌握aspect、joinpoint、pointcut和advice等基本概念,那么在这里要求人们提供示例代码是错误的。我甚至会在AspectJ中为您提供一个功能齐全的示例(见下文),但有什么用呢?你能理解吗?我不打算提供的是Maven配置,因为这实际上超出了范围,即使我知道如何使用Maven构建AspectJ代码。请随意使用搜索引擎学习,然后带着“我懒得学习,请为我做吧”以外的具体问题回来

参数类根据您的示例:

package de.scrum_master.app;

public class ArgumentClass1 {}
package de.scrum_master.app;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {}
package de.scrum_master.app;

public abstract class AnotherClass {
    public abstract Object handle(ArgumentClass1 arg1, ArgumentClass2 arg2);
}
package de.scrum_master.app;

public class SomeClass {
    public static void someClassMethod() {
        get(new AnotherClass() {
            @CustomAnnotation
            public Object handle(ArgumentClass1 arg1, ArgumentClass2 arg2) {
                return "dummy";
            }
        });
    }

    public static Object get(AnotherClass anotherClass) {
        return anotherClass.handle(new ArgumentClass1(), new ArgumentClass2());
    }

    private static void anotherClassMethod(String string, String string2) {}

    @CustomAnnotation
    private static void yetAnotherClassMethod(int i, int j) {}

    public static void main(String[] args) {
        someClassMethod();
        anotherClassMethod("foo", "bar");
        yetAnotherClassMethod(11, 22);
    }
}
package de.scrum_master.aspect;

import de.scrum_master.app.CustomAnnotation;

public aspect AnnotatedMethodInterceptor {
    Object around() : execution(@CustomAnnotation * *(..)) {
        System.out.println(thisJoinPoint);
        for (Object arg : thisJoinPoint.getArgs()) {
            System.out.println("  Checking argument " + arg);
        }
        return proceed();
    }
}
--

示例注释:

package de.scrum_master.app;

public class ArgumentClass1 {}
package de.scrum_master.app;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {}
package de.scrum_master.app;

public abstract class AnotherClass {
    public abstract Object handle(ArgumentClass1 arg1, ArgumentClass2 arg2);
}
package de.scrum_master.app;

public class SomeClass {
    public static void someClassMethod() {
        get(new AnotherClass() {
            @CustomAnnotation
            public Object handle(ArgumentClass1 arg1, ArgumentClass2 arg2) {
                return "dummy";
            }
        });
    }

    public static Object get(AnotherClass anotherClass) {
        return anotherClass.handle(new ArgumentClass1(), new ArgumentClass2());
    }

    private static void anotherClassMethod(String string, String string2) {}

    @CustomAnnotation
    private static void yetAnotherClassMethod(int i, int j) {}

    public static void main(String[] args) {
        someClassMethod();
        anotherClassMethod("foo", "bar");
        yetAnotherClassMethod(11, 22);
    }
}
package de.scrum_master.aspect;

import de.scrum_master.app.CustomAnnotation;

public aspect AnnotatedMethodInterceptor {
    Object around() : execution(@CustomAnnotation * *(..)) {
        System.out.println(thisJoinPoint);
        for (Object arg : thisJoinPoint.getArgs()) {
            System.out.println("  Checking argument " + arg);
        }
        return proceed();
    }
}
根据您的示例抽象类:

package de.scrum_master.app;

public class ArgumentClass1 {}
package de.scrum_master.app;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {}
package de.scrum_master.app;

public abstract class AnotherClass {
    public abstract Object handle(ArgumentClass1 arg1, ArgumentClass2 arg2);
}
package de.scrum_master.app;

public class SomeClass {
    public static void someClassMethod() {
        get(new AnotherClass() {
            @CustomAnnotation
            public Object handle(ArgumentClass1 arg1, ArgumentClass2 arg2) {
                return "dummy";
            }
        });
    }

    public static Object get(AnotherClass anotherClass) {
        return anotherClass.handle(new ArgumentClass1(), new ArgumentClass2());
    }

    private static void anotherClassMethod(String string, String string2) {}

    @CustomAnnotation
    private static void yetAnotherClassMethod(int i, int j) {}

    public static void main(String[] args) {
        someClassMethod();
        anotherClassMethod("foo", "bar");
        yetAnotherClassMethod(11, 22);
    }
}
package de.scrum_master.aspect;

import de.scrum_master.app.CustomAnnotation;

public aspect AnnotatedMethodInterceptor {
    Object around() : execution(@CustomAnnotation * *(..)) {
        System.out.println(thisJoinPoint);
        for (Object arg : thisJoinPoint.getArgs()) {
            System.out.println("  Checking argument " + arg);
        }
        return proceed();
    }
}
带有一些示例方法的应用程序类:

package de.scrum_master.app;

public class ArgumentClass1 {}
package de.scrum_master.app;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {}
package de.scrum_master.app;

public abstract class AnotherClass {
    public abstract Object handle(ArgumentClass1 arg1, ArgumentClass2 arg2);
}
package de.scrum_master.app;

public class SomeClass {
    public static void someClassMethod() {
        get(new AnotherClass() {
            @CustomAnnotation
            public Object handle(ArgumentClass1 arg1, ArgumentClass2 arg2) {
                return "dummy";
            }
        });
    }

    public static Object get(AnotherClass anotherClass) {
        return anotherClass.handle(new ArgumentClass1(), new ArgumentClass2());
    }

    private static void anotherClassMethod(String string, String string2) {}

    @CustomAnnotation
    private static void yetAnotherClassMethod(int i, int j) {}

    public static void main(String[] args) {
        someClassMethod();
        anotherClassMethod("foo", "bar");
        yetAnotherClassMethod(11, 22);
    }
}
package de.scrum_master.aspect;

import de.scrum_master.app.CustomAnnotation;

public aspect AnnotatedMethodInterceptor {
    Object around() : execution(@CustomAnnotation * *(..)) {
        System.out.println(thisJoinPoint);
        for (Object arg : thisJoinPoint.getArgs()) {
            System.out.println("  Checking argument " + arg);
        }
        return proceed();
    }
}
如您所见,有一些静态方法,部分是public/private,其中一个由
@CustomAnnotation
注释,另一个不是,一个包含一个匿名类,具体化了上面的抽象类,还包含一个由
@CustomAnnotation
注释的方法。我们应该期望
yetAnotherClassMethod(int,int)
handle(ArgumentClass1,ArgumentClass2)
被方面截获,因为它们带有我们的目标注释

最后,但并非最不重要的是

带有自定义注释的方面拦截方法:

package de.scrum_master.app;

public class ArgumentClass1 {}
package de.scrum_master.app;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {}
package de.scrum_master.app;

public abstract class AnotherClass {
    public abstract Object handle(ArgumentClass1 arg1, ArgumentClass2 arg2);
}
package de.scrum_master.app;

public class SomeClass {
    public static void someClassMethod() {
        get(new AnotherClass() {
            @CustomAnnotation
            public Object handle(ArgumentClass1 arg1, ArgumentClass2 arg2) {
                return "dummy";
            }
        });
    }

    public static Object get(AnotherClass anotherClass) {
        return anotherClass.handle(new ArgumentClass1(), new ArgumentClass2());
    }

    private static void anotherClassMethod(String string, String string2) {}

    @CustomAnnotation
    private static void yetAnotherClassMethod(int i, int j) {}

    public static void main(String[] args) {
        someClassMethod();
        anotherClassMethod("foo", "bar");
        yetAnotherClassMethod(11, 22);
    }
}
package de.scrum_master.aspect;

import de.scrum_master.app.CustomAnnotation;

public aspect AnnotatedMethodInterceptor {
    Object around() : execution(@CustomAnnotation * *(..)) {
        System.out.println(thisJoinPoint);
        for (Object arg : thisJoinPoint.getArgs()) {
            System.out.println("  Checking argument " + arg);
        }
        return proceed();
    }
}
我没有检查示例中的参数,而是在参数数组上循环以打印它们。不过,你可以在这里做任何你想做的事

现在请弄清楚AOP和AspectJ语法都是关于什么的。有足够的教程,只要使用你最喜欢的搜索引擎或从开始

示例代码控制台输出:

package de.scrum_master.app;

public class ArgumentClass1 {}
package de.scrum_master.app;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {}
package de.scrum_master.app;

public abstract class AnotherClass {
    public abstract Object handle(ArgumentClass1 arg1, ArgumentClass2 arg2);
}
package de.scrum_master.app;

public class SomeClass {
    public static void someClassMethod() {
        get(new AnotherClass() {
            @CustomAnnotation
            public Object handle(ArgumentClass1 arg1, ArgumentClass2 arg2) {
                return "dummy";
            }
        });
    }

    public static Object get(AnotherClass anotherClass) {
        return anotherClass.handle(new ArgumentClass1(), new ArgumentClass2());
    }

    private static void anotherClassMethod(String string, String string2) {}

    @CustomAnnotation
    private static void yetAnotherClassMethod(int i, int j) {}

    public static void main(String[] args) {
        someClassMethod();
        anotherClassMethod("foo", "bar");
        yetAnotherClassMethod(11, 22);
    }
}
package de.scrum_master.aspect;

import de.scrum_master.app.CustomAnnotation;

public aspect AnnotatedMethodInterceptor {
    Object around() : execution(@CustomAnnotation * *(..)) {
        System.out.println(thisJoinPoint);
        for (Object arg : thisJoinPoint.getArgs()) {
            System.out.println("  Checking argument " + arg);
        }
        return proceed();
    }
}
执行(Object de.scrum\u master.app.SomeClass.1.handle(ArgumentClass1,ArgumentClass2))
正在检查参数de.scrum\u master.app。ArgumentClass1@1bdf2b92
正在检查参数de.scrum\u master.app。ArgumentClass2@58a58c89
执行(void de.scrum_master.app.SomeClass.yetAnotherClassMethod(int,int))
核对论点11
核对论据22

你是在找一个好朋友吗?@John,也许是的,因为我对术语不太熟悉。我看了你所指的页面,但我看不到任何关于什么是切入点以及如何准确实现切入点的解释。我正在寻找一种最简单的方法来做我想做的事情——在执行调用的方法之前执行一些检查。对我来说,注释似乎是一种方式,但我能找到的所有教程都是针对那些已经有相当好的知识的人,而不是完全的新手(我做了很多POJO,从来没有做过AOP)。虽然这个答案可能有用,但它“有点”自大。你自己不这么认为吗?正如我在问题中所说,我主要来自POJO开发。我在阅读和学习maven和gradle时没有遇到任何困难,因为有很多很好的教程和文档。关于AOP,我能找到的只是一些教程,不是针对那些决定第一次接触它的人,而是针对那些已经熟悉AspectJ的所有术语和官方文档的人。请原谅,这个回答的语气非常傲慢。至于例子——谢谢,我会试试。你可以跳过引号,我承认我的答案很自负。那又怎么样?我的批评是实质性的,我的回答也是建设性的。没有好的AOP教程是不正确的。如果您阅读,您将看到它是针对来自POJO开发的绝对初学者的。我自己也是一名POJO开发人员,我从不使用Spring或EJB。我通过阅读教程和其他文档材料自学AspectJ。我还可以推荐Ramnivas Laddad的《AspectJ在行动》一书。祝你好运