Java 在调用其他方法时随时调用方法

Java 在调用其他方法时随时调用方法,java,Java,是否有任何方法可以使一种“超级方法”在每次调用一个方法时都被调用,即使对于未定义的方法也是如此?有点像这样: public void onStart() { System.out.println("Start"); } public void onEnd() { System.out.println("End"); } public SuperMethod superMethod() { System.out.println("Super"); } // "Star

是否有任何方法可以使一种“超级方法”在每次调用一个方法时都被调用,即使对于未定义的方法也是如此?有点像这样:

public void onStart() {
    System.out.println("Start");
}

public void onEnd() {
    System.out.println("End");
}

public SuperMethod superMethod() {
    System.out.println("Super");
}

// "Start"
// "Super"
onStart();

// "End"
// "Super"
onEnd();

// "Super"
onRun();

编辑细节:我有一个更新很多的库,每次更新都会被重新使用。为了简化我的工作流程,我让我的程序自动更新库(需要做我希望它做的事情,我不会详细说明原因,但我的程序将在以后的更新中工作),并且我有随库下载的模糊映射,例如,我想创建一种名为
Library
的代理,然后当我调用
Library.getInstance()
时,它将获得
getInstance()
的模糊映射,并调用库的方法
getInstance()
abz
,因为它是在当前时刻映射到的。

Java实际上不允许这样的魔法。为了让调用发生,它必须出现在(编译的)代码中。因此答案是否定的,除非明确地添加对相关方法的调用。但是,您可以通过使用预处理器或运行时代码生成来隐藏这一点


我认为AspectJ可能是您想要的。

当然您可以做到这一点,不是用标准java,而是用

下面是一个简单的例子:

事后劝告

package net.fsa.aspectj.test;


public aspect SuperMethdAspect {

    pointcut afterPointCut() : execution(public * com.my.pack.age.MyClass.*(..));

    after() : afterPointCut() {
        System.out.println("Super");
    }
}
你的目标阶级

package com.my.pack.age;

public class MyClass {

    public void onStart() {
        System.out.println("Start");
    }

    public void onEnd() {
        System.out.println("End");
    }
}
最后是一些测试应用程序

package net.fsa.aspectj.test;

import com.my.pack.age.MyClass;

public class MyApp {

    public static void main(String... args) {
        MyClass myClass = new MyClass();
        myClass.onStart();
        myClass.onEnd();
    }
}
输出

Start
Super
End
Super

我想这并不完全是您想要的,但是您可以将方法中的所有代码包装成
try{}最后{supermethod()}

这就是所谓的超级方法。

这个概念背后的术语叫做拦截器。您需要一个这样做的容器,如ApplicationServer、CDI容器、Spring或AOP。它是这样工作的

1. call your Method
2. pause your Method
3. call intercepter
4. do interceptor stuff
5. resume your Method inside the interceptor

下面是使用类的纯Java实现:


为什么要这样做?请注意,使用
super
这个词很容易混淆,因为它在java中已经有其他含义。您需要熟悉方面。在普通java中这是不可能的,但在AOP(面向方面编程)中,可以在调用方法之前/之后调用方法。AOP框架的一个例子是SpringAOP()。怎么样?谢谢。还有什么方法可以使
com.my.pack.age.MyClass
动态化吗?库的映射一直在变化。@JordanDoyle允许进行许多组合。如果您不知道要交换的包/类的集合,那么您可能需要多个方面,例如每个库一个方面,实际功能放在其他类中。如果你想把一个包中的ALS类作为目标,那么你可以使用<代码> COM.MyPo.Acth.*.*/Cux> @ JordanDoyle。如果你不能编译目标类,那么你绝对需要考虑这是绝对完美的,而且正是我所需要的。谢谢=有没有办法代理字段@tom?谢谢。@JordanDoyle不直接,但您可以将getter/setter添加到接口中,并让代理将它们转换为字段访问。如果库是一个具有参数化构造函数的类,该怎么办?@Venkatesh:构造函数没有名称,因此它们不会被混淆。您可以正常创建模糊类的实例,然后将其传递给代理。在我的示例中,如果
librarympl
有一个构造函数,例如
librarympl(字符串s,int i)
,您将使用
newlibraryproxy(映射,newlibrarympl(“x”,1)).proxy()
import java.lang.reflect.*;
import java.util.*;

public class Demo
{
    public static void main(String[] args)
    {
        Map<String, String> map = new HashMap<String, String>();
        map.put("onStart", "abc");
        map.put("onEnd", "def");
        Library library = new LibraryProxy(map, new LibraryImpl()).proxy();
        library.onStart();
        library.onEnd();
        library.onRun();
    }
}

interface Library
{
    void onStart();
    void onEnd();
    void onRun();
}

class LibraryImpl
{
    public void abc() { System.out.println("Start"); }
    public void def() { System.out.println("End"); }
}

class LibraryProxy implements InvocationHandler
{
    Map<String, String> map;
    Object impl;

    public LibraryProxy(Map<String, String> map, Object impl)
    {
        this.map = map;
        this.impl = impl;
    }

    public Library proxy()
    {
        return (Library) Proxy.newProxyInstance(Library.class.getClassLoader(),
            new Class[] { Library.class }, this);
    }

    @Override
    public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
    {
        Object res = null;
        String name = map.get(m.getName());
        if (name == null) {
            System.out.println("[" + m.getName() + " is not defined]");
        } else {
            m = impl.getClass().getMethod(name, m.getParameterTypes());
            res = m.invoke(impl, args);
        }
        System.out.println("super duper");
        return res;
    }
}