2013-02-13 147 views
2

我需要使用cglib爲沒有默認構造函數的類生成子類。我有以下代碼類工作正常與默認構造函數:生成沒有默認構造函數的類的子類

Enhancer enhancer = new Enhancer(); 
    enhancer.setCallbackType(NoOp.class); 
    enhancer.setUseCache(false); 

    enhancer.setSuperclass(clazz); 
    return enhancer.createClass(); 

新類應該有哪些需要從它的超類調用一些非默認構造函數默認構造函數。

我已經搜索並發現cglib不能做這樣的事情,我需要使用asm。但是我找不到添加默認構造函數的例子。

如果有人有一個例子如何實現它,那會很好。

回答

3

我解決了這個問題。它看起來有點不同於我以前的想象。 Cglib繼承了所有的構造函數,而不僅僅是我之前想的默認構造函數。

但是它似乎不能替換構造函數而不影響現有的cglib構造函數構造代碼。這是微不足道的暗示,所以我只是從構造函數注入轉移到了方法注入。我在構造函數返回之前添加我的方法調用。這工作!我很高興。

這是我得到:

CGLIB增強調用

Enhancer enhancer = new Enhancer(); 
     enhancer.setNamingPolicy(new IndexedNamingPolicy()); 
     enhancer.setCallbackType(NoOp.class); 
     enhancer.setUseCache(false); 
     enhancer.setStrategy(new DefaultGeneratorStrategy() { 
      @Override 
      protected ClassGenerator transform(ClassGenerator cg) throws Exception { 
       return new TransformingClassGenerator(cg, new DefaultConstructorEmitter(key)); 
      } 
     }); 

     enhancer.setSuperclass(clazz); 
     return enhancer.createClass(); 

和我DefaultConstructorEmitter(呵呵它仍然命名爲構造處理,沒關係)

private class DefaultConstructorEmitter extends ClassEmitterTransformer { 
     private final Signature CALL_SIGNATURE = TypeUtils.parseSignature("void someMethod(Object)"); 

     private String parametersKey; 

     public DefaultConstructorEmitter(final String key) { 
      parametersKey = key; 
     } 

     @Override 
     public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions) { 
      final CodeEmitter emitter = super.begin_method(access, sig, exceptions); 
      if (sig.getName().equals(Constants.CONSTRUCTOR_NAME)) { 
       return new CodeEmitter(emitter) { 
        @Override 
        public void visitInsn(int arg0) { 
         if (arg0 == Opcodes.RETURN) { 
          Type classType = ... 
          emitter.load_this(); 
          emitter.push(parametersKey); 
          emitter.invoke_static(classType, CALL_SIGNATURE); 
         } 
         super.visitInsn(arg0); 
        } 
       }; 
      } 

      return emitter; 
     } 
    } 

希望這個例子將幫助別人像我一樣不要花費幾個小時。

相關問題