动态代理
代理的概念
为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。
动态代理
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。
在java的动态代理API中,有两个重要的类和接口,一个是Proxy(Class)、另一个则是 InvocationHandler(Interface),这一个类和接口是实现我们动态代理所必须用到的
动态代理设计模式
![GWY96GFG]QC)IP45~}6__2.png
1、被代理类+增强=生成新的类(java)
2、编译新的类(class)
3、加载新的类
4、创建代理对象$Proxy12 (12是随机数)
Proxy(Class)(一般我们用最后一种方法)
Proxy是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
Proxy 的静态方法
static InvocationHandler getInvocationHandler(Object proxy)
该方法用于获取指定代理对象所关联的调用处理器
static Class getProxyClass(ClassLoader loader, Class[] interfaces)
该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
static boolean isProxyClass(Class cl)
该方法用于判断指定类对象是否是一个动态代理类
static Object newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h)
loader 指定代理类的ClassLoader加载器
interfaces 指定代理类要实现的接口
h: 表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
InvocationHandler(Interface)
InvocationHandler是负责连接代理类和委托类的中间类必须实现的接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。
InvocationHandler 的核心方法
Object invoke(Object proxy, Method method, Object[] args)
proxy 该参数为代理类的实例
method 被调用的方法对象
args 调用method对象的方法参数
该方法也是InvocationHandler接口所定义的唯一的一个方法,该方法负责集中处理动态代理类上的所有方法的调用。调用处理器根据这三个参数进行预处理或分派到委托类实例上执行。
动态代理的优点和缺点
优点
接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理
缺点
它始终无法摆脱仅支持 interface 代理的桎梏,它们已经注定有一个共同的父类叫 Proxy。Java 的继承机制注定了这些动态代理类们无法实现对 class 的动态代理,原因是多继承在 Java 中本质上就行不通。
举例
public interface IDrink {
public default void drink(){
System.out.println("喝咖啡");
}
}
public class Coffee implements IDrink{
public void drink(){
System.out.println("喝咖啡");
}
}
public class MilkHandler implements InvocationHandler{
Object obj=null;
public MilkHandler(Object obj){
this.obj=obj;
}
//proxy:被代理对象 method:需要被增强的方法 args:方法的参数
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("加牛奶");
method.invoke(obj, args);//通过反射调用加牛奶的方法
return null;
}
}
public class Test {
public static void main(String[] args) {
Coffee c=new Coffee();//实现IDrink接口
MilkHandler h=new MilkHandler(c);
IDrink d=(IDrink)Proxy.newProxyInstance(c.getClass().getClassLoader(), c.getClass().getInterfaces(), h);//实现了IDrink接口
d.drink();
}
}