亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在我的代理類中為每個方法執行 InvocationHandler 調用方法

在我的代理類中為每個方法執行 InvocationHandler 調用方法

飲歌長嘯 2022-11-02 10:00:56
我已經實現了一個動態代理,以便在我的方法開始之前執行一些操作?,F在我從代理類調用兩個方法時遇到問題,這里是代碼:動態代理類: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);    }}
查看完整描述

2 回答

?
郎朗坤

TA貢獻1921條經驗 獲得超9個贊

發生的事情是,首先您只代理第一次調用,然后您在非代理類上調用 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 {

    public static void main(String[] args) {

        try {

            IEventDesignDialog a  = proxy(EventDesignDialog.class);

            a.getEventType().getShow();

            a.getDateAndTimeDisplayFormat().getShow();

        } catch (InstantiationException | IllegalAccessException e) {

            e.printStackTrace();

        }

    }



    @SuppressWarnings("unchecked")

    private static <T extends IPage> T proxy(final Class<? extends IPage> type) throws InstantiationException, IllegalAccessException {

        return (T) IPageProxy.proxy(type);

    }

}

interface IPage{}

interface IEventDesignDialog extends IPage{

    IEventDesignDialog getShow();

    IEventDesignDialog getEventType();

    IEventDesignDialog getDateAndTimeDisplayFormat();

}

class EventDesignDialog implements IEventDesignDialog{


    public IEventDesignDialog getShow() {

        System.out.println("get show method invoked successfully");


        //NOTE: this will be treated as same proxy but not this

        return this;

    }


    public IEventDesignDialog getDateAndTimeDisplayFormat() {

        System.out.println("get date and time display format method invoked successfully");


        // NOTE: we supply some iinstance which will be proxied

        return new MyIEventDesignDialog();

    }


    public IEventDesignDialog getEventType() {

        System.out.println("get event type method invoked successfully");


        //NOTE: this will be treated as same proxy but not this

        return this;

    }


}

class IPageProxy implements InvocationHandler {


    private IPage instance;

    private List<Class<?>> interfaces;



    public IPageProxy(IPage instance, List<Class<?>> interfaces) {

        this.instance = instance;

        this.interfaces = interfaces;

    }


    @SuppressWarnings("unchecked")

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

            throws InstantiationException, IllegalAccessException {


        List<Class<?>> interfaces = Arrays.asList(type.getInterfaces());



        //TODO: get interfaces properly recursively

        return (T) Proxy.newProxyInstance(

                type.getClassLoader(),

                type.getInterfaces(),

                new IPageProxy(type.newInstance(), interfaces)

        );


    }


    @SuppressWarnings("unchecked")

    public static <T extends IPage> T proxy(T object) {


        //TODO: get interfaces properly recursively

        List<Class<?>> interfaces = Arrays.asList(object.getClass().getInterfaces());


        return (T) Proxy.newProxyInstance(

                object.getClass().getClassLoader(),

                object.getClass().getInterfaces(),

                new IPageProxy(object, interfaces)

        );


    }





    @Override

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


        // before method executed this code will be done

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


        // Invoke original method

        Object invoke = method.invoke(instance, args);

        if (invoke == null) {

            return null;

        }


        //If some of the method returns the original object

        //we swap the returned object by our proxy

        if (invoke == instance) {

            return proxy;

        }


        //TODO: check if you want to swap in place

        //other interfaces

        if (interfaces.contains(method.getReturnType())) {

            return IPageProxy.proxy((IPage)invoke);

        }

        return invoke;

    }

}


class MyIEventDesignDialog implements IEventDesignDialog {

    @Override

    public IEventDesignDialog getShow() {

        return null;

    }


    @Override

    public IEventDesignDialog getEventType() {

        return null;

    }


    @Override

    public IEventDesignDialog getDateAndTimeDisplayFormat() {

        return null;

    }

}

輸出:


*   Dynamic proxy invoke method executed for getEventType

get event type method invoked successfully

*   Dynamic proxy invoke method executed for getShow

get show method invoked successfully

*   Dynamic proxy invoke method executed for getDateAndTimeDisplayFormat

get date and time display format method invoked successfully

*   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() 來監視它。


查看完整回答
反對 回復 2022-11-02
?
慕蓋茨4494581

TA貢獻1850條經驗 獲得超11個贊

我已經通過使用返回代理實例的默認方法創建一個接口來解決這個問題,然后在執行調用的方法功能后返回它:


更新代碼:


public interface IPage {

    default <T extends IPage> T getProxyInstance() {

        try {

            return (T) IPageProxy.getInstance(this.getClass());

        } catch (InstantiationException | IllegalAccessException e) {

            e.printStackTrace();

        }

        return null;

    }

}

我的頁面界面:


@Page(path = "MyPath")

public interface IEventDesignDialog extends IPage{

    @Entity(visibileName = "Show")

    public IEventDesignDialog getShow();


    @Entity(visibileName = "Date And Time display format")

    public IEventDesignDialog getDateAndTimeDisplayFormat();


    @Entity(visibileName = "Event Type")

    public IEventDesignDialog getEventType();    

}

我的頁面類:


@Page(path = "MyPath")

public class EventDesignDialog implements IEventDesignDialog{

        @Entity(visibileName = "Show")

        public IEventDesignDialog getShow() {

            System.out.println("get show method invokde successfully");

            return getProxyInstance();

        }


        @Entity(visibileName = "Date And Time display format")

        public IEventDesignDialog getDateAndTimeDisplayFormat() {

            System.out.println("get date and time display format method invokde successfully");

            return getProxyInstance();

        }


        @Entity(visibileName = "Event Type")

        public IEventDesignDialog getEventType() {

            System.out.println("get event type method invokde successfully");

            return getProxyInstance();

        }

}

主類:


public class Main {


    public static void main(String[] args) {

        try {

            IEventDesignDialog a  = ((IEventDesignDialog)getInstance(EventDesignDialog.class)).getEventType().getShow();


            ((IShowDesignDialog)getInstance(ShowDesignDialog.class)).getShowName().getShowType();

        } catch (InstantiationException | IllegalAccessException e) {

            e.printStackTrace();

        }

    }



    @SuppressWarnings("unchecked")

    public static <T extends IPage> T getInstance(final Class<? extends IPage> type) throws InstantiationException, IllegalAccessException {

        return (T) IPageProxy.getInstance(type);

    }


}

IProxy 頁面保持不變,無需更改。


查看完整回答
反對 回復 2022-11-02
  • 2 回答
  • 0 關注
  • 168 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號