简介
代理模式:使用代理类来增强目标类的功能。在代码结构上,代理对象持有目标对象,通过代理对象访问目标对象,这样可以在不改变目标对象的前提下增加额外的功能,如权限校验、缓存等
代理模式内部的角色:
- 目标类:实现业务功能
- 代理类:用户通过代理类来访问目标类
- 增强方法:代理类中要调用的方法,就是通过它来为目标类添加功能
- 目标接口:代理类和目标类都需要实现目标接口,在有些情况下目标接口是不需要的
代理模式的分类:依据代理类的创建方式,代理模式分为静态代理和动态代理
spring、mybatis等常见框架中大量使用到了动态代理,例如spring的aop,通过动态代理来为目标类增加功能
代理模式的分类
静态代理
静态代理:用户手动编写代理类,在编译时,目标类、代理类已经全部确定
案例:目标类实现售卖功能,代理类中收取服务费
第一步:目标接口
public interface SellTickets {
void sell();
}
第二步:目标类
public class TrainStation implements SellTickets {
@Override
public void sell() {
System.out.println("火车站卖票");
}
}
第三步:代理类
public class ProxyPoint implements SellTickets {
private final TrainStation trainStation; // 代理类持有目标类的实例
public ProxyPoint() { }
public ProxyPoint(TrainStation trainStation) {
this.trainStation = trainStation;
}
@Override
public void sell() {
System.out.println("代理点收取服务费");
trainStation.sell();
}
}
测试:
public class StaticProxyClient {
public static void main(String[] args) {
// 创建代理类时,传入目标类的实例,通过代理类来访问目标类
ProxyPoint proxyPoint = new ProxyPoint(new TrainStation());
proxyPoint.sell();
}
}
动态代理
动态代理:在程序运行时,基于字节码技术,动态地创建代理类。和静态代理不同的地方在于,静态代理时代理类需要用户手动编写,是编译时生成,动态代理时代理类由程序来自动创建,是运行时生成,用户只需要指定代理类要执行的增强方法和目标类。
用户可以使用jdk原生的方式来创建动态代理类,也可以使用第三方库,例如cglib,提供的方式来创建代理类
基于jdk的动态代理技术
jdk原生的动态代理技术
案例:
第一步:目标接口、目标类,和之前一样
第二步:创建代理类的工厂。代理类是运行时创建的,这里指定代理类的创建方式,程序运行时,使用用户指定的方式,在内存中动态地创建一个类,就是动态代理
public class JdkProxyFactory {
// 创建火车站的代理类
public static Object getTrainStationProxyObj(TrainStation trainStation) {
return dynamicProxy(trainStation,
// 代理类中要执行的方法
(InvocationHandler) (proxy, method, args) -> {
// 这里代理类只拦截指定方法
if (method.getName().equals("sell")) {
System.out.println("收取代理费");
}
return method.invoke(trainStation, args); // 执行目标类中的方法
});
}
// 传入目标对象和调用处理器
private static <T> Object dynamicProxy(T target, InvocationHandler h) {
return Proxy.newProxyInstance(target.getClass().getClassLoader() // 代理类的类加载器
, target.getClass().getInterfaces() // 代理类要实现的接口
, h);
}
}
测试:
public class JdkProxyClient {
public static void main(String[] args) {
TrainStation targetObj = new TrainStation();
SellTickets proxyObj = (SellTickets) JdkProxyFactory.getTrainStationProxyObj(targetObj);
proxyObj.sell();
}
}
基于cglib的动态代理技术
基于cglib的动态代理技术:由于jdk提供的动态代理技术要求目标类必须要实现目标接口,所以它的使用范围比较小,cglib提供了一种动态代理技术,它是基于继承关系,目标类不需要实现接口。
案例:
第一步:添加依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
第二步:目标类,可以没有目标接口,因为cglib提供的动态代理技术,是基于继承关系来进行代理
第三步:创建代理类的工厂
public class CgProxyFactory {
public static TrainStation getProxyObj(TrainStation trainStation) {
Enhancer enhancer = new Enhancer();
// 代理类的父类
enhancer.setSuperclass(TrainStation.class);
// 代理类中要执行的方法
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method
, Object[] objects, MethodProxy methodProxy)
throws Throwable {
if (method.getName().equals("sell")) {
System.out.println("收取代理费");
}
return method.invoke(trainStation, objects);
}
});
return (TrainStation) enhancer.create();
}
}
测试:
public class CgProxyClient {
public static void main(String[] args) {
TrainStation targetObj = new TrainStation();
TrainStation proxyObj = CgProxyFactory.getProxyObj(targetObj);
proxyObj.sell();
}
}
原理解析
查看创建出的代理类
使用arthas,查看动态创建出的代理类。具体方法,在程序中打印出代理类的类名,然后程序休眠,使用arthas连接程序,在arthas中使用jad查看类的字节码
案例:
public class CgProxyClient {
public static void main(String[] args) {
TrainStation targetObj = new TrainStation();
TrainStation proxyObj = CgProxyFactory.getProxyObj(targetObj);
proxyObj.sell();
// 代理类的类名
// class org.wyj.proxy.cg_proxy.TrainStation$$EnhancerByCGLIB$$37abd3d3
System.out.println("proxyObj.getClass() = " + proxyObj.getClass());
// 程序休眠,方便arthus连接
try {
Thread.sleep(10 * 1000 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
使用arthas连接到当前程序,执行命令,jad ${类的全限定名}
,查看动态生成的代理类
jdk生成的代理类
案例:这里直接展示创建结果,下面就是之前案例中jdk在内存中动态创建的代理类的字节码,
package com.sun.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import org.wyj.proxy.jdk_proxy.SellTickets;
public final class $Proxy0
extends Proxy
implements SellTickets {
private static Method m1;
private static Method m4;
private static Method m2;
private static Method m3;
private static Method m0;
// 构造方法,调用这个方法来创建代理类的实例
public $Proxy0(InvocationHandler invocationHandler) {
super(invocationHandler);
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m4 = Class.forName("org.wyj.proxy.jdk_proxy.SellTickets").getMethod("show", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m3 = Class.forName("org.wyj.proxy.jdk_proxy.SellTickets").getMethod("sell", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
}
catch (NoSuchMethodException noSuchMethodException) {
throw new NoSuchMethodError(noSuchMethodException.getMessage());
}
catch (ClassNotFoundException classNotFoundException) {
throw new NoClassDefFoundError(classNotFoundException.getMessage());
}
}
public final boolean equals(Object object) {
try {
return (Boolean)this.h.invoke(this, m1, new Object[]{object});
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final String toString() {
try {
return (String)this.h.invoke(this, m2, null);
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final int hashCode() {
try {
return (Integer)this.h.invoke(this, m0, null);
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final void sell() {
try {
this.h.invoke(this, m3, null);
return;
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}
总结:使用jdk创建出的代理类,默认是Proxy的子类,并且实现了用户指定的接口
cglib创建的代理类
案例:之前案例中创建出的代理类
package org.wyj.proxy.cg_proxy;
import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.wyj.proxy.cg_proxy.TrainStation;
public class TrainStation$$EnhancerByCGLIB$$c8c06447
extends TrainStation
implements Factory {
private boolean CGLIB$BOUND;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static final Method CGLIB$sell$0$Method;
private static final MethodProxy CGLIB$sell$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$finalize$1$Method;
private static final MethodProxy CGLIB$finalize$1$Proxy;
private static final Method CGLIB$equals$2$Method;
private static final MethodProxy CGLIB$equals$2$Proxy;
private static final Method CGLIB$toString$3$Method;
private static final MethodProxy CGLIB$toString$3$Proxy;
private static final Method CGLIB$hashCode$4$Method;
private static final MethodProxy CGLIB$hashCode$4$Proxy;
private static final Method CGLIB$clone$5$Method;
private static final MethodProxy CGLIB$clone$5$Proxy;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class<?> clazz = Class.forName("org.wyj.proxy.cg_proxy.TrainStation$$EnhancerByCGLIB$$c8c06447");
Class<?> clazz2 = Class.forName("java.lang.Object");
Method[] methodArray = ReflectUtils.findMethods(new String[]{"finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, clazz2.getDeclaredMethods());
CGLIB$finalize$1$Method = methodArray[0];
CGLIB$finalize$1$Proxy = MethodProxy.create(clazz2, clazz, "()V", "finalize", "CGLIB$finalize$1");
CGLIB$equals$2$Method = methodArray[1];
CGLIB$equals$2$Proxy = MethodProxy.create(clazz2, clazz, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
CGLIB$toString$3$Method = methodArray[2];
CGLIB$toString$3$Proxy = MethodProxy.create(clazz2, clazz, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
CGLIB$hashCode$4$Method = methodArray[3];
CGLIB$hashCode$4$Proxy = MethodProxy.create(clazz2, clazz, "()I", "hashCode", "CGLIB$hashCode$4");
CGLIB$clone$5$Method = methodArray[4];
CGLIB$clone$5$Proxy = MethodProxy.create(clazz2, clazz, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
clazz2 = Class.forName("org.wyj.proxy.cg_proxy.TrainStation");
CGLIB$sell$0$Method = ReflectUtils.findMethods(new String[]{"sell", "()V"}, clazz2.getDeclaredMethods())[0];
CGLIB$sell$0$Proxy = MethodProxy.create(clazz2, clazz, "()V", "sell", "CGLIB$sell$0");
}
final void CGLIB$sell$0() {
super.sell();
}
// 重写目标类中的方法,在方法中调用用户设置的拦截器
public final void sell() {
MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
if (methodInterceptor == null) {
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$BIND_CALLBACKS(this);
methodInterceptor = this.CGLIB$CALLBACK_0;
}
if (methodInterceptor != null) {
Object object = methodInterceptor.intercept(this, CGLIB$sell$0$Method, CGLIB$emptyArgs, CGLIB$sell$0$Proxy);
return;
}
super.sell();
}
final void CGLIB$finalize$1() throws Throwable {
super.finalize();
}
// 重写Object类中的方法
protected final void finalize() throws Throwable {
MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
if (methodInterceptor == null) {
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$BIND_CALLBACKS(this);
methodInterceptor = this.CGLIB$CALLBACK_0;
}
if (methodInterceptor != null) {
Object object = methodInterceptor.intercept(this, CGLIB$finalize$1$Method, CGLIB$emptyArgs, CGLIB$finalize$1$Proxy);
return;
}
super.finalize();
}
final boolean CGLIB$equals$2(Object object) {
return super.equals(object);
}
public final boolean equals(Object object) {
MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
if (methodInterceptor == null) {
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$BIND_CALLBACKS(this);
methodInterceptor = this.CGLIB$CALLBACK_0;
}
if (methodInterceptor != null) {
Object object2 = methodInterceptor.intercept(this, CGLIB$equals$2$Method, new Object[]{object}, CGLIB$equals$2$Proxy);
return object2 == null ? false : (Boolean)object2;
}
return super.equals(object);
}
final String CGLIB$toString$3() {
return super.toString();
}
public final String toString() {
MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
if (methodInterceptor == null) {
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$BIND_CALLBACKS(this);
methodInterceptor = this.CGLIB$CALLBACK_0;
}
if (methodInterceptor != null) {
return (String)methodInterceptor.intercept(this, CGLIB$toString$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy);
}
return super.toString();
}
final int CGLIB$hashCode$4() {
return super.hashCode();
}
public final int hashCode() {
MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
if (methodInterceptor == null) {
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$BIND_CALLBACKS(this);
methodInterceptor = this.CGLIB$CALLBACK_0;
}
if (methodInterceptor != null) {
Object object = methodInterceptor.intercept(this, CGLIB$hashCode$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);
return object == null ? 0 : ((Number)object).intValue();
}
return super.hashCode();
}
final Object CGLIB$clone$5() throws CloneNotSupportedException {
return super.clone();
}
protected final Object clone() throws CloneNotSupportedException {
MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
if (methodInterceptor == null) {
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$BIND_CALLBACKS(this);
methodInterceptor = this.CGLIB$CALLBACK_0;
}
if (methodInterceptor != null) {
return methodInterceptor.intercept(this, CGLIB$clone$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy);
}
return super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature signature) {
String string = ((Object)signature).toString();
switch (string.hashCode()) {
case -1574182249: {
if (!string.equals("finalize()V")) break;
return CGLIB$finalize$1$Proxy;
}
case -508378822: {
if (!string.equals("clone()Ljava/lang/Object;")) break;
return CGLIB$clone$5$Proxy;
}
case 1826985398: {
if (!string.equals("equals(Ljava/lang/Object;)Z")) break;
return CGLIB$equals$2$Proxy;
}
case 1913648695: {
if (!string.equals("toString()Ljava/lang/String;")) break;
return CGLIB$toString$3$Proxy;
}
case 1978249955: {
if (!string.equals("sell()V")) break;
return CGLIB$sell$0$Proxy;
}
case 1984935277: {
if (!string.equals("hashCode()I")) break;
return CGLIB$hashCode$4$Proxy;
}
}
return null;
}
public TrainStation$$EnhancerByCGLIB$$c8c06447() {
TrainStation$$EnhancerByCGLIB$$c8c06447 trainStation$$EnhancerByCGLIB$$c8c06447 = this;
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$BIND_CALLBACKS(trainStation$$EnhancerByCGLIB$$c8c06447);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] callbackArray) {
CGLIB$THREAD_CALLBACKS.set(callbackArray);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] callbackArray) {
CGLIB$STATIC_CALLBACKS = callbackArray;
}
private static final void CGLIB$BIND_CALLBACKS(Object object) {
block2: {
Object object2;
block3: {
TrainStation$$EnhancerByCGLIB$$c8c06447 trainStation$$EnhancerByCGLIB$$c8c06447 = (TrainStation$$EnhancerByCGLIB$$c8c06447)object;
if (trainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$BOUND) break block2;
trainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$BOUND = true;
object2 = CGLIB$THREAD_CALLBACKS.get();
if (object2 != null) break block3;
object2 = CGLIB$STATIC_CALLBACKS;
if (CGLIB$STATIC_CALLBACKS == null) break block2;
}
trainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])object2)[0];
}
}
public Object newInstance(Callback[] callbackArray) {
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$SET_THREAD_CALLBACKS(callbackArray);
TrainStation$$EnhancerByCGLIB$$c8c06447 trainStation$$EnhancerByCGLIB$$c8c06447 = new TrainStation$$EnhancerByCGLIB$$c8c06447();
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$SET_THREAD_CALLBACKS(null);
return trainStation$$EnhancerByCGLIB$$c8c06447;
}
public Object newInstance(Callback callback) {
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$SET_THREAD_CALLBACKS(new Callback[]{callback});
TrainStation$$EnhancerByCGLIB$$c8c06447 trainStation$$EnhancerByCGLIB$$c8c06447 = new TrainStation$$EnhancerByCGLIB$$c8c06447();
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$SET_THREAD_CALLBACKS(null);
return trainStation$$EnhancerByCGLIB$$c8c06447;
}
public Object newInstance(Class[] classArray, Object[] objectArray, Callback[] callbackArray) {
TrainStation$$EnhancerByCGLIB$$c8c06447 trainStation$$EnhancerByCGLIB$$c8c06447;
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$SET_THREAD_CALLBACKS(callbackArray);
Class[] classArray2 = classArray;
switch (classArray.length) {
case 0: {
trainStation$$EnhancerByCGLIB$$c8c06447 = new TrainStation$$EnhancerByCGLIB$$c8c06447();
break;
}
default: {
throw new IllegalArgumentException("Constructor not found");
}
}
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$SET_THREAD_CALLBACKS(null);
return trainStation$$EnhancerByCGLIB$$c8c06447;
}
public Callback getCallback(int n) {
MethodInterceptor methodInterceptor;
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$BIND_CALLBACKS(this);
switch (n) {
case 0: {
methodInterceptor = this.CGLIB$CALLBACK_0;
break;
}
default: {
methodInterceptor = null;
}
}
return methodInterceptor;
}
public void setCallback(int n, Callback callback) {
switch (n) {
case 0: {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)callback;
break;
}
}
}
public Callback[] getCallbacks() {
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$BIND_CALLBACKS(this);
TrainStation$$EnhancerByCGLIB$$c8c06447 trainStation$$EnhancerByCGLIB$$c8c06447 = this;
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public void setCallbacks(Callback[] callbackArray) {
Callback[] callbackArray2 = callbackArray;
TrainStation$$EnhancerByCGLIB$$c8c06447 trainStation$$EnhancerByCGLIB$$c8c06447 = this;
this.CGLIB$CALLBACK_0 = (MethodInterceptor)callbackArray[0];
}
static {
TrainStation$$EnhancerByCGLIB$$c8c06447.CGLIB$STATICHOOK1();
}
}
总结:代理类是目标类的子类,会重写它从父类中继承来的方法,包括Object类中的方法。在重写的方法中,调用拦截器来完成任务,拦截器是用户提供的,指定了增强方法和目标对象的执行方式。
代理类失效的情况
基于jdk创建的代理类,代理类只可以代理目标接口中的方法,因为代理类只会实现目标接口中的方法。
基于cglib创建的代理类,代理类只可以代理目标类中可以被继承的方法,因为代理类只会重写可以被继承的方法,如果方法无法被继承,在执行时,会直接调用目标类中的方法,从而导致代理类无法代理。
代理类的执行效率
测试方式:执行100万次,每一次都创建一个代理类,然后调用一次代理类中的方法,方法中什么都不做,这里只关心方法的调用速度
public class JdkProxyClient {
public static void main(String[] args) {
TrainStation targetObj = new TrainStation();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
SellTickets proxyObj = (SellTickets) JdkProxyFactory.getTrainStationProxyObj(targetObj);
proxyObj.sell();
}
long executeTime = System.currentTimeMillis() - startTime;
System.out.println("执行时间:" + executeTime + "ms");
}
}
得出的结论:
测试方式 | 基于jdk创建的代理类 | 基于cglib创建的代理类 |
---|---|---|
创建100万个代理类,每个代理类都执行一次 | 112ms | 1130ms |
创建1个代理类,每个代理类都执行100万次 | 29ms | 34ms |
可以看出,执行速度差不多,但是jdk创建代理类的速度更快,因为jdk生成的字节码更少
源码解析
jdk创建代理的方式
API总结:
Proxy:public class Proxy implements java.io.Serializable
:创建代理类的工具类,提供了静态方法,用于创建动态代理类和动态代理对象,它也是所有动态代理类的父类。
public class Proxy implements java.io.Serializable {
private static final long serialVersionUID = -2222568056686623797L;
// 构造器的参数,动态生成的代理类,会生成一个构造方法,这里就是构造方法的参数
/** parameter types of a proxy class constructor */
private static final Class<?>[] constructorParams =
{ InvocationHandler.class };
// 创建代理类并且获取代理对象的方法,用户需要提供三个参数,用于加载代理类的类加载器、
// 代理类需要实现的接口、代理类中需要执行的增强方法。
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
// 在这一步会生成代理类
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
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:public interface InvocationHandler
:调用处理器,在调用处理器中调用增强方法和目标对象。每个代理实例有一个相关联的调用处理器,代理对象内部实际上是通过调用处理器来工作的
public interface InvocationHandler {
// 参数proxy是代理对象
// 参数method是目标类中的方法的Method对象,调用哪个方法,这儿就是哪个方法的实例
// 参数args是method方法的参数
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
这里对源码的介绍很浅,重点是要理解创建代理类需要提供哪些参数、代理类的执行机制。