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

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 頁面保持不變,無需更改。
添加回答
舉報