1

最近与代理对象一起工作,我遇到了困难的问题......我想分享它并听取你的意见......也许是一个解决方案......如果问题被证明是有效的。

使用动态代理,想法是将工作委托给另一个class实现InvocationHandler interface.真实或其他代理)使用反射。你必须有一个interfacethat a concrete class,我们喜欢代理它的对象,实现。所以我们使用界面。

我认为这件事是因为代理对象只有第一个调用的方法被拦截......这意味着:如果在对象的方法内部concrete(类是具体的对象,而不是接口)调用其他实例方法,这些方法将由concrete对象直接调用,而不是通过代理(在此之前不再考虑调用处理程序)。我知道“动态代理”的类被认为是 的子类interface,但不是该类的子concrete类。所以在concrete类内部,“this”关键字不能引用代理对象,只要代理对象类不是子类型of concrete..,实际上是“动态代理”的“兄弟”,concrete因为concrete和类interface.

请看一下下面的代码场景,我发现了一个相当有问题的情况。

public class Example
{

    static interface OutputerInterface
    {
        String getText();

        void out();

        void setText(String data);

    }

    static class Outputer implements OutputerInterface {

        private String txt;

        public Outputer()
        {
            this.txt = null;
        }

        @Override
        public String getText()
        {
            return txt;
        }

        @Override
        public void setText(String data)
        {
            this.txt = data;
        }

        @Override
        public void out () {
            String text = this.getText();
            System.out.println (text);
        }
    }

    static class OutputerInvocationHandler implements InvocationHandler {
        private OutputerInterface outputer;

        public OutputerInvocationHandler(OutputerInterface concreteEntity)
        {
            this.outputer = concreteEntity;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
        {
            String methodName = method.getName();
            System.out.println("Intercepted " + methodName);
            if (methodName.equals("getText"))
            {
                if (this.outputer.getText() == null) { // only if not setted
                    this.outputer.setText("Hi, i am outputer");
                }
            }

            return method.invoke(outputer, args);
        }
    }

    static OutputerInterface proxify (OutputerInterface entity) {
        return (OutputerInterface) Proxy.newProxyInstance(
                Outputer.class.getClassLoader(),
                Outputer.class.getInterfaces(), 
                new OutputerInvocationHandler(entity));
    }


    public static void main(String[] args)
    {
        OutputerInterface outputer;

        outputer = proxify (new Outputer());
        String text = outputer.getText(); 
        System.out.println (text); // this works!

        outputer = proxify (new Outputer());
        outputer.out(); // this doesn´t works
    }
}

有没有办法确保无论是否直接从代理调用 getText() 都会被拦截。谢谢!问候!胜利者。

4

2 回答 2

1

您需要为具体类提供对InvocationHandler驱动它的引用,并在适当的地方使用该引用代替“this”(隐式或显式)。

或者你可以实现 InvocationHandler,具体的类,虽然很难看出这一点;-)

于 2013-07-30T01:03:06.730 回答
1

这是 Java 内置动态代理的一个限制:您只能实现多个接口,但不能扩展一个类。

在您的情况下,我想您正在尝试做的是扩展Outputer,不,您不能通过设计使用动态代理来做到这一点。您应该尝试使用运行时代码生成库,例如CGLib

于 2013-10-02T16:46:49.940 回答