在我的代理类中为每个方法执行 InvocationHandler 调用方法

我已经实现了一个动态代理,以便在我的方法开始之前执行一些操作。现在我从代理类调用两个方法时遇到问题,这里是代码:


动态代理类:


public class IPageProxy implements InvocationHandler {


    private Class <? extends IPage> screenClazz;


    public IPageProxy(final Class <? extends IPage> screenClazz) {

        this.screenClazz = screenClazz;

    }


    @SuppressWarnings("unchecked")

    public static <T extends IPage> T getInstance(final Class<? extends IPage> type)

            throws InstantiationException, IllegalAccessException {


        List<Class<?>> interfaces = new ArrayList<>();

        interfaces.addAll(Arrays.asList(type.getInterfaces()));


        return (T) Proxy.newProxyInstance(

                type.getClassLoader(),

                findInterfaces(type),

                new IPageProxy(type)

             );


    }



    static Class<?>[] findInterfaces(final Class<? extends IPage> type) {

        Class<?> current = type;


        do {

            final Class<?>[] interfaces = current.getInterfaces();


            if (interfaces.length != 0) {

                return interfaces;

            }

        } while ((current = current.getSuperclass()) != Object.class);


        throw new UnsupportedOperationException("The type does not implement any interface");

    }






    @Override

    public Object invoke(final Object proxy, final Method method, final Object[] args) throws InvocationTargetException,

            IllegalAccessException, IllegalArgumentException, InstantiationException, ParserConfigurationException, XPathExpressionException, NoSuchFieldException, SecurityException {


        // before method executed this code will be done

        System.out.println("*   Dynamic proxy invoke method executed for " +  method.getName());


        // Invoke original method

        return method.invoke(screenClazz.newInstance(), args);

    }

}


饮歌长啸
浏览 196回答 2
2回答

郎朗坤

发生的事情是,首先您只代理第一次调用,然后您在非代理类上调用 getShow(),这就是为什么您会得到您提到的结果。如果你想实现你提到的目标,你需要基于创建的实例而不是仅仅基于类创建另一个代理。更新:我将提供示例代码,您可以粘贴到任何 java 文件中并执行它。在你看到 TODO 的地方,你可以根据你想要提供代理的方式放置你自己的逻辑。重要时刻见注。为了简化演示,我将所有类放在一个文件中。import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.Arrays;import java.util.List;class Scratch {&nbsp; &nbsp; public static void main(String[] args) {&nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IEventDesignDialog a&nbsp; = proxy(EventDesignDialog.class);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; a.getEventType().getShow();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; a.getDateAndTimeDisplayFormat().getShow();&nbsp; &nbsp; &nbsp; &nbsp; } catch (InstantiationException | IllegalAccessException e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; @SuppressWarnings("unchecked")&nbsp; &nbsp; private static <T extends IPage> T proxy(final Class<? extends IPage> type) throws InstantiationException, IllegalAccessException {&nbsp; &nbsp; &nbsp; &nbsp; return (T) IPageProxy.proxy(type);&nbsp; &nbsp; }}interface IPage{}interface IEventDesignDialog extends IPage{&nbsp; &nbsp; IEventDesignDialog getShow();&nbsp; &nbsp; IEventDesignDialog getEventType();&nbsp; &nbsp; IEventDesignDialog getDateAndTimeDisplayFormat();}class EventDesignDialog implements IEventDesignDialog{&nbsp; &nbsp; public IEventDesignDialog getShow() {&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("get show method invoked successfully");&nbsp; &nbsp; &nbsp; &nbsp; //NOTE: this will be treated as same proxy but not this&nbsp; &nbsp; &nbsp; &nbsp; return this;&nbsp; &nbsp; }&nbsp; &nbsp; public IEventDesignDialog getDateAndTimeDisplayFormat() {&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("get date and time display format method invoked successfully");&nbsp; &nbsp; &nbsp; &nbsp; // NOTE: we supply some iinstance which will be proxied&nbsp; &nbsp; &nbsp; &nbsp; return new MyIEventDesignDialog();&nbsp; &nbsp; }&nbsp; &nbsp; public IEventDesignDialog getEventType() {&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("get event type method invoked successfully");&nbsp; &nbsp; &nbsp; &nbsp; //NOTE: this will be treated as same proxy but not this&nbsp; &nbsp; &nbsp; &nbsp; return this;&nbsp; &nbsp; }}class IPageProxy implements InvocationHandler {&nbsp; &nbsp; private IPage instance;&nbsp; &nbsp; private List<Class<?>> interfaces;&nbsp; &nbsp; public IPageProxy(IPage instance, List<Class<?>> interfaces) {&nbsp; &nbsp; &nbsp; &nbsp; this.instance = instance;&nbsp; &nbsp; &nbsp; &nbsp; this.interfaces = interfaces;&nbsp; &nbsp; }&nbsp; &nbsp; @SuppressWarnings("unchecked")&nbsp; &nbsp; public static <T extends IPage> T proxy(final Class<? extends IPage> type)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throws InstantiationException, IllegalAccessException {&nbsp; &nbsp; &nbsp; &nbsp; List<Class<?>> interfaces = Arrays.asList(type.getInterfaces());&nbsp; &nbsp; &nbsp; &nbsp; //TODO: get interfaces properly recursively&nbsp; &nbsp; &nbsp; &nbsp; return (T) Proxy.newProxyInstance(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type.getClassLoader(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type.getInterfaces(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new IPageProxy(type.newInstance(), interfaces)&nbsp; &nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; }&nbsp; &nbsp; @SuppressWarnings("unchecked")&nbsp; &nbsp; public static <T extends IPage> T proxy(T object) {&nbsp; &nbsp; &nbsp; &nbsp; //TODO: get interfaces properly recursively&nbsp; &nbsp; &nbsp; &nbsp; List<Class<?>> interfaces = Arrays.asList(object.getClass().getInterfaces());&nbsp; &nbsp; &nbsp; &nbsp; return (T) Proxy.newProxyInstance(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; object.getClass().getClassLoader(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; object.getClass().getInterfaces(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new IPageProxy(object, interfaces)&nbsp; &nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public Object invoke(final Object proxy, final Method method, final Object[] args) throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; // before method executed this code will be done&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("*&nbsp; &nbsp;Dynamic proxy invoke method executed for " +&nbsp; method.getName());&nbsp; &nbsp; &nbsp; &nbsp; // Invoke original method&nbsp; &nbsp; &nbsp; &nbsp; Object invoke = method.invoke(instance, args);&nbsp; &nbsp; &nbsp; &nbsp; if (invoke == null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; //If some of the method returns the original object&nbsp; &nbsp; &nbsp; &nbsp; //we swap the returned object by our proxy&nbsp; &nbsp; &nbsp; &nbsp; if (invoke == instance) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return proxy;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; //TODO: check if you want to swap in place&nbsp; &nbsp; &nbsp; &nbsp; //other interfaces&nbsp; &nbsp; &nbsp; &nbsp; if (interfaces.contains(method.getReturnType())) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return IPageProxy.proxy((IPage)invoke);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return invoke;&nbsp; &nbsp; }}class MyIEventDesignDialog implements IEventDesignDialog {&nbsp; &nbsp; @Override&nbsp; &nbsp; public IEventDesignDialog getShow() {&nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public IEventDesignDialog getEventType() {&nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public IEventDesignDialog getDateAndTimeDisplayFormat() {&nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; }}输出:*&nbsp; &nbsp;Dynamic proxy invoke method executed for getEventTypeget event type method invoked successfully*&nbsp; &nbsp;Dynamic proxy invoke method executed for getShowget show method invoked successfully*&nbsp; &nbsp;Dynamic proxy invoke method executed for getDateAndTimeDisplayFormatget date and time display format method invoked successfully*&nbsp; &nbsp;Dynamic proxy invoke method executed for getShow您可以从 Mockito 的工作方式中获得灵感。请查看此页面:https ://static.javadoc.io/org.mockito/mockito-core/2.27.0/org/mockito/Mockito.html#spy-T-我知道它是用于测试的,但您仍然可以从中获得想法。所以你可以在一个类和一个对象上应用 spy() 来监视它。

慕盖茨4494581

我已经通过使用返回代理实例的默认方法创建一个接口来解决这个问题,然后在执行调用的方法功能后返回它:更新代码:public interface IPage {&nbsp; &nbsp; default <T extends IPage> T getProxyInstance() {&nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return (T) IPageProxy.getInstance(this.getClass());&nbsp; &nbsp; &nbsp; &nbsp; } catch (InstantiationException | IllegalAccessException e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; }}我的页面界面:@Page(path = "MyPath")public interface IEventDesignDialog extends IPage{&nbsp; &nbsp; @Entity(visibileName = "Show")&nbsp; &nbsp; public IEventDesignDialog getShow();&nbsp; &nbsp; @Entity(visibileName = "Date And Time display format")&nbsp; &nbsp; public IEventDesignDialog getDateAndTimeDisplayFormat();&nbsp; &nbsp; @Entity(visibileName = "Event Type")&nbsp; &nbsp; public IEventDesignDialog getEventType();&nbsp; &nbsp;&nbsp;}我的页面类:@Page(path = "MyPath")public class EventDesignDialog implements IEventDesignDialog{&nbsp; &nbsp; &nbsp; &nbsp; @Entity(visibileName = "Show")&nbsp; &nbsp; &nbsp; &nbsp; public IEventDesignDialog getShow() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("get show method invokde successfully");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return getProxyInstance();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; @Entity(visibileName = "Date And Time display format")&nbsp; &nbsp; &nbsp; &nbsp; public IEventDesignDialog getDateAndTimeDisplayFormat() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("get date and time display format method invokde successfully");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return getProxyInstance();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; @Entity(visibileName = "Event Type")&nbsp; &nbsp; &nbsp; &nbsp; public IEventDesignDialog getEventType() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("get event type method invokde successfully");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return getProxyInstance();&nbsp; &nbsp; &nbsp; &nbsp; }}主类:public class Main {&nbsp; &nbsp; public static void main(String[] args) {&nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IEventDesignDialog a&nbsp; = ((IEventDesignDialog)getInstance(EventDesignDialog.class)).getEventType().getShow();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ((IShowDesignDialog)getInstance(ShowDesignDialog.class)).getShowName().getShowType();&nbsp; &nbsp; &nbsp; &nbsp; } catch (InstantiationException | IllegalAccessException e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; @SuppressWarnings("unchecked")&nbsp; &nbsp; public static <T extends IPage> T getInstance(final Class<? extends IPage> type) throws InstantiationException, IllegalAccessException {&nbsp; &nbsp; &nbsp; &nbsp; return (T) IPageProxy.getInstance(type);&nbsp; &nbsp; }}IProxy 页面保持不变,无需更改。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java