Java学习-动态代理

版权声明:欢迎转载,请注明作者和出处 https://blog.csdn.net/baichoufei90/article/details/83305446

Java学习-动态代理

0x01 摘要

我们在看源码的时候,往往能发现很多实用动态代理的例子,本文将对其进行简要介绍。

0x02 概念

在不想直接暴露真实对象,且想再对象的方法前后增加逻辑时可以用代理。

代理类和被代理类实现共同接口,且代理类可以访问被代理类的实际对象,在其方法调用前后增加自定义的逻辑。

代理的好处就是隐藏了真实对象,且可加逻辑处理代码。这一切对客户端来说是无感知的。

0x03 被代理对象和接口

public interface Interface {
    void doSomething();
    void somethingElse(String arg);
}

class RealObject implements Interface {

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

    @Override
    public void somethingElse(String arg) {
        System.out.println("somethingElse " + arg);
    }
}

0x04 简陋的代理

代码如下:

class SimpleProxy implements Interface {
    private Interface proxy;

    public SimpleProxy(Interface proxy) {
        this.proxy = proxy;
    }

    @Override
    public void doSomething() {
        System.out.println("SimpleProxy doSomething.");
        proxy.doSomething();
    }

    @Override
    public void somethingElse(String arg) {
        System.out.println("SimpleProxy somethingElse " + arg);
        proxy.somethingElse(arg);
    }
}

0x05 InvocationHandler实现动态代理

动态代理代码示例如下:

class DynamicProxyHandler implements InvocationHandler {
    //要代理的原始对象
    private Object proxy;

    //传入被代理的对象
    public DynamicProxyHandler(Object proxy) {
        this.proxy = proxy;
    }
	/**
     * 在代理实例上处理方法调用并返回结果
     * @param proxy 被代理对象
     * @param method 被代理的方法
     * @param args 该方法的参数数组
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("method.getDeclaringClass() = "+ method.getDeclaringClass());
        // 这一步的作用是为了防止调用继承自Object的方法如 toString hashCode等
        // 也就是说,接口创建出的代理对象不仅有接口的方法,还有从Object类继承的方法
        if (method.getDeclaringClass()== Object.class) {
            return method.invoke(this, args);
        }
        System.out.println("*** proxy: " + proxy.getClass() +
                ". method: " + method + ". args: " + args);
        System.out.println("something you need do before invoking");
        if(args != null) {
            for(Object arg : args)
                System.out.println(" " + arg);
        }
        //调用方法
        Object result = method.invoke(this.proxy, args);
        System.out.println("something you need do after invoking");
        
        return result;
    }
}

0x06 测试代码

客户端调用测试代码如下:

 public static void main(String[] args) {
        Parent real = new RealObject();
        real.doSomething();
        real.somethingElse("bonobo");
        
        System.out.println("--------------------------Insert a Simple proxy and call again");
        consumer(new SimpleProxy(real));

        System.out.println("--------------------------Insert a dynamic proxy and call again");
        
        System.out.println(real.getClass().getInterfaces().length);
        System.out.println(new Class[]{ Interface.class }.length);

        /**
         * @param   loader the class loader to define the proxy class
         * @param   interfaces the list of interfaces for the proxy class to implement
         * @param   h the invocation handler to dispatch method invocations to
         * @return  a proxy instance with the specified invocation handler of a
         *          proxy class that is defined by the specified class loader
         *          and that implements the specified interfaces
         */
        Interface proxy = (Interface)Proxy.newProxyInstance(
                RealObject.class.getClassLoader(),
                new Class[]{ Interface.class },
                new DynamicProxyHandler(real));

        Interface proxy2 = (Interface)Proxy.newProxyInstance(
                real.getClass().getClassLoader(),
                real.getClass().getInterfaces(),
                new DynamicProxyHandler(real));

        consumer(proxy2);
    }

猜你喜欢

转载自blog.csdn.net/baichoufei90/article/details/83305446