Java代理机制

代理概念

  • 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。
  • 代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。

静态代理与动态代理

  • interface接口有没有可能不编写实现类,直接在运行期创建某个interface的实例呢?这是可能的,因为Java标准库提供了一种动态代理(Dynamic Proxy)的机制:可以在运行期动态创建某个interface的实例。
  • 所谓动态代理,是和静态相对应的。

静态代理实例: 这种方式就是我们通常编写代码的方式。
定义接口

public interface Hello {
    void morning(String name);
}

编写实现类

public class HelloWorld implements Hello {
    public void morning(String name) {
        System.out.println("Good morning, " + name);
    }
}

创建实例,转型为接口并调用:

Hello hello = new HelloWorld();
hello.morning("Bob");

动态代理实例: 没有实现类、在运行期动态创建接口对象的方式,

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Main {
    public static void main(String[] args) {
    	//1. 实现方法
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (method.getName().equals("morning")) {
                //实现接口的方法的位置
                    System.out.println("Good morning, " + args[0]);
                }
                return null;
            }
        };
        
        //2. 创建接口的实例
        Hello hello = (Hello) Proxy.newProxyInstance(
            Hello.class.getClassLoader(), // 传入ClassLoader
            new Class[] { Hello.class }, // 传入要实现的接口
            handler); // 传入处理调用方法的InvocationHandler
        
        //3. 调用接口方法
        hello.morning("Bob");
    }
}

interface Hello {
    void morning(String name);
}

运行结果:
Good morning, Bob

总结

其实就是JVM帮我们自动编写了一个实现类(不需要源码,可以直接生成字节码),并不存在可以直接实例化接口的黑魔法。动态代理是通过Proxy创建代理对象,然后将接口方法“代理”给InvocationHandler完成的。


版权声明:本文为m0_46638350原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。