gpt4 book ai didi

java - 覆盖外部对象的方法

转载 作者:行者123 更新时间:2023-11-29 07:02:54 24 4
gpt4 key购买 nike

我有一种情况,我想拦截/覆盖外部(我无权访问它们)对象的方法。我的情况的一个例子:

我有一个外部对象:

public class ExternalObject {
private String name;

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}
}

外部类女巫使用它:

public class ExternalClass {
public static void main(String[] args) {
ExternalObject o = new ExternalObject();
o.setName("Tom");

MyClass.doSomething(o);

o.setName("Jerry");

System.out.print(o.getName());
}
}

然后是 MyClass 女巫有机会访问外部对象:

public class MyClass {
public static void doSomething(ExternalObject o){

}
}

是否可以覆盖或修改MyClass中的setName方法?我需要的是让 setName 方法检查名称是否为“jerry”,然后将其改回“tom”,如果不是,则执行原始方法的操作。

像这样:

public void mySetName(String name){
if(name.equals("Jerry"){
name = "Tom";
}
doWhatOriginalMethodDoes();
}

因此,如果有人像现在这样运行外部类,那么 Tom 将被打印两次。

顺便说一句,外部(原始)对象和方法非常复杂。我四处搜索,这应该可以与 reflect.Proxy 相关,但我无法让它工作。

感谢您的帮助! :)

最佳答案

最简单的方法是使用继承:

public class MySubClass extends ExternalObject {

private ExternalObject obj;

public MySubClass(ExternalObject obj) {
this.obj = obj;
}

@Override
public void setName(String name){
if(name.equals("Jerry") {
super.setName("Tom");
} else {
super.setName(name);
}
}

// override all public method to call super method
@Override
public AClass otherMethod1(BClass arg){
return super.otherMethod1(arg);
}

@Override
public CClass otherMethod2(DClass arg){
return super.otherMethod2(arg);
}
}

由于 MySubClass 是一个 ExternalObject,您可以调用:

MySubClass subObject = new MySubClass(o);
MyClass.doSomething(subObject);

或者,如果您的类实现了一个接口(interface),您可以使用代理:

首先,定义一个InvocationHandler

public Class ExternalObjectInterfaceInvocationHandler implements java.lang.reflect.InvocationHandler {

// keep a reference to the wrapped object
private ExternalObjectInterface obj;

public ExternalObjectInterfaceInvocationHandler(ExternalObjectInterface obj) {
this.obj = obj;
}

public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
try {
if (m.getName().equals("setName")) {
// do something
}
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw e;
}
// return something
}
}

然后用代理包裹你的对象:

ExternalObjectInterface obj = ...

//wrap the obj with a proxy
ExternalObjectInterface wrappedInstance = (ExternalObjectInterface) Proxy.newProxyInstance(
ExternalObjectInterface.class.getClassLoader(),
new Class[] {ExternalObjectInterface.class},
new ExternalObjectInterfaceHandler( obj )
);

然后调用:

MyClass.doSomething(wrappedInstance);

如果您的对象没有实现接口(interface),第三种解决方案是使用 CGLib:

<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>

要包装你的对象,你可以使用这样的东西:

public static <S,W> W createWrapper(final S source, final Class<W> wrapperClass) {

Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(wrapperClass);
enhancer.setInterfaces(wrapperClass.getInterfaces());
enhancer.setCallback(new MethodInterceptor() {

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

if ("setName".equals(method.getName())) {
//do something
return null;
}

if (Arrays.asList(wrapperClass.getDeclaredMethods()).contains(method)) {
return methodProxy.invokeSuper(proxy, args);
}

return methodProxy.invoke(source, args);
}
});

return (W) enhancer.create();
}

使用 CGLib 的一些例子 herehere

关于java - 覆盖外部对象的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23296139/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com