代理模式
为其他对象提供一个代理以控制对某个对象的访问。代理类主要负责为委托了(真实对象)预处理消息、过滤消息、传递消息给委托类,代理类不现实具体服务,而是利用委托类来完成服务,并将执行结果封装处理。
其实就是代理类为被代理类预处理消息、过滤消息并在此之后将消息转发给被代理类,之后还能进行消息的后置处理。代理类和被代理类通常会存在关联关系(即上面提到的持有的被带离对象的引用),代理类本身不实现服务,而是通过调用被代理类中的方法来提供服务。
静态代理
创建一个接口,然后创建被代理的类实现该接口并且实现该接口中的抽象方法。之后再创建一个代理类,同时使其也实现这个接口。在代理类中持有一个被代理对象的引用,而后在代理类方法中调用该对象的方法。
接口:
public interface Fangdong {
/**
* 出租
*/
void rent(BigDecimal money);
}
被代理类:
public class ZhongJie implements Fangdong {
@Override
public void rent(BigDecimal money) {
System.out.println("我在帮房东卖房,此房" + money +"万元");
}
}
代理类:
public class ZhongJieProxy implements Fangdong {
private Fangdong fangdong = new ZhongJie();
@Override
public void rent(BigDecimal money) {
System.out.println("卖房前");
fangdong.rent(money);
System.out.println("卖房后");
}
public static void main(String[] args) {
//代理类调用
ZhongJieProxy proxy = new ZhongJieProxy();
//被代理类ZhongJie被传递给了代理类ZhongJieProxy
//代理类在执行具体方法时通过所持用的被代理类完成调用。
proxy.rent(new BigDecimal(300));
//卖房前
//我在帮房东卖房,此房300万元
//卖房后
}
}
使用静态代理很容易就完成了对一个类的代理操作。但是静态代理的缺点也暴露了出来:由于代理只能为一个类服务,如果需要代理的类很多,那么就需要编写大量的代理类,比较繁琐。因此,我们需要采用动态代理,来避免这个繁琐的问题。
动态代理
动态代理可以为多个类服务,运行期动态创建被代理类的实例。
动态代理有2种方式:
- JDK动态代理:代理类实现 InvocationHandler接口
- Cglib动态代理: 必须导入 cglib jar包,代理类实现MethodInterceptor接口。
一. JDK动态代理
利用反射机制在运行时创建代理类。我们构建一个proxy类来实现InvocationHandler接口。
//代理类必须实现InvocationHandler接口
public class JdkProxy implements InvocationHandler {
//被代理类(目标类)
private Object target;
JdkProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before invoke method " + method.getName());
//目标类 执行方法
method.invoke(target, args);
System.out.println("after invoke method " + method.getName());
return null;
}
public static void main(String[] args) {
//此处为了保存动态代理生成Class文件
System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
Fangdong fangdong = new ZhongJie();
Class<?>[] interfaces = fangdong.getClass().getInterfaces();
ClassLoader classLoader = fangdong.getClass().getClassLoader();
InvocationHandler invocationHandler = new JdkProxy(fangdong);
CarFactory carFactory = new BenzFactory();
JdkProxy carProxy = new JdkProxy(carFactory);
//可以代理多个类
CarFactory car = (CarFactory) Proxy.newProxyInstance(carFactory.getClass().getClassLoader(), carFactory.getClass().getInterfaces(), carProxy);
Fangdong fangdong1 = (Fangdong) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
fangdong1.rent(BigDecimal.valueOf(300));
car.produce("Benz");
}
}
打印输出:
before invoke method rent
我在帮房东卖房,此房300万元
after invoke method rent
before invoke method produce
正在制造品牌车 Benz
after invoke method produce
JDK动态代理底层实现
jdk动态代理具体步骤:
1. 通过实现 InvocationHandler 接口创建自己的调用处理器;
2. 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
3. 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
4. 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
既然生成代理对象是用的Proxy类的静态方newProxyInstance,那么我们就去它的源码里看一下它到底都做了些什么?
/**
* 代理类缓存
* subKeyFactory -> new KeyFactory()
* valueFactory -> new ProxyClassFactory()
*/
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
/**
* 返回指定接口的代理类实例,该接口将方法调用分派给指定的调用处理程序。
*
* <p>{@code Proxy.newProxyInstance} throws
* @param loader 代理类的类加载器
* @param interfaces 要实现的代理类的接口列表
* @param h 将方法调用分派到的调用处理程序
* @return 具有由指定的类加载器定义的代理类的指定调用处理程序并实现指定接口的代理实例。
*/
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
//InvocationHandler 不能为空
Objects.requireNonNull(h);
//数组的clone(深拷贝)
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* 查找或者生成指定的代理类
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* 调用构造器,构造器有目标类
*/
try {
if (sm != null) {
//检查新的代理对戏那个的权限
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//获取代理类的构造器
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
// //如果Class作用域为私有,通过 setAccessible 支持访问
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
//获取Proxy Class构造函数,创建Proxy代理实例。
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);
}
}
Class<?> cl = getProxyClass0(loader, intfs);方法
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
//接口个数不能超过2的32次方-1
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
//如果指定接口的代理类已经存在与缓存中,则不用新创建,直接从缓存中取即可;
//如果缓存中没有指定代理对象,则通过ProxyClassFactory来创建一个代理对象。
//key 类加载器,parameter 是接口
return proxyClassCache.get(loader, interfaces);
}
WeakCache.java
final class WeakCache<K, P, V> {
private final ReferenceQueue<K> refQueue
= new ReferenceQueue<>();
// the key type is Object for supporting null key
//缓存的底层实现, key为一级缓存, value为二级缓存。 为了支持null, map的key类型设置为Object
private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map
= new ConcurrentHashMap<>();
//reverseMap记录了所有代理类生成器是否可用, 这是为了实现缓存的过期机制
private final ConcurrentMap<Supplier<V>, Boolean> reverseMap
= new ConcurrentHashMap<>();
//生成二级缓存key的工厂, 这里传入的是KeyFactory
private final BiFunction<K, P, ?> subKeyFactory;
//生成二级缓存value的工厂, 这里传入的是ProxyClassFactory
private final BiFunction<K, P, V> valueFactory;
//初始化subKeyFactory 和 valueFactory
public WeakCache(BiFunction<K, P, ?> subKeyFactory,
BiFunction<K, P, V> valueFactory) {
this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
this.valueFactory = Objects.requireNonNull(valueFactory);
}
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);
//清除过期缓存
expungeStaleEntries();
//将key包装成CacheKey,并关联个应用队列
Object cacheKey = CacheKey.valueOf(key, refQueue);
// lazily install the 2nd level valuesMap for the particular cacheKey
//获取二级缓存
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
if (valuesMap == null) {
//以CAS方式放入, 如果不存在则放入,否则返回原先的值
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,
valuesMap = new ConcurrentHashMap<>());
//如果oldValuesMap有值, 说明放入失败
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
// create subKey and retrieve the possible Supplier<V> stored by that
// subKey from valuesMap
//使用subKeyFactory生成二级缓存key
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
//获取二级缓存value
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
while (true) {
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
// supplier有可能是一个后面代码生成的一个Factory,也肯是一个CacheValue(就是生成的代理类),
//因为他们都实现Supplier,所以都可以用get获取。
//判断是Factory 还是 CacheValue在get里面判断
V value = supplier.get();
if (value != null) {
return value;
}
}
// else no supplier in cache
// or a supplier that returned null (could be a cleared CacheValue
// or a Factory that wasn't successful in installing the CacheValue)
// lazily construct a Factory
if (factory == null) {
//新建一个Factory后面将会放入二级缓存的value里面
factory = new Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// successfully installed Factory
//说明已经成功放入
supplier = factory;
}
// else retry with winning supplier
//否则, 期间可能有其他线程修改了值, 那么需再次循环(此时可直接取出使用)
} else {
//期间有可能其他线程修改了supplier的值,这是需要替换
if (valuesMap.replace(subKey, supplier, factory)) {
// successfully replaced
// cleared CacheEntry / unsuccessful Factory
// with our Factory
supplier = factory;
} else {
// retry with current supplier
supplier = valuesMap.get(subKey);
}
}
}
}
}
ProxyClassFactory.java
利用ProxyClassFactory对象的apply方法,生成代理类。
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
*/
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
/*
* Verify that the Class object actually represents an
* interface.
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
*/
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
// if no non-public proxy interfaces, use com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/*
* 生成代理对象字节码
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
//native方法生成代理对象 将字节码转换成Class文件
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
/*
* A ClassFormatError here means that (barring bugs in the
* proxy class generation code) there was some other
* invalid aspect of the arguments supplied to the proxy
* class creation (such as virtual machine limitations
* exceeded).
*/
throw new IllegalArgumentException(e.toString());
}
}
}
ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags); 生成代理类的class字节文件。
public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
final byte[] var4 = var3.generateClassFile();
if (saveGeneratedFiles) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
try {
int var1 = var0.lastIndexOf(46);
Path var2;
if (var1 > 0) {
Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
Files.createDirectories(var3);
var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
} else {
var2 = Paths.get(var0 + ".class");
}
//写入字节码文件
Files.write(var2, var4, new OpenOption[0]);
return null;
} catch (IOException var4x) {
throw new InternalError("I/O exception saving generated file: " + var4x);
}
}
});
}
return var4;
}
Proxy.generateClassFile();方法的具体实现,生成class字节码
private byte[] generateClassFile() {
//第一步, 将所有的方法组装成ProxyMethod对象
//首先为代理类生成toString, hashCode, equals等代理方法
addProxyMethod(hashCodeMethod, Object.class);
addProxyMethod(equalsMethod, Object.class);
addProxyMethod(toStringMethod, Object.class);
//遍历每一个接口的每一个方法, 并且为其生成ProxyMethod对象
for (int i = 0; i < interfaces.length; i++) {
Method[] methods = interfaces[i].getMethods();
for (int j = 0; j < methods.length; j++) {
addProxyMethod(methods[j], interfaces[i]);
}
}
//对于具有相同签名的代理方法, 检验方法的返回值是否兼容
for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
checkReturnTypes(sigmethods);
}
//第二步, 组装要生成的class文件的所有的字段信息和方法信息
try {
//添加构造器方法
methods.add(generateConstructor());
//遍历缓存中的代理方法
for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
for (ProxyMethod pm : sigmethods) {
//添加代理类的静态字段, 例如:private static Method m1;
fields.add(new FieldInfo(pm.methodFieldName,
"Ljava/lang/reflect/Method;", ACC_PRIVATE | ACC_STATIC));
//添加代理类的代理方法
methods.add(pm.generateMethod());
}
}
//添加代理类的静态字段初始化方法
methods.add(generateStaticInitializer());
} catch (IOException e) {
throw new InternalError("unexpected I/O Exception");
}
//验证方法和字段集合不能大于65535
if (methods.size() > 65535) {
throw new IllegalArgumentException("method limit exceeded");
}
if (fields.size() > 65535) {
throw new IllegalArgumentException("field limit exceeded");
}
//第三步, 写入最终的class文件
//验证常量池中存在代理类的全限定名
cp.getClass(dotToSlash(className));
//验证常量池中存在代理类父类的全限定名, 父类名为:"java/lang/reflect/Proxy"
cp.getClass(superclassName);
//验证常量池存在代理类接口的全限定名
for (int i = 0; i < interfaces.length; i++) {
cp.getClass(dotToSlash(interfaces[i].getName()));
}
//接下来要开始写入文件了,设置常量池只读
cp.setReadOnly();
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bout);
try {
//1.写入魔数
dout.writeInt(0xCAFEBABE);
//2.写入次版本号
dout.writeShort(CLASSFILE_MINOR_VERSION);
//3.写入主版本号
dout.writeShort(CLASSFILE_MAJOR_VERSION);
//4.写入常量池
cp.write(dout);
//5.写入访问修饰符
dout.writeShort(ACC_PUBLIC | ACC_FINAL | ACC_SUPER);
//6.写入类索引
dout.writeShort(cp.getClass(dotToSlash(className)));
//7.写入父类索引, 生成的代理类都继承自Proxy
dout.writeShort(cp.getClass(superclassName));
//8.写入接口计数值
dout.writeShort(interfaces.length);
//9.写入接口集合
for (int i = 0; i < interfaces.length; i++) {
dout.writeShort(cp.getClass(dotToSlash(interfaces[i].getName())));
}
//10.写入字段计数值
dout.writeShort(fields.size());
//11.写入字段集合
for (FieldInfo f : fields) {
f.write(dout);
}
//12.写入方法计数值
dout.writeShort(methods.size());
//13.写入方法集合
for (MethodInfo m : methods) {
m.write(dout);
}
//14.写入属性计数值, 代理类class文件没有属性所以为0
dout.writeShort(0);
} catch (IOException e) {
throw new InternalError("unexpected I/O Exception");
}
//转换成二进制数组输出
return bout.toByteArray();
}
这时可以有个疑问,即使生成了代理类,但 目标方法执行的时候,前后的打印语句是在什么时候打印出来的? 这个时候,我们需要去生成的class文件中查看。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.sun.proxy;
import com.mk.coffee.test.jdk.reflect.Car;
import com.mk.coffee.test.jdk.reflect.CarFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements CarFactory {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final Car produce(String var1) throws {
try {
return (Car)super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.mk.coffee.test.jdk.reflect.CarFactory").getMethod("produce", Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
这个生成的Class文件,我们重点关注 produce方法
public final Car produce(String var1) throws {
try {
//此处的h,父类Proxy中的InvocationHandler
//this 为 代理类对象
//m3 表示 m3 = Class.forName("com.mk.coffee.test.jdk.reflect.CarFactory").getMethod("produce", Class.forName("java.lang.String"));
//参数是new Object[]{var1}
return (Car)super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
以上就是JDK动态代理的具体流程。你确定都知道了吗?
JDK动态代理流程图
二. Cglib动态代理
要实现CGLIG动态代理,必须引入cglib包,实现MethodIntercepter接口。
import org.springframework.cglib.core.DebuggingClassWriter;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @Auther: makui
* @Date: 2018/12/13
* @Description: cglib 动态代理
*/
public class CgbliProxy implements MethodInterceptor {
//通过Enhancer 创建代理对象
private Enhancer enhancer = new Enhancer();
//通过Class对象获取代理对象
public Object getProxy(Class c) {
//设置创建子类的类
enhancer.setSuperclass(c);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("代理类调用父类的方法之前...");
//代理类调用父类的方法
methodProxy.invokeSuper(obj, args);
System.out.println("代理类调用父类的方法之后...");
return null;
}
public static void main(String[] args) {
//代理类class文件存入本地磁盘可以查看
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/makui/Desktop/");
CgbliProxy cglibProxy = new CgbliProxy();
Car car = (Car) cglibProxy.getProxy(Car.class);
CarFactory carFactory = (CarFactory) cglibProxy.getProxy(BenzFactory.class);
carFactory.produce("aodi");
car.run(500);
}
}
打印输出:
代理类调用父类的方法之前...
正在制造品牌车 aodi
代理类调用父类的方法之后...
代理类调用父类的方法之前...
正在以时速500行驶
代理类调用父类的方法之后...
Cglib动态代理的实现步骤
a. 创建一个代理类,实现了MethodIntercepter接口。实现了intercept方法。
b. 通过Enhancer 创建代理类。
MethodIntercepter接口
//MethodIntercepter 接口就一个拦截方法
public interface MethodInterceptor extends Callback
{
/**
* @param obj "this", obj表示增强的对象,即实现这个接口类的一个对象;
* @param method method表示要被拦截的方法;
* @param args 要被拦截方法的参数;
* @param proxy 要触发父类的方法对象;
*/
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable;
}
重点在于Enhancer 创建代理类.
//设置父类
public void setSuperclass(Class superclass) {
if (superclass != null && superclass.isInterface()) {
this.setInterfaces(new Class[]{superclass});
} else if (superclass != null && superclass.equals(Object.class)) {
this.superclass = null;
} else {
this.superclass = superclass;
}
}
//设置接口
public void setInterfaces(Class[] interfaces) {
this.interfaces = interfaces;
}
//创建代理对象
public Object create() {
this.classOnly = false;
this.argumentTypes = null;
//创建代理对象实际调用的方法
return this.createHelper();
}
//通过newInstance()方法创建EnhancerKey对象,作为Enhancer父类AbstractClassGenerator.create()方法
private Object createHelper() {
preValidate();
Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
ReflectUtils.getNames(interfaces),
filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
callbackTypes,
useFactory,
interceptDuringConstruction,
serialVersionUID);
this.currentKey = key;
Object result = super.create(key);
return result;
}
创建代理对象
protected Object create(Object key) {
try {
ClassLoader loader = getClassLoader();
Map<ClassLoader, ClassLoaderData> cache = CACHE;
ClassLoaderData data = cache.get(loader);
if (data == null) {
synchronized (AbstractClassGenerator.class) {
cache = CACHE;
data = cache.get(loader);
if (data == null) {
Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
data = new ClassLoaderData(loader);
newCache.put(loader, data);
CACHE = newCache;
}
}
}
this.key = key;
Object obj = data.get(this, getUseCache());
if (obj instanceof Class) {
//生成对象实例
return firstInstance((Class) obj);
}
//生成对象实例
return nextInstance(obj);
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Exception e) {
throw new CodeGenerationException(e);
}
}
nextInstance(obj) 生成对象
protected Object nextInstance(Object instance) {
EnhancerFactoryData data = (EnhancerFactoryData) instance;
if (classOnly) {
return data.generatedClass;
}
Class[] argumentTypes = this.argumentTypes;
Object[] arguments = this.arguments;
if (argumentTypes == null) {
argumentTypes = Constants.EMPTY_CLASS_ARRAY;
arguments = null;
}
return data.newInstance(argumentTypes, arguments, callbacks);
}
EnhancerFactoryData的newInstance方法,通过发射生成代理对象。
/**
* 第一个参数为代理对象的构成器类型,
* 第二个为代理对象构造方法参数,
* 第三个为对应回调对象。
* 最后根据这些参数,通过反射生成代理对象
*/
public Object newInstance(Class[] argumentTypes, Object[] arguments, Callback[] callbacks) {
setThreadCallbacks(callbacks);
try {
// Explicit reference equality is added here just in case Arrays.equals does not have one
if (primaryConstructorArgTypes == argumentTypes ||
Arrays.equals(primaryConstructorArgTypes, argumentTypes)) {
// If we have relevant Constructor instance at hand, just call it
// This skips "get constructors" machinery
return ReflectUtils.newInstance(primaryConstructor, arguments);
}
// Take a slow path if observing unexpected argument types
return ReflectUtils.newInstance(generatedClass, argumentTypes, arguments);
} finally {
// clear thread callbacks to allow them to be gc'd
setThreadCallbacks(null);
}
}
Cglib为每个代理类生成3个Class文件
FastClass机制
Jdk动态代理的拦截对象是通过反射的机制来调用被拦截实例方法的,反射的效率比较低,所以cglib采用了FastClass的机制来实现对被拦截方法的调用。FastClass机制就是对一个类的方法建立索引,调用方法时根据方法的签名来计算索引,通过索引来直接调用相应的方法。
这也就是为什么CGLIB生成的动态代理会包含3个class文件的原因,其中一个是生成的代理类,另外两个类都是FastClass机制需要的。另外两个类都继承了FastClass这个类。其中一个class为生成的代理类中的每个方法建立了索引,另外一个则为我们被代理类的所有方法包含其父类的方法建立了索引。
//根据方法签名获取index
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case -2077043409:
if(var10000.equals("getPerson(Ljava/lang/String;)Lcom/demo/pojo/Person;")) {
return 21;
}
break;
case -2055565910:
if(var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
return 12;
}
break;
case -1902447170:
if(var10000.equals("setPerson()V")) {
return 7;
}
break;
//省略部分代码.....
//根据index直接定位执行方法
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
eaaaed75 var10000 = (eaaaed75)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
return new Boolean(var10000.equals(var3[0]));
case 1:
return var10000.toString();
case 2:
return new Integer(var10000.hashCode());
case 3:
return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]);
case 4:
return var10000.newInstance((Callback)var3[0]);
case 5:
return var10000.newInstance((Callback[])var3[0]);
case 6:
var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
return null;
case 7:
var10000.setPerson();
return null;
case 8:
var10000.setCallbacks((Callback[])var3[0]);
return null;
case 9:
return var10000.getCallback(((Number)var3[0]).intValue());
case 10:
return var10000.getCallbacks();
case 11:
eaaaed75.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
return null;
case 12:
eaaaed75.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
return null;
case 13:
return eaaaed75.CGLIB$findMethodProxy((Signature)var3[0]);
case 14:
return var10000.CGLIB$toString$3();
case 15:
return new Boolean(var10000.CGLIB$equals$2(var3[0]));
case 16:
return var10000.CGLIB$clone$5();
case 17:
return new Integer(var10000.CGLIB$hashCode$4());
case 18:
var10000.CGLIB$finalize$1();
return null;
case 19:
var10000.CGLIB$setPerson$0();
return null;
//省略部分代码....
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
FastClass并不是跟代理类一块生成的,而是在第一次执行MethodProxy invoke/invokeSuper时生成的并放在了缓存中。
//MethodProxy invoke/invokeSuper都调用了init()
private void init() {
if(this.fastClassInfo == null) {
Object var1 = this.initLock;
synchronized(this.initLock) {
if(this.fastClassInfo == null) {
MethodProxy.CreateInfo ci = this.createInfo;
MethodProxy.FastClassInfo fci = new MethodProxy.FastClassInfo();
fci.f1 = helper(ci, ci.c1);//如果缓存中就取出,没有就生成新的FastClass
fci.f2 = helper(ci, ci.c2);
fci.i1 = fci.f1.getIndex(this.sig1);//获取方法的index
fci.i2 = fci.f2.getIndex(this.sig2);
this.fastClassInfo = fci;
this.createInfo = null;
}
}
}
}**
总结 (JDK动态代理和Gglib动态代理的区别)
至此,动态代理的原理我们就基本搞清楚了,代码细节有兴趣可以再研究下。
最后我们总结一下JDK动态代理和Gglib动态代理的区别:
-
JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
-
JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。
-
JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。
-
Cglib通过继承,不能代理final, private 方法。