Java: Is it possible to always execute a certain function before other functions are called? (Like @Before in JUnit)

前端 未结 7 1574
情歌与酒
情歌与酒 2021-01-02 23:59

Is there a way to always execute a function before any other function of a class is called?

I have a class where I need to refresh some fields always before any func

7条回答
  •  离开以前
    2021-01-03 00:38

    Use a dynamic proxy in which you can filter to those methods before which your specific "before" method should be called. And call it in those cases before dispatching the call. Please see the answer from How do I intercept a method invocation with standard java features (no AspectJ etc)?

    UPDATE:

    An interface is needed to be separated for the proxy. The refresh() method cannot remain private. It must be public and part of the interface (which is not nice here) to be able to be called from the proxy.

    package CallBefore;
    
    public interface ExampleInterface {
        void function1();
    
        void function2();
    
        void otherFunction();
    
        void refresh();
    }
    

    Your class implements that interface:

    package CallBefore;
    
    public class Example implements ExampleInterface {
    
        @Override
        public void function1() {
        System.out.println("function1() has been called");
        }
    
        @Override
        public void function2() {
        System.out.println("function2() has been called");
        }
    
        @Override
        public void otherFunction() {
        System.out.println("otherFunction() has been called");
        }
    
        @Override
        public void refresh() {
        System.out.println("refresh() has been called");
        }
    }
    

    The proxy which does the trick. It filters the needed methods and calls refresh().

    package CallBefore;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class ExampleProxy implements InvocationHandler {
    
        private ExampleInterface obj;
    
        public static ExampleInterface newInstance(ExampleInterface obj) {
        return (ExampleInterface) java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),
            obj.getClass().getInterfaces(), new ExampleProxy(obj));
        }
    
        private ExampleProxy(ExampleInterface obj) {
        this.obj = obj;
        }
    
        @Override
        public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
        Object result;
        try {
            if (m.getName().startsWith("function")) {
            obj.refresh();
            }
            result = m.invoke(obj, args);
        } catch (InvocationTargetException e) {
            throw e.getTargetException();
        } catch (Exception e) {
            throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
        }
        return result;
        }
    }
    

    The usage:

    package CallBefore;
    
    public class Main {
    
        public static void main(String[] args) {
    
        ExampleInterface proxy = ExampleProxy.newInstance(new Example());
        proxy.function1();
        proxy.function2();
        proxy.otherFunction();
        proxy.refresh();
        }
    }
    

    Output:

    refresh() has been called
    function1() has been called
    refresh() has been called
    function2() has been called
    otherFunction() has been called
    refresh() has been called
    

提交回复
热议问题