java动态代理(知识点清单)
概述
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架。
相关的类和接口
- java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
- java.lang.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。
Proxy提供的静态方法:
// 方法 1: 该方法用于获取指定代理对象所关联的调用处理器
static InvocationHandler getInvocationHandler(Object proxy)
// 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
static Class getProxyClass(ClassLoader loader, Class[] interfaces)
// 方法 3:该方法用于判断指定类对象是否是一个动态代理类
static boolean isProxyClass(Class cl)
// 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
static Object newProxyInstance(ClassLoader loader, Class[] interfaces,
InvocationHandler h)
基本实现步骤
- 实现InvocaHandler接口创建调用处理器
(static InvocationHandler getInvocationHandler(Object proxy)) - 创建动态代理类
(static Class getProxyClass(ClassLoader loader, Class[] interfaces)) - 通过反射机制获得动态代理类的构造函数对象
- 通过拿到的构造函数对象创建动态代理类实例,传入参数为调用处理器对象
写一个Real类,代表需要被代理的批发商,然后用代理对象去卖出单品。
package cn.sunzoom.ProxyDemo;
public class Real implements proxy_object{
@Override
public String say() {
String str = "我是批发商,我搞批发!!";
return str;
}
}
代码一:
package cn.sunzoom.ProxyDemo;
import java.lang.reflect.*;
public class ProxyDemo1 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//1.通过实现 InvocationHandler 接口创建自己的调用处理器;
InvocationHandler IH = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("say")) {
String str = "我是代理商,我在批发商进货,然后售出单件!!";
return str;
}
return method.invoke(proxy,args);
}
};
//2.通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
Class clazz = Proxy.getProxyClass(Real.class.getClassLoader(),Real.class.getInterfaces());
//3.通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
Constructor constructor = clazz.getConstructor(IH.getClass().getInterfaces());
//4.通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
proxy_object theproxy = (proxy_object) constructor.newInstance(IH);
String say = theproxy.say();
System.out.println(say);
}
}
结果:
代码二:简化(写法二运用
static Object newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h)
和 static InvocationHandler getInvocationHandler(Object proxy) ):
package cn.sunzoom.ProxyDemo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyDemo2 {
public static void main(String[] args){
proxy_object proxy = (proxy_object) Proxy.newProxyInstance(Real.class.getClassLoader(), Real.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("say")){
String str = "我是批发商的代理商,顾客不需要多,所以我只售出单品的!";
return str;
}
return method.invoke(proxy,args);
}
});
String str = proxy.say();
System.out.println(str);
}
}
结果: