Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何对带注释方法的每个方法调用执行某些操作?_Java_Spring_Annotations_Aspectj - Fatal编程技术网

Java 如何对带注释方法的每个方法调用执行某些操作?

Java 如何对带注释方法的每个方法调用执行某些操作?,java,spring,annotations,aspectj,Java,Spring,Annotations,Aspectj,我想用Java编写一个注释,它在执行带注释的方法之前和之后执行一些东西,类似于Spring中的aspects 我已经尝试了Spring方面,但它只适用于bean(),我希望保持独立于Spring框架 将字符串写入控制台的简单类: public class Main { public static void main(String[] args) { say("How are you?"); } @Hello private s

我想用Java编写一个注释,它在执行带注释的方法之前和之后执行一些东西,类似于Spring中的aspects

我已经尝试了Spring方面,但它只适用于bean(),我希望保持独立于Spring框架

将字符串写入控制台的简单类:

public class Main {
    public static void main(String[] args) {
        say("How are you?");
    }

    @Hello
    private static void say(String s) {
        System.out.println(s);
    }
}
关联的注释:

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Hello {}
我需要这样的东西(从春天的角度推断)

我想要以下输出:

你好

你好吗

世界

编辑:

我创建了以下方面(没有注释),但它不起作用

@lombok.extern.java.Log
public aspect Log {
    pointcut methodExecuted():execution(* **(..));

    void around(): methodExecuted() {
        log.info("Hello");
        proceed();
        log.info("world!");
    }
}

我的错误在哪里?

假设您使用AspectJ编译器成功编译了aspect,它应该与您使用的代码一起工作,只是它会记录所有方法的执行,也就是说,
main(…)
,所以您会在“你好吗?”前后两次使用aspect的输出。如果您没有看到任何东西,则可能是您在设置构建系统时犯了错误

您应该更改切入点以实际限制日志记录到带注释的方法:
execution(**(..)&&&@annotation(Hello)
。此外,如果您的around通知具有void返回类型,则日志记录将无法使用非void方法。因此,您应该使用返回类型
Object
,并实际返回
procedure()
的结果

我还强烈建议您不仅要盲目使用AspectJ这样的强大工具,还要在使用之前研究一些文档。很明显,你没有这样做,或者只是很草率地这样做。然后,你就得到了一种效果,那就是使用工具时,你的能力不是很强。;-)

这是我的:

package de.scrum\u master.app;
公共类应用程序{
公共静态void main(字符串[]args){
说(“你好吗?”);
}
@你好
私有静态void say(字符串s){
系统输出打印项次;
}
}
package de.scrum\u master.aspect;
导入de.scrum_master.app.Hello;
公共方面{
切入点方法执行():执行(**(..)&&&@注释(Hello);
对象环绕():methodExecuted(){
System.out.println(“你好”);
对象结果=继续();
System.out.println(“世界!”);
返回结果;
}
}
控制台日志:

你好 你好吗 世界
嗯,您需要一些东西来拦截这些方法调用。Java不会开箱即用,因此您需要“编织”一些itercepting代码,即您需要一个框架。如果您不想或不能使用Spring AOP,请看一看AspectJ。正如我所说,对于Spring,我有一个问题,即注释只适用于bean,或者我误解了什么?好吧,理论上几乎所有东西都可以是bean。bean将使框架能够将实例包装在代理中,以拦截调用,从而更易于使用。对于没有被框架实例化的非bean类或“bean”,您需要将拦截代码编织到类本身中——这可能发生在编译或加载时。在这里查看一些关于如何使用Spring实现AOP(加载时编织)的信息:我一直在回答,但它不起作用。我相应地编辑了我的问题。它不限于bean,它目前是有限的,因为您使用的是基于代理的SpringAOP,它只适用于bean。您可以将成熟的aspectj与编译或加载时编织结合使用,这实际上修改了字节码并在其中注入了代码,无论是否使用Spring。您编写的aspects已经是基于AspectJ的aspects,与Spring无关。您不需要AspectJ语言中的aspects,
@aspect
一个也可以很好地工作。您这样说似乎是一个优势。在我看来不是。本机语法更具表现力,不会尝试将所有内容都放入注释中。此外,OP在他自己的示例中使用了本机语法,我坚持使用它,很高兴看到(对我来说)一些更可读的更改。我不知道为什么@AspectJ语法在Spring AOP之外如此流行,因为它是唯一的选择。OP从一个基于Java的示例开始,给人的印象是它只是Spring,我试图阻止/解释情况并非如此,因此我建议使用带注释的纯Java。我并不介意AspectJ类中的注释,另外的优点是不需要专门的编译器。另一方面,在本机语法imho.M中声明优先级和介绍要容易得多。Deinum,让我稍微限定一下您的一般语句:如果您不使用AspectJ编译器编译@AspectJ方面,它是未完成的,即您只能在LTW(加载时编织)中使用它场景,因为编织代理不仅需要编织方面,还需要在编织之前完成纯Java类,使其成为一个成熟的方面类。这同样意味着您需要能够控制JVM命令行。如果您想使用CTW(编译时编织),无论使用哪种语法变体,都无法使用AspectJ编译器。
@lombok.extern.java.Log
public aspect Log {
    pointcut methodExecuted():execution(* **(..));

    void around(): methodExecuted() {
        log.info("Hello");
        proceed();
        log.info("world!");
    }
}
package de.scrum_master.app;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(METHOD)
public @interface Hello {}