1. 使用举例
public interface Calculator {
public int add(int i, int j);
}
public class MyCglib implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object o1 = methodProxy.invokeSuper(o, objects);
return o1;
}
}
public static void main(String[] args) {
//动态代理创建的class文件存储到本地
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"d:\\code");
//通过cglib动态代理获取代理对象的过程,创建调用的对象,在后续创建过程中EnhanceKey的对象,所以在进行enhancer对象创建的时候需要把EnhancerKey(newInstance)对象准备好,不过这个对象也需要动态代理来生成
Enhancer enhancer = new Enhancer();
//设置enhancer对象的父类
enhancer.setSuperclass(MyCalculator.class);
MyCglib myCglib = new MyCglib();
//设置enhancer的回调对象
enhancer.setCallback(myCglib);
//创建代理对象
MyCalculator myCalculator = (MyCalculator) enhancer.create();
//通过代理对象调用目标方法
int add = myCalculator.add(1, 1);
System.out.println(myCalculator.getClass());
}
2. 源码解析
public Object create() {
classOnly = false;
argumentTypes = null;
return createHelper();
}
private Object createHelper() {
// 校验callbackTypes、filter是否为空,以及为空时的处理
preValidate();
// 通过newInstance方法来创建EnhancerKey对象,正常情况下,只需要new一个对象就可以调用方法了,
// 但是Key_Factory是一个EnhancerKey类型,是一个内部接口,需要动态代理来实现,最终是为了调用newInstance方法
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);
// 设置当前enhancer的代理类的key标识
this.currentKey = key;
// 调用父类即AbstractClassGenerator的创建代理类
Object result = super.create(key);
return result;
}
链接到
AbstractClassGenerator.java#create(key)
方法
protected Object create(Object key) {
try {
// 获取到当前生成器的类加载器
ClassLoader loader = getClassLoader();
// 当前类加载器对应的缓存 缓存key为类加载器,缓存的value为ClassLoaderData,可以理解为一个缓存对象,只不过此缓存对象中包含的是具体的业务逻辑处理过程,
// 有两个function的函数式接口,一个是返回gen.key,对应的名称叫GET_KEY,还有一个是为了创建具体的class,名字叫做load
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) {
// 新建一个缓存Cache,并将之前的缓存Cache的数据添加进来,并将已经被gc回收的数据给清除掉
Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
// 新建一个当前加载器对应的ClassLoaderData并加到缓存中,但ClassLoaderData中此时还没有数据
data = new ClassLoaderData(loader);
newCache.put(loader, data);
// 刷新全局缓存
CACHE = newCache;
}
}
}
// 设置一个全局key
this.key = key;
// 在刚创建的data(ClassLoaderData)中调用get方法 并将当前生成器,
// 返回的是生成好的代理类的class信息;--》generatedClasses.get(gen);
//其中generatedClasses包含两个Function;有两个构建好的回调。根据判断调用,最终达到生成字节码的目的。
Object obj = data.get(this, getUseCache());
// 如果为class则实例化class并返回我们需要的代理类
if (obj instanceof Class) {
return firstInstance((Class) obj);
}
// 如果不是则说明是实体,则直接执行另一个方法返回实体
return nextInstance(obj);
}
catch (RuntimeException | Error ex) {
throw ex;
}
catch (Exception ex) {
throw new CodeGenerationException(ex);
}
}
上面代码注意
ClassLoaderData
类,是一个内部类
AbstractClasGenerator$ClassLoaderData
,其中比较重要的属性
generatedClasses
,是一个
LoadingCache
类型
public LoadingCache(Function<K, KK> keyMapper, Function<K, V> loader) {
this.keyMapper = keyMapper;
this.loader = loader;
this.map = new ConcurrentHashMap();
}
包含两个Function 类型的函数。
另外
ClassLoaderData
的代码如下:
protected static class ClassLoaderData {
private final Set<String> reservedClassNames = new HashSet<String>();
private final LoadingCache<AbstractClassGenerator, Object, Object> generatedClasses;
private final WeakReference<ClassLoader> classLoader;
private final Predicate uniqueNamePredicate = new Predicate() {
public boolean evaluate(Object name) {
return reservedClassNames.contains(name);
}
};
//核心代码,回调获取key
private static final Function<AbstractClassGenerator, Object> GET_KEY = new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
return gen.key;
}
};
//注意这个构造方法,里面
public ClassLoaderData(ClassLoader classLoader) {
// 判断类加载器不能为空
if (classLoader == null) {
throw new IllegalArgumentException("classLoader == null is not yet supported");
}
// 设置类加载器,弱引用 即在下次垃圾回收时就会进行回收
this.classLoader = new WeakReference<ClassLoader>(classLoader);
// 新建一个回调函数,该回调函数的作用在于缓存中没获取到值时,生成字节码文件
Function<AbstractClassGenerator, Object> load =
new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
//生成字节码文件
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
};
// 为这个ClassLoadData新建一个缓存类
generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);
}
//...省略若干代码....
public Object get(AbstractClassGenerator gen, boolean useCache) {
// 如果不用缓存(默认使用)
if (!useCache) {
// 则直接调用生成器的命令
return gen.generate(ClassLoaderData.this);
}
else {
// 传入代理类生成器 并根据代理类生成器获取值返回
Object cachedValue = generatedClasses.get(gen);
// 解包装并返回
return gen.unwrapCachedValue(cachedValue);
}
}
}
总结
主要是需要生成字节码。
LoadingCache
中放入了两个
Function
函数,通过回调的形式,一个获取key,一个根据上面的key获取字节码对象。
部分字节码展示
:
public final int add(int paramInt1, int paramInt2) {
if (this.CGLIB$CALLBACK_0 == null)
CGLIB$BIND_CALLBACKS(this);
if (this.CGLIB$CALLBACK_0 != null) {
this.CGLIB$CALLBACK_0.intercept(this, CGLIB$add$0$Method, new Object[] { new Integer(paramInt1), new Integer(paramInt2) }, CGLIB$add$0$Proxy);
return (this.CGLIB$CALLBACK_0.intercept(this, CGLIB$add$0$Method, new Object[] { new Integer(paramInt1), new Integer(paramInt2) }, CGLIB$add$0$Proxy) == null) ? 0 : ((Number)this.CGLIB$CALLBACK_0.intercept(this, CGLIB$add$0$Method, new Object[] { new Integer(paramInt1), new Integer(paramInt2) }, CGLIB$add$0$Proxy)).intValue();
}
return super.add(paramInt1, paramInt2);
}
可以看到callBack 不为空的话,那么调用intercept。继而调用到FastClass 中的方法。
版权声明:本文为sbl19940819原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。