CGlib动态代理中Enhancer.create()函数的逻辑

来源:互联网 发布:软件平台架构 编辑:程序博客网 时间:2024/06/05 07:11

整个过程如下:

Cglib根据父类,Callback, Filter 及一些相关信息生成key.
然后根据key 生成对应的子类的二进制表现形式
使用ClassLoader装载对应的二进制,生成Class对象,并缓存
最后实例化Class对象,并缓存

下面是相对应的关键代码.

1)Cglib如何生成的Class的二进制文件
针对不同场景, CGlib准备了不同的Class生成方法, 他们都实现了接口: ClassGenerator. 下面我们只针对默认的Enhancer来分析.

Java代码
//此函数会被AbstractClassGenerator.create间接调用,并会在create函数中将结果缓存.

Enhancer.generateClass(ClassVisitor v)   //AbstractClassGenerator.create(Object key)  protected Object create(Object key) {      try {          Class gen = null;          synchronized (source) {              ClassLoader loader = getClassLoader();              Map cache2 = null;              cache2 = (Map)source.cache.get(loader);              if (cache2 == null) {                  cache2 = new HashMap();                  cache2.put(NAME_KEY, new HashSet());                  source.cache.put(loader, cache2);              } else if (useCache) {                  Reference ref = (Reference)cache2.get(key);                  gen = (Class) (( ref == null ) ? null : ref.get());               }              if (gen == null) {                  Object save = CURRENT.get();                  CURRENT.set(this);                  try {                      this.key = key;                      if (attemptLoad) {                          try {                              gen = loader.loadClass(getClassName());                          } catch (ClassNotFoundException e) {                              // ignore                          }                      }                      if (gen == null) {                          //生成的Class的二进制存储                          byte[] b = strategy.generate(this);                          String className = ClassNameReader.getClassName(new ClassReader(b));                          //将类名放入Cache中,Cache实际上是一个Hashset的实例                          getClassNameCache(loader).add(className);                          //将生成的类装载路JVM                          gen = ReflectUtils.defineClass(className, b, loader);                      }                      if (useCache) {                          //将装载的类放入cache                          cache2.put(key, new WeakReference(gen));                      }                      return firstInstance(gen);                  } finally {                      CURRENT.set(save);                  }              }          }          return firstInstance(gen);      } catch (RuntimeException e) {          throw e;      } catch (Error e) {          throw e;      } catch (Exception e) {          throw new CodeGenerationException(e);      }  }  

2)Cglib生成的Class二进制(byte[])放哪
放在byte数组中,下面这行代码就截取于方法AbstractClassGenerator.create(Object key)
byte[] b = strategy.generate(this);

然后通过 ReflectUtils.defineClass(className, b, loader) 生成对应的Class实例,并缓存入cache2

3)Cglib如何把二进制Load生成的Class

Java代码

//ReflectUtils.defineClass(className, b, loader)  public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception {      Object[] args = new Object[]{className, b, new Integer(0), new Integer(b.length), PROTECTION_DOMAIN };      //DEFINE_CLASS 是通过静态块来实例化的一个java.lang.ClassLoader.defineClass的方法对象      Class c = (Class)DEFINE_CLASS.invoke(loader, args);      // Force static initializers to run.      Class.forName(className, true, loader);      return c;  }     
原创粉丝点击