一、动态代理机制
- 通过实现 InvocationHandler 接口创建自己的调用处理器;
- 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
- 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
- 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
二、代码示例
1.HelloService
接口。
public interface HelloService {
void sayHello();
}
2.HelloServiceImpl
实现类。
public class HelloServiceImpl implements HelloService{
@Override
public void sayHello() {
System.out.println("hello proxy");
}
}
3.HelloInvocationHandler
代理对象生成类,需继承InvocationHandler
接口。
public class HelloInvocationHandler implements InvocationHandler {
private Object target;
HelloInvocationHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("25661");
Object result = method.invoke(target, args);
return result;
}
}
4.ProxyTest
测试类。
public class ProxyTest {
public static void main(String[] args) {
HelloService hello = new HelloServiceImpl();
HelloInvocationHandler handler = new HelloInvocationHandler(hello);
HelloService proxy = (HelloService)Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), handler);
proxy.sayHello();
}
}
三、Proxy.newProxyInstance方法解析
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
}
//查找或生成指定的代理类。
//如果代理类由给定加载器定义实现
//给定的接口存在,这将返回缓存的副本;
//否则,它将通过ProxyClassFactory创建代理类
Class<?> cl = getProxyClass0(loader, interfaces);
//用指定的调用处理程序调用它的构造函数。
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//获得代理对象的构造函数
final Constructor<?> cons = cl.getConstructor(constructorParams);
//下面这块个人觉得是对新的代理对象进行校验
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
//通过反射获得代理对象
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
四、总结
一个典型的动态代理创建对象过程可分为以下四个步骤:
- 通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(…);
- 通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…}); - 通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class}); - 通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler))。
JDK的一个缺陷是始终无法摆脱仅支持interface代理的桎梏,因为它的设计注定了这个遗憾,Java的继承机制注定了这些动态代理类们无法实现对class的动态代理,原因是Java不支持多继承。