代理概念
- 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。
- 代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。
静态代理与动态代理
- 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完成的。