private static < T > void generateProxyClass ( Class < T > primaryInterface , String superClassName , String methodBody ) throws Exception { String newClassName = superClassName . replaceAll ( "(.+)\\.(\\w+)" , "$1.Hikari$2" ) ; CtClass superCt = classPool . getCtClass ( superClassName ) ; CtClass targetCt = classPool . makeClass ( newClassName , superCt ) ; targetCt . setModifiers ( Modifier . FINAL ) ; System . out . println ( "Generating " + newClassName ) ; targetCt . setModifiers ( Modifier . PUBLIC ) ; // Make a set of method signatures we inherit implementation for, so we don't generate delegates for these Set < String > superSigs = new HashSet <> ( ) ; for ( CtMethod method : superCt . getMethods ( ) ) { if ( ( method . getModifiers ( ) & Modifier . FINAL ) == Modifier . FINAL ) { superSigs . add ( method . getName ( ) + method . getSignature ( ) ) ; } } Set < String > methods = new HashSet <> ( ) ; for ( Class < ? > intf : getAllInterfaces ( primaryInterface ) ) { CtClass intfCt = classPool . getCtClass ( intf . getName ( ) ) ; targetCt . addInterface ( intfCt ) ; for ( CtMethod intfMethod : intfCt . getDeclaredMethods ( ) ) { final String signature = intfMethod . getName ( ) + intfMethod . getSignature ( ) ; // don't generate delegates for methods we override if ( superSigs . contains ( signature ) ) { continue ; } // Ignore already added methods that come from other interfaces if ( methods . contains ( signature ) ) { continue ; } // Track what methods we've added methods . add ( signature ) ; // Clone the method we want to inject into CtMethod method = CtNewMethod . copy ( intfMethod , targetCt , null ) ; String modifiedBody = methodBody ; // If the super-Proxy has concrete methods (non-abstract), transform the call into a simple super.method() call CtMethod superMethod = superCt . getMethod ( intfMethod . getName ( ) , intfMethod . getSignature ( ) ) ; if ( ( superMethod . getModifiers ( ) & Modifier . ABSTRACT ) != Modifier . ABSTRACT && ! isDefaultMethod ( intf , intfMethod ) ) { modifiedBody = modifiedBody . replace ( "((cast) " , "" ) ; modifiedBody = modifiedBody . replace ( "delegate" , "super" ) ; modifiedBody = modifiedBody . replace ( "super)" , "super" ) ; } modifiedBody = modifiedBody . replace ( "cast" , primaryInterface . getName ( ) ) ; // Generate a method that simply invokes the same method on the delegate if ( isThrowsSqlException ( intfMethod ) ) { modifiedBody = modifiedBody . replace ( "method" , method . getName ( ) ) ; } else { modifiedBody = "{ return ((cast) delegate).method($$); }" . replace ( "method" , method . getName ( ) ) . replace ( "cast" , primaryInterface . getName ( ) ) ; } if ( method . getReturnType ( ) == CtClass . voidType ) { modifiedBody = modifiedBody . replace ( "return" , "" ) ; } method . setBody ( modifiedBody ) ; targetCt . addMethod ( method ) ; } } targetCt . getClassFile ( ) . setMajorVersion ( ClassFile . JAVA_8 ) ; targetCt . writeFile ( genDirectory + "target/classes" ) ; }
Generate Javassist Proxy Classes