Automatically delegating all methods of a java cla

2019-01-21 23:34发布

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).

8条回答
你好瞎i
2楼-- · 2019-01-22 00:16

Let me redefine the problem for a specific case. I want to override the close method of ResultSet interface in jdbc. My aim is to close the preparedstatement in close method of result set. I could not access to the Class (DelegatingResultSet) that implements in ResultSet interface. There are a lot of methods in ResultSet interface and overriding them one by one and calling the corresponding method from the ResultSet object is one solution. For a dynamic solution I used Dynamic ProxyClasses (https://docs.oracle.com/javase/1.5.0/docs/guide/reflection/proxy.html).

    // New ResultSet implementation
    public class MyResultSet implements InvocationHandler {
        ResultSet rs;
        PreparedStatement ps;
        private Method closeMethod;

        public MyResultSet(ResultSet rs, PreparedStatement ps) {
            super();
            this.rs = rs;
            this.ps = ps;
            try {
                closeMethod = ResultSet.class.getMethod("close",null);
            } catch (NoSuchMethodException | SecurityException e) {
                e.printStackTrace();
            }
        }

        public void close() {
            try {
                rs.close();
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }

        public static Object newInstance(ResultSet rs, PreparedStatement ps) {
            return java.lang.reflect.Proxy.newProxyInstance(rs.getClass().getClassLoader(), rs.getClass().getInterfaces(),
                    new MyResultSet(rs,ps));
        }

        public Object invoke(Object proxy, Method m, Object[] args) 
throws Throwable {
            Object result = null;
            try {
                Class declaringClass = m.getDeclaringClass();

                if (m.getName().compareTo("close")==0) {
                        close();
                } else {
                    result = m.invoke(rs, args);
                }
            } catch (InvocationTargetException e) {
                throw e.getTargetException();
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());

            } finally {
            }
            return result;
        }
    }

// How to call it:

ResultSet prs = (ResultSet) MyResultSet.newInstance(rs,ps);
查看更多
老娘就宠你
3楼-- · 2019-01-22 00:18

Check the @Delegation annotation from Lombok framework: https://projectlombok.org/features/Delegate.html

查看更多
登录 后发表回答