自动委托java类的所有方法 [英] Automatically delegating all methods of a java class

查看:95
本文介绍了自动委托java类的所有方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个有很多公共方法的课程:

  public class MyClass {

public void method1(){}
public void method2(){}
(...)
public void methodN(){}

}

现在我想创建一个包装器类,它将委托所有的方法来包装实例( delegate ):

  public class WrapperClass extends MyClass {
private final MyClass delegate ;

public WrapperClass(MyClass delegate){
this.delagate = delegate;
}

public void method1(){delegate.method1(); }
public void method2(){delegate.method2(); }
(...)
public void methodN(){delegate.methodN(); }

}

现在如果MyClass有很多方法我需要覆盖它们中的每一个,它们或多或少是只是代表的相同的代码。我想知道是否可以做一些魔术来自动调用Java中的一个方法(所以Wrapper类将需要说嘿,如果你调用一个方法我只是去委托对象和调用这个方法吧)。



BTW:我不能使用继承,因为委托不在我的控制之下。我只是从其他地方得到它的实例(另一种情况是MyClass是最终的)



注意:我不想要IDE生成,我知道我可以在IntelliJ / Eclipse的帮助下完成它,但是我很好奇,如果这可以在代码中完成。



任何建议如何实现这样的东西?(注意:我可能可以在一些脚本语言,如php,我可以使用php magic函数拦截调用)

解决方案

也许动态代理的java可以帮助你,它只有在你使用接口的情况下才有效,在这种情况下,我将调用接口 MyInterface 设置默认实现:

  public class MyClass实现MyInterface {

@Override
public void method1(){
System.out.println(foo1);
}

@Override
public void method2(){
System.out.println(foo2);


@Override
public void methodN(){
System.out.println(fooN);
}

public static void main(String [] args){
MyClass wrapped = new MyClass();
wrapped.method1();
wrapped.method2();
MyInterface wrapper = WrapperClass.wrap(wrapped);
wrapper.method1();
wrapper.method2();
}

}

包装器类实现看起来像:

  public class WrapperClass extends MyClass implements MyInterface,InvocationHandler {

private final MyClass delegate;

public WrapperClass(MyClass delegate){
this.delegate = delegate;
}

public static MyInterface wrap(MyClass wrapped){
return(MyInterface)Proxy.newProxyInstance(MyClass.class.getClassLoader(),new Class [] {MyInterface.class },新的WrapperClass(包装));
}

//你可以跳过这个定义,它只用于演示
public void method1(){
System.out.println(bar) ;
}

@Override
public Object invoke(Object proxy,Method method,Object [] args)throws Throwable {
方法m = findMethod(this.getClass ), 方法);
if(m!= null){
return m.invoke(this,args);
}
m = findMethod(delegate.getClass(),方法);
if(m!= null){
return m.invoke(delegate,args);
}
返回null;


私有方法findMethod(Class<?> clazz,Method method)throws Throwable {
try {
return clazz.getDeclaredMethod(method.getName() ,method.getParameterTypes());
} catch(NoSuchMethodException e){
返回null;
}
}

}

请注意这个类:




  • extends MyClass ,继承默认实现执行

  • 实现调用处理程序,以允许代理做反思

  • code> MyInterface (以满足装饰器模式)



此解决方案允许您覆盖特殊方法,而是委托所有其他人。这将使用Wrapper类的子类。



请注意,方法 findMethod 尚未捕获特殊案件


Say I have a class with many of public methods:

public class MyClass {

    public void method1() {}
    public void method2() {}
    (...)
    public void methodN() {}

}

Now I would like to create a wrapper class which would delegate all the methods to wrapped instance (delegate):

public class WrapperClass extends MyClass  {
    private final MyClass delegate;

    public WrapperClass(MyClass delegate) {
        this.delagate = delegate;
    }

    public void method1() { delegate.method1(); }
    public void method2() { delegate.method2(); }
    (...)
    public void methodN() { delegate.methodN(); }

}

Now if MyClass has a lot of methods I would need to override each of them which is more or less the same code which just "delegates". I was wondering if it is possible to do some magic to automatically call a method in Java (so the Wrapper class would need to say "Hey if you call a method on me just go to delegate object and call this method on it).

BTW: I can not use inheritance because the delegate is not under my control.I just get its instance from elsewhere (another case would be if MyClass was final).

NOTE: I do not want IDE generation. I know I can do it with help of IntelliJ/Eclipse, but I'm curious if this can be done in code.

Any suggestions how to achieve something like this? (NOTE: I would probably be able to do it in some scripting languages like php where I could use php magic functions to intercept the call).

解决方案

Perhaps the dynamic Proxy of java can help you. It only works if you consequently use interfaces. In this case, I will call the interface MyInterface and set up a default implementation:

public class MyClass implements MyInterface {

    @Override
    public void method1() {
        System.out.println("foo1");
    }

    @Override
    public void method2() {
        System.out.println("foo2");
    }

    @Override
    public void methodN() {
        System.out.println("fooN");
    }

    public static void main(String[] args) {
        MyClass wrapped = new MyClass();
        wrapped.method1();
        wrapped.method2();
        MyInterface wrapper = WrapperClass.wrap(wrapped);
        wrapper.method1();
        wrapper.method2();
    }

}

The wrapper class implementation would look like:

public class WrapperClass extends MyClass implements MyInterface, InvocationHandler {

    private final MyClass delegate;

    public WrapperClass(MyClass delegate) {
        this.delegate = delegate;
    }

    public static MyInterface wrap(MyClass wrapped) {
        return (MyInterface) Proxy.newProxyInstance(MyClass.class.getClassLoader(), new Class[] { MyInterface.class }, new WrapperClass(wrapped));
    }

    //you may skip this definition, it is only for demonstration
    public void method1() {
        System.out.println("bar");
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Method m = findMethod(this.getClass(), method);
        if (m != null) {
            return m.invoke(this, args);
        }
        m = findMethod(delegate.getClass(), method);
        if (m != null) {
            return m.invoke(delegate, args);
        }
        return null;
    }

    private Method findMethod(Class<?> clazz, Method method) throws Throwable {
        try {
            return clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
        } catch (NoSuchMethodException e) {
            return null;
        }
    }

}

Note that this class:

  • extends MyClass, to inherit a default implementation (any other would do)
  • implements Invocationhandler, to allow the proxy to do reflection
  • optionally implement MyInterface (to satisfy the decorator pattern)

This solution allows you to override special methods, but to delegate all others. This will even work with sub classes of Wrapper class.

Note that the method findMethod does not yet capture the special cases.

这篇关于自动委托java类的所有方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆