private void autoInjectProperty(ModelClass modelClass) { // 连接数据库,自动获取所有信息,然后添加属性 CtClass ctClass = modelClass.originClass; String entitySimpleName = ctClass.getSimpleName(); List<String> skipFields = modelClass.notMappingColumns(); try { DBType dbType = ServiceFramwork.injector.getInstance(DBType.class); DBInfo dbInfo = ServiceFramwork.injector.getInstance(DBInfo.class); Map<String, String> columns = dbInfo.tableColumns.get(entitySimpleName); if (columns == null) return; for (String columnName : columns.keySet()) { String fieldName = columnName; String fieldType = columns.get(columnName); if (skipFields.contains(fieldName)) continue; if (fieldName.equals("discriminator")) continue; // 对定义过的属性略过 boolean pass = true; try { ctClass.getField(fieldName); } catch (Exception e) { pass = false; } if (pass) continue; ConstPool constPool = ctClass.getClassFile().getConstPool(); AnnotationsAttribute attr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag); CtField ctField = CtField.make( " private " + dbType.typeToJava(fieldType).v2() + " " + fieldName + " ;", ctClass); Tuple<Class, Map> tuple = dbType.dateType(fieldType, constPool); if (tuple != null) { createAnnotation(attr, tuple.v1(), tuple.v2()); } if (fieldName.equals("id")) { createAnnotation(attr, javax.persistence.Id.class, map()); createAnnotation(attr, javax.persistence.GeneratedValue.class, map()); } else { createAnnotation( attr, Column.class, map("nullable", new BooleanMemberValue(true, constPool))); } if (attr.getAnnotations().length > 0) { ctField.getFieldInfo().addAttribute(attr); } ctClass.addField(ctField); } } catch (Exception e) { e.printStackTrace(); } ctClass.defrost(); }
public static void defrostClassIfExists(AOPClassPool pool, String className) { // In some cases we get a class frozen exception. I guess if the invocation class // existed, method was unwrapped and the wrapped again CtClass existing = pool.getCached(className); if (existing != null) { existing.defrost(); } }
private void autoInjectGetSet(CtClass ctClass) throws Exception { // hibernate 可能需要 setter/getter 方法,好吧 我们为它添加这些方法 for (CtField ctField : ctClass.getDeclaredFields()) { if (isFinal(ctField) || isStatic(ctField) || ctField.hasAnnotation(Validate.class)) continue; // Property name String propertyName = ctField.getName().substring(0, 1).toUpperCase() + ctField.getName().substring(1); String getter = "get" + propertyName; String setter = "set" + propertyName; try { CtMethod ctMethod = ctClass.getDeclaredMethod(getter); if (ctMethod.getParameterTypes().length > 0 || Modifier.isStatic(ctMethod.getModifiers())) { throw new NotFoundException("it's not a getter !"); } } catch (NotFoundException noGetter) { String code = "public " + ctField.getType().getName() + " " + getter + "() { return this." + ctField.getName() + "; }"; CtMethod getMethod = CtMethod.make(code, ctClass); getMethod.setModifiers(getMethod.getModifiers() | AccessFlag.SYNTHETIC); ctClass.addMethod(getMethod); } try { CtMethod ctMethod = ctClass.getDeclaredMethod(setter); if (ctMethod.getParameterTypes().length != 1 || !ctMethod.getParameterTypes()[0].equals(ctField.getType()) || Modifier.isStatic(ctMethod.getModifiers())) { throw new NotFoundException("it's not a setter !"); } } catch (NotFoundException noSetter) { CtMethod setMethod = CtMethod.make( "public void " + setter + "(" + ctField.getType().getName() + " value) { this." + ctField.getName() + " = value; }", ctClass); setMethod.setModifiers(setMethod.getModifiers() | AccessFlag.SYNTHETIC); ctClass.addMethod(setMethod); } } ctClass.defrost(); }
@Override public void enhanceThisClass(final ApplicationClass applicationClass) throws Exception { final CtClass ctClass = makeClass(applicationClass); if (ctClass.isInterface()) { return; } final Map<CtField, InjectionInfo> fieldsToInject = scanForInjections(ctClass); // in all methods, replace the field accesses with a call to spring for (final CtMethod ctMethod : ctClass.getDeclaredMethods()) { ctMethod.instrument( new ExprEditor() { @Override public void edit(final FieldAccess fieldAccess) { try { final InjectionInfo injectionInfo = fieldsToInject.get(fieldAccess.getField()); if (injectionInfo != null && fieldAccess.isReader()) { switch (injectionInfo.injectionMethod) { case BY_NAME: fieldAccess.replace( "$_ = ($r)play.utils.Java.invokeStatic(play.modules.spring.Spring.class, \"getBean\", new Object[] {\"" + injectionInfo.beanName + "\"});"); break; case BY_TYPE: fieldAccess.replace( "$_ = ($r)play.utils.Java.invokeStatic(play.modules.spring.Spring.class, \"getBeanOfType\", new Object[] {$type});"); break; } } } catch (final Exception e) { Logger.error( e, "Error in SpringEnhancer. %s.%s has not been properly enhanced (fieldAccess %s).", applicationClass.name, ctMethod.getName(), fieldAccess); throw new UnexpectedException("Error enhancing injected field", e); } } }); } applicationClass.enhancedByteCode = ctClass.toBytecode(); ctClass.defrost(); }
/** * Retrieve the String value of an annotation which is not available at runtime. * * @param clazz The annotated class * @param annotation The annotation which is not visible at runtime * @param name The name of the String property of the annotation to retrieve * @return The String value of the annotation or null if the annotation or its property is not * present */ public static String getInvisibleAnnotationStringValue( Class<?> clazz, Class<? extends Annotation> annotation, String name) { CtClass ctClass = GwtClassPool.getCtClass(clazz); ctClass.defrost(); AnnotationsAttribute attr = (AnnotationsAttribute) ctClass.getClassFile().getAttribute(AnnotationsAttribute.invisibleTag); if (attr == null) { return null; } javassist.bytecode.annotation.Annotation an = attr.getAnnotation(annotation.getName()); ctClass.freeze(); return an != null ? ((StringMemberValue) an.getMemberValue(name)).getValue() : null; }
public void rewrite(final CtClass clazz) throws CannotCompileException { try { ClassPool cp = ClassPool.getDefault(); byte[] b1 = clazz.toBytecode(); clazz.defrost(); ClassReader cr = new ClassReader(b1); ClassWriter cw = new ClassWriter(0); // new ClassWriter(cr, 0); // TraceClassVisitor ca = new TraceClassVisitor( cw, new PrintWriter(System.out, true) ); // CheckClassAdapter cca = new CheckClassAdapter(ca); ConcurrencyControlRewriter.Adapter ca2 = new ConcurrencyControlRewriter.Adapter(cw, clazz); cr.accept(ca2, 0); byte[] b2 = cw.toByteArray(); cp.makeClass(new ByteArrayInputStream(b2)); } catch (IOException e) { throw new CannotCompileException(e); } }
/* Hibernate 的关联关系太复杂了。要么你区分控制端和被控制端。要么你必须在使用的时候将两端都设置好关联关系。 对于mappedBy也是一个无语的设计。为什么我要通过它来区分控制端? */ public void inner_enhance(ModelClass modelClass) throws Exception { CtClass ctClass = modelClass.originClass; CtField[] fields = ctClass.getDeclaredFields(); enhanceJPACallback(ctClass); OneToOneEnhancer oneToOneEnhancer = new OneToOneEnhancer(modelClass); oneToOneEnhancer.enhancer(); OneToManyEnhancer oneToManyEnhancer = new OneToManyEnhancer(modelClass); oneToManyEnhancer.enhancer(); ManyToOneEnhancer manyToOneEnhancer = new ManyToOneEnhancer(modelClass); manyToOneEnhancer.enhancer(); ManyToManyEnhancer manyToManyEnhancer = new ManyToManyEnhancer(modelClass); manyToManyEnhancer.enhancer(); ctClass.defrost(); }
@Override public void enhanceThisClass(ApplicationClass applicationClass) throws Exception { final CtClass ctClass = makeClass(applicationClass); if (ctClass.isInterface()) { return; } if (ctClass.getName().endsWith(".package")) { return; } // Add a default constructor if needed try { boolean hasDefaultConstructor = false; for (CtConstructor constructor : ctClass.getDeclaredConstructors()) { if (constructor.getParameterTypes().length == 0) { hasDefaultConstructor = true; break; } } if (!hasDefaultConstructor && !ctClass.isInterface()) { CtConstructor defaultConstructor = CtNewConstructor.make("public " + ctClass.getSimpleName() + "() {}", ctClass); ctClass.addConstructor(defaultConstructor); } } catch (Exception e) { Logger.error(e, "Error in PropertiesEnhancer"); throw new UnexpectedException("Error in PropertiesEnhancer", e); } if (isScala(applicationClass)) { // Temporary hack for Scala. Done. applicationClass.enhancedByteCode = ctClass.toBytecode(); ctClass.defrost(); return; } for (CtField ctField : ctClass.getDeclaredFields()) { try { if (isProperty(ctField)) { // Property name String propertyName = ctField.getName().substring(0, 1).toUpperCase() + ctField.getName().substring(1); String getter = "get" + propertyName; String setter = "set" + propertyName; try { CtMethod ctMethod = ctClass.getDeclaredMethod(getter); if (ctMethod.getParameterTypes().length > 0 || Modifier.isStatic(ctMethod.getModifiers())) { throw new NotFoundException("it's not a getter !"); } } catch (NotFoundException noGetter) { // Créé le getter String code = "public " + ctField.getType().getName() + " " + getter + "() { return this." + ctField.getName() + "; }"; CtMethod getMethod = CtMethod.make(code, ctClass); getMethod.setModifiers(getMethod.getModifiers() | AccessFlag.SYNTHETIC); ctClass.addMethod(getMethod); } if (!isFinal(ctField)) { try { CtMethod ctMethod = ctClass.getDeclaredMethod(setter); if (ctMethod.getParameterTypes().length != 1 || !ctMethod.getParameterTypes()[0].equals(ctField.getType()) || Modifier.isStatic(ctMethod.getModifiers())) { throw new NotFoundException("it's not a setter !"); } } catch (NotFoundException noSetter) { // Créé le setter CtMethod setMethod = CtMethod.make( "public void " + setter + "(" + ctField.getType().getName() + " value) { this." + ctField.getName() + " = value; }", ctClass); setMethod.setModifiers(setMethod.getModifiers() | AccessFlag.SYNTHETIC); ctClass.addMethod(setMethod); createAnnotation(getAnnotations(setMethod), PlayPropertyAccessor.class); } } } } catch (Exception e) { Logger.error(e, "Error in PropertiesEnhancer"); throw new UnexpectedException("Error in PropertiesEnhancer", e); } } // Add a default constructor if needed try { boolean hasDefaultConstructor = false; for (CtConstructor constructor : ctClass.getDeclaredConstructors()) { if (constructor.getParameterTypes().length == 0) { hasDefaultConstructor = true; break; } } if (!hasDefaultConstructor) { CtConstructor defaultConstructor = CtNewConstructor.defaultConstructor(ctClass); ctClass.addConstructor(defaultConstructor); } } catch (Exception e) { Logger.error(e, "Error in PropertiesEnhancer"); throw new UnexpectedException("Error in PropertiesEnhancer", e); } // Intercept all fields access for (final CtBehavior ctMethod : ctClass.getDeclaredBehaviors()) { ctMethod.instrument( new ExprEditor() { @Override public void edit(FieldAccess fieldAccess) throws CannotCompileException { try { // Acces à une property ? if (isProperty(fieldAccess.getField())) { // TODO : vérifier que c'est bien un champ d'une classe de l'application // (fieldAccess.getClassName()) // Si c'est un getter ou un setter String propertyName = null; if (fieldAccess .getField() .getDeclaringClass() .equals(ctMethod.getDeclaringClass()) || ctMethod .getDeclaringClass() .subclassOf(fieldAccess.getField().getDeclaringClass())) { if ((ctMethod.getName().startsWith("get") || (!isFinal(fieldAccess.getField()) && ctMethod.getName().startsWith("set"))) && ctMethod.getName().length() > 3) { propertyName = ctMethod.getName().substring(3); propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1); } } // On n'intercepte pas le getter de sa propre property if (propertyName == null || !propertyName.equals(fieldAccess.getFieldName())) { String invocationPoint = ctClass.getName() + "." + ctMethod.getName() + ", line " + fieldAccess.getLineNumber(); if (fieldAccess.isReader()) { // Réécris l'accés en lecture à la property fieldAccess.replace( "$_ = ($r)play.classloading.enhancers.PropertiesEnhancer.FieldAccessor.invokeReadProperty($0, \"" + fieldAccess.getFieldName() + "\", \"" + fieldAccess.getClassName() + "\", \"" + invocationPoint + "\");"); } else if (!isFinal(fieldAccess.getField()) && fieldAccess.isWriter()) { // Réécris l'accés en ecriture à la property fieldAccess.replace( "play.classloading.enhancers.PropertiesEnhancer.FieldAccessor.invokeWriteProperty($0, \"" + fieldAccess.getFieldName() + "\", " + fieldAccess.getField().getType().getName() + ".class, $1, \"" + fieldAccess.getClassName() + "\", \"" + invocationPoint + "\");"); } } } } catch (Exception e) { throw new UnexpectedException("Error in PropertiesEnhancer", e); } } }); } // Done. applicationClass.enhancedByteCode = ctClass.toBytecode(); ctClass.defrost(); }
@Override public byte[] transform( ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { // Be careful with Apache library usage in this class (e.g. ArrayUtils). Usage will likely cause // a ClassCircularityError // under JRebel. Favor not including outside libraries and unnecessary classes. CtClass clazz = null; try { boolean mySkipOverlaps = skipOverlaps; boolean myRenameMethodOverlaps = renameMethodOverlaps; String convertedClassName = className.replace('/', '.'); ClassPool classPool = null; String xformKey = convertedClassName; String[] xformVals = null; Boolean[] xformSkipOverlaps = null; Boolean[] xformRenameMethodOverlaps = null; if (!xformTemplates.isEmpty()) { if (xformTemplates.containsKey(xformKey)) { xformVals = xformTemplates.get(xformKey).split(","); classPool = ClassPool.getDefault(); clazz = classPool.makeClass(new ByteArrayInputStream(classfileBuffer), false); } } else { if (annotationTransformedClasses.contains(convertedClassName)) { logger.warn( convertedClassName + " has already been transformed by a previous instance of DirectCopyTransfomer. " + "Skipping this annotation based transformation. Generally, annotation-based transformation is handled " + "by bean id blAnnotationDirectCopyClassTransformer with template tokens being added to " + "blDirectCopyTransformTokenMap via EarlyStageMergeBeanPostProcessor."); } boolean isValidPattern = true; List<DirectCopyIgnorePattern> matchedPatterns = new ArrayList<DirectCopyIgnorePattern>(); for (DirectCopyIgnorePattern pattern : ignorePatterns) { boolean isPatternMatch = false; for (String patternString : pattern.getPatterns()) { isPatternMatch = convertedClassName.matches(patternString); if (isPatternMatch) { break; } } if (isPatternMatch) { matchedPatterns.add(pattern); } isValidPattern = !(isPatternMatch && pattern.getTemplateTokenPatterns() == null); if (!isValidPattern) { return null; } } if (isValidPattern) { classPool = ClassPool.getDefault(); clazz = classPool.makeClass(new ByteArrayInputStream(classfileBuffer), false); List<?> attributes = clazz.getClassFile().getAttributes(); Iterator<?> itr = attributes.iterator(); List<String> templates = new ArrayList<String>(); List<Boolean> skips = new ArrayList<Boolean>(); List<Boolean> renames = new ArrayList<Boolean>(); check: { while (itr.hasNext()) { Object object = itr.next(); if (AnnotationsAttribute.class.isAssignableFrom(object.getClass())) { AnnotationsAttribute attr = (AnnotationsAttribute) object; Annotation[] items = attr.getAnnotations(); for (Annotation annotation : items) { String typeName = annotation.getTypeName(); if (typeName.equals(DirectCopyTransform.class.getName())) { ArrayMemberValue arrayMember = (ArrayMemberValue) annotation.getMemberValue("value"); for (MemberValue arrayMemberValue : arrayMember.getValue()) { AnnotationMemberValue member = (AnnotationMemberValue) arrayMemberValue; Annotation memberAnnot = member.getValue(); ArrayMemberValue annot = (ArrayMemberValue) memberAnnot.getMemberValue("templateTokens"); for (MemberValue memberValue : annot.getValue()) { String val = ((StringMemberValue) memberValue).getValue(); if (val != null && templateTokens.containsKey(val)) { templateCheck: { for (DirectCopyIgnorePattern matchedPattern : matchedPatterns) { for (String ignoreToken : matchedPattern.getTemplateTokenPatterns()) { if (val.matches(ignoreToken)) { break templateCheck; } } } templates.add(templateTokens.get(val)); } } } BooleanMemberValue skipAnnot = (BooleanMemberValue) memberAnnot.getMemberValue("skipOverlaps"); if (skipAnnot != null) { skips.add(skipAnnot.getValue()); } else { skips.add(mySkipOverlaps); } BooleanMemberValue renameAnnot = (BooleanMemberValue) memberAnnot.getMemberValue("renameMethodOverlaps"); if (renameAnnot != null) { renames.add(renameAnnot.getValue()); } else { renames.add(myRenameMethodOverlaps); } } xformVals = templates.toArray(new String[templates.size()]); xformSkipOverlaps = skips.toArray(new Boolean[skips.size()]); xformRenameMethodOverlaps = renames.toArray(new Boolean[renames.size()]); break check; } } } } } } } if (xformVals != null && xformVals.length > 0) { logger.lifecycle( LifeCycleEvent.START, String.format( "Transform - Copying into [%s] from [%s]", xformKey, StringUtils.join(xformVals, ","))); // Load the destination class and defrost it so it is eligible for modifications clazz.defrost(); int index = 0; for (String xformVal : xformVals) { // Load the source class String trimmed = xformVal.trim(); classPool.appendClassPath(new LoaderClassPath(Class.forName(trimmed).getClassLoader())); CtClass template = classPool.get(trimmed); // Add in extra interfaces CtClass[] interfacesToCopy = template.getInterfaces(); for (CtClass i : interfacesToCopy) { checkInterfaces: { CtClass[] myInterfaces = clazz.getInterfaces(); for (CtClass myInterface : myInterfaces) { if (myInterface.getName().equals(i.getName())) { if (xformSkipOverlaps[index]) { break checkInterfaces; } else { throw new RuntimeException( "Duplicate interface detected " + myInterface.getName()); } } } logger.debug(String.format("Adding interface [%s]", i.getName())); clazz.addInterface(i); } } // copy over any EntityListeners ClassFile classFile = clazz.getClassFile(); ClassFile templateFile = template.getClassFile(); ConstPool constantPool = classFile.getConstPool(); buildClassLevelAnnotations(classFile, templateFile, constantPool); // Copy over all declared fields from the template class // Note that we do not copy over fields with the @NonCopiedField annotation CtField[] fieldsToCopy = template.getDeclaredFields(); for (CtField field : fieldsToCopy) { if (field.hasAnnotation(NonCopied.class)) { logger.debug(String.format("Not adding field [%s]", field.getName())); } else { try { CtField ctField = clazz.getDeclaredField(field.getName()); String originalSignature = ctField.getSignature(); String mySignature = field.getSignature(); if (!originalSignature.equals(mySignature)) { throw new IllegalArgumentException( "Field with name (" + field.getName() + ") and signature " + "(" + field.getSignature() + ") is targeted for weaving into (" + clazz.getName() + "). " + "An incompatible field of the same name and signature of (" + ctField.getSignature() + ") " + "already exists. The field in the target class should be updated to a different name, " + "or made to have a matching type."); } if (xformSkipOverlaps[index]) { logger.debug(String.format("Skipping overlapped field [%s]", field.getName())); continue; } } catch (NotFoundException e) { // do nothing -- field does not exist } logger.debug(String.format("Adding field [%s]", field.getName())); CtField copiedField = new CtField(field, clazz); boolean defaultConstructorFound = false; String implClass = getImplementationType(field.getType().getName()); // Look through all of the constructors in the implClass to see // if there is one that takes zero parameters try { CtConstructor[] implConstructors = classPool.get(implClass).getConstructors(); if (implConstructors != null) { for (CtConstructor cons : implConstructors) { if (cons.getParameterTypes().length == 0) { defaultConstructorFound = true; break; } } } } catch (NotFoundException e) { // Do nothing -- if we don't find this implementation, it's probably because it's // an array. In this case, we will not initialize the field. } if (defaultConstructorFound) { clazz.addField(copiedField, "new " + implClass + "()"); } else { clazz.addField(copiedField); } } } // Copy over all declared methods from the template class CtMethod[] methodsToCopy = template.getDeclaredMethods(); for (CtMethod method : methodsToCopy) { if (method.hasAnnotation(NonCopied.class)) { logger.debug(String.format("Not adding method [%s]", method.getName())); } else { try { CtClass[] paramTypes = method.getParameterTypes(); CtMethod originalMethod = clazz.getDeclaredMethod(method.getName(), paramTypes); if (xformSkipOverlaps[index]) { logger.debug( String.format( "Skipping overlapped method [%s]", methodDescription(originalMethod))); continue; } if (transformedMethods.contains(methodDescription(originalMethod))) { throw new RuntimeException( "Method already replaced " + methodDescription(originalMethod)); } else { logger.debug( String.format("Marking as replaced [%s]", methodDescription(originalMethod))); transformedMethods.add(methodDescription(originalMethod)); } logger.debug(String.format("Removing method [%s]", method.getName())); if (xformRenameMethodOverlaps[index]) { originalMethod.setName(renameMethodPrefix + method.getName()); } else { clazz.removeMethod(originalMethod); } } catch (NotFoundException e) { // Do nothing -- we don't need to remove a method because it doesn't exist } logger.debug(String.format("Adding method [%s]", method.getName())); CtMethod copiedMethod = new CtMethod(method, clazz, null); clazz.addMethod(copiedMethod); } } index++; } if (xformTemplates.isEmpty()) { annotationTransformedClasses.add(convertedClassName); } logger.lifecycle( LifeCycleEvent.END, String.format( "Transform - Copying into [%s] from [%s]", xformKey, StringUtils.join(xformVals, ","))); return clazz.toBytecode(); } } catch (ClassCircularityError error) { error.printStackTrace(); throw error; } catch (Exception e) { throw new RuntimeException("Unable to transform class", e); } finally { if (clazz != null) { clazz.detach(); } } return null; }
@Override public byte[] transform( ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { String convertedClassName = className.replace('/', '.'); if (xformTemplates.containsKey(convertedClassName)) { String xformKey = convertedClassName; String[] xformVals = xformTemplates.get(xformKey).split(","); logger.lifecycle( LifeCycleEvent.START, String.format( "Transform - Copying into [%s] from [%s]", xformKey, StringUtils.join(xformVals, ","))); try { // Load the destination class and defrost it so it is eligible for modifications ClassPool classPool = ClassPool.getDefault(); CtClass clazz = classPool.makeClass(new ByteArrayInputStream(classfileBuffer), false); clazz.defrost(); for (String xformVal : xformVals) { // Load the source class String trimmed = xformVal.trim(); classPool.appendClassPath(new LoaderClassPath(Class.forName(trimmed).getClassLoader())); CtClass template = classPool.get(trimmed); // Add in extra interfaces CtClass[] interfacesToCopy = template.getInterfaces(); for (CtClass i : interfacesToCopy) { logger.debug(String.format("Adding interface [%s]", i.getName())); clazz.addInterface(i); } // Copy over all declared fields from the template class // Note that we do not copy over fields with the @NonCopiedField annotation CtField[] fieldsToCopy = template.getDeclaredFields(); for (CtField field : fieldsToCopy) { if (field.hasAnnotation(NonCopied.class)) { logger.debug(String.format("Not adding field [%s]", field.getName())); } else { logger.debug(String.format("Adding field [%s]", field.getName())); CtField copiedField = new CtField(field, clazz); boolean defaultConstructorFound = false; String implClass = getImplementationType(field.getType().getName()); // Look through all of the constructors in the implClass to see // if there is one that takes zero parameters try { CtConstructor[] implConstructors = classPool.get(implClass).getConstructors(); if (implConstructors != null) { for (CtConstructor cons : implConstructors) { if (cons.getParameterTypes().length == 0) { defaultConstructorFound = true; break; } } } } catch (NotFoundException e) { // Do nothing -- if we don't find this implementation, it's probably because it's // an array. In this case, we will not initialize the field. } if (defaultConstructorFound) { clazz.addField(copiedField, "new " + implClass + "()"); } else { clazz.addField(copiedField); } } } // Copy over all declared methods from the template class CtMethod[] methodsToCopy = template.getDeclaredMethods(); for (CtMethod method : methodsToCopy) { if (method.hasAnnotation(NonCopied.class)) { logger.debug(String.format("Not adding method [%s]", method.getName())); } else { try { CtClass[] paramTypes = method.getParameterTypes(); CtMethod originalMethod = clazz.getDeclaredMethod(method.getName(), paramTypes); if (transformedMethods.contains(methodDescription(originalMethod))) { throw new RuntimeException( "Method already replaced " + methodDescription(originalMethod)); } else { logger.debug( String.format("Marking as replaced [%s]", methodDescription(originalMethod))); transformedMethods.add(methodDescription(originalMethod)); } logger.debug(String.format("Removing method [%s]", method.getName())); clazz.removeMethod(originalMethod); } catch (NotFoundException e) { // Do nothing -- we don't need to remove a method because it doesn't exist } logger.debug(String.format("Adding method [%s]", method.getName())); CtMethod copiedMethod = new CtMethod(method, clazz, null); clazz.addMethod(copiedMethod); } } } logger.lifecycle( LifeCycleEvent.END, String.format( "Transform - Copying into [%s] from [%s]", xformKey, StringUtils.join(xformVals, ","))); return clazz.toBytecode(); } catch (Exception e) { throw new RuntimeException("Unable to transform class", e); } } return null; }
@Override public void enhanceThisClass(ApplicationClass applicationClass) throws Exception { CtClass ctClass = makeClass(applicationClass); String entityName = ctClass.getName(); Logger.debug("Enhance class " + entityName); // Only enhance Neo4jModel classes. if (!ctClass.subtypeOf(classPool.get("play.modules.neo4j.model.Neo4jModel"))) { return; } // Add a default constructor if needed try { for (CtConstructor constructor : ctClass.getDeclaredConstructors()) { if (constructor.getParameterTypes().length == 0) { ctClass.removeConstructor(constructor); } if (constructor.getParameterTypes().length == 1 && constructor.getParameterTypes()[0].getClass().isInstance(Node.class)) { ctClass.removeConstructor(constructor); } } if (!ctClass.isInterface()) { Logger.debug("Adding default constructor"); CtConstructor defaultConstructor = CtNewConstructor.make("public " + ctClass.getSimpleName() + "() { super();}", ctClass); ctClass.addConstructor(defaultConstructor); } } catch (Exception e) { Logger.error(e, "Error in PropertiesEnhancer"); throw new UnexpectedException("Error in PropertiesEnhancer", e); } // for all field, we add getter / setter for (CtField ctField : ctClass.getDeclaredFields()) { try { // Property name String propertyName = ctField.getName().substring(0, 1).toUpperCase() + ctField.getName().substring(1); String getter = "get" + propertyName; String setter = "set" + propertyName; Logger.debug("Field " + ctField.getName() + " is a property ?"); if (isProperty(ctField)) { Logger.debug("true"); // ~~~~~~~~~ // GETTER // ~~~~~~~ try { CtMethod ctMethod = ctClass.getDeclaredMethod(getter); if (!ctMethod.getName().equalsIgnoreCase("getShouldBeSave")) { ctClass.removeMethod(ctMethod); throw new NotFoundException("it's not a true getter !"); } } catch (NotFoundException noGetter) { // create getter Logger.debug("Adding getter " + getter + " for class " + entityName); // @formatter:off String code = "public " + ctField.getType().getName() + " " + getter + "() {" + "if(this.shouldBeSave == Boolean.FALSE && this.node != null){" + "return ((" + ctField.getType().getName() + ") play.modules.neo4j.util.Binder.bindFromNeo4jFormat(this.node.getProperty(\"" + ctField.getName() + "\", null)," + ctField.getType().getName() + ".class ));" + "}else{" + "return " + ctField.getName() + ";" + "}" + "}"; // @formatter:on Logger.debug(code); CtMethod getMethod = CtMethod.make(code, ctClass); ctClass.addMethod(getMethod); } // ~~~~~~~~~ // SETTER // ~~~~~~~ try { CtMethod ctMethod = ctClass.getDeclaredMethod(setter); if (ctMethod.getParameterTypes().length != 1 || !ctMethod.getParameterTypes()[0].equals(ctField.getType()) || Modifier.isStatic(ctMethod.getModifiers()) || hasPlayPropertiesAccessorAnnotation(ctMethod)) { if (hasPlayPropertiesAccessorAnnotation(ctMethod)) { ctClass.removeMethod(ctMethod); } throw new NotFoundException("it's not a true setter !"); } } catch (NotFoundException noSetter) { // create setter Logger.debug("Adding setter " + setter + " for class " + entityName); // @formatter:off String code = "public void " + setter + "(" + ctField.getType().getName() + " value) { " + "this." + ctField.getName() + " = value;" + "this.shouldBeSave = Boolean.TRUE;" + "}"; // formatter:on CtMethod setMethod = CtMethod.make(code, ctClass); Logger.debug(code); ctClass.addMethod(setMethod); } } else { // ~~~~~~~~~ // GETTER for neo4j relation property // ~~~~~~~ if (hasNeo4jRelationAnnotation(ctField)) { // test for related annotation Neo4jRelatedTo relatedTo = getRelatedAnnotation(ctField); if (relatedTo != null) { CtMethod ctMethod = ctClass.getDeclaredMethod(getter); ctClass.removeMethod(ctMethod); String code; if (relatedTo.lazy()) { // @formatter:off code = "public " + ctField.getType().getName() + " " + getter + "() {" + "if(this." + ctField.getName() + " == null){" + "java.lang.reflect.Field field = this.getClass().getField(\"" + ctField.getName() + "\");" + "this." + ctField.getName() + "=play.modules.neo4j.relationship.Neo4jRelationFactory.getModelsFromRelation(\"" + relatedTo.value() + "\", \"" + relatedTo.direction() + "\", field, this.node);" + "}" + "return " + ctField.getName() + ";" + "}"; // @formatter:on } else { // @formatter:off code = "public " + ctField.getType().getName() + " " + getter + "() {" + "return " + ctField.getName() + ";" + "}"; // @formatter:on } Logger.debug(code); CtMethod method = CtMethod.make(code, ctClass); ctClass.addMethod(method); } // test for unique relation annotation Neo4jUniqueRelation uniqueRelation = getUniqueRelationAnnotation(ctField); if (uniqueRelation != null) { CtMethod ctMethod = ctClass.getDeclaredMethod(getter); ctClass.removeMethod(ctMethod); String code; // @formatter:off code = "public " + ctField.getType().getName() + " " + getter + "() {" + "return (" + ctField.getType().getName() + ")" + ctField.getName() + ";" + "}"; // @formatter:on Logger.debug(code); CtMethod method = CtMethod.make(code, ctClass); ctClass.addMethod(method); } } } } catch (Exception e) { Logger.error(e, "Error in PropertiesEnhancer"); throw new UnexpectedException("Error in PropertiesEnhancer", e); } } // Adding getByKey() method Logger.debug("Adding getByKey() method for class " + entityName); // @formatter:off String codeGetByKey = "public static play.modules.neo4j.model.Neo4jModel getByKey(Long key) throws play.modules.neo4j.exception.Neo4jException {" + "return (" + entityName + ")_getByKey(key, \"" + entityName + "\");" + "}"; // @formatter:on Logger.debug(codeGetByKey); CtMethod getByKeyMethod = CtMethod.make(codeGetByKey, ctClass); ctClass.addMethod(getByKeyMethod); // ~~~~~~~~~~~~~~~ // Adding findAll() method // @formatter:off String codeFindAll = "public static java.util.List findAll() {" + "return " + entityName + "._findAll(\"" + entityName + "\");" + "}"; // @formatter:on Logger.debug(codeFindAll); CtMethod findAllMethod = CtMethod.make(codeFindAll, ctClass); ctClass.addMethod(findAllMethod); // ~~~~~~~~~~~~~~~ // Adding queryIndex() method // @formatter:off String queryIndex = "public static java.util.List queryIndex(String indexname, String query) {" + "return " + entityName + "._queryIndex(indexname, query);" + "}"; // @formatter:on Logger.debug(queryIndex); CtMethod queryIndexMethod = CtMethod.make(queryIndex, ctClass); ctClass.addMethod(queryIndexMethod); // Done. applicationClass.enhancedByteCode = ctClass.toBytecode(); ctClass.defrost(); }
/** * Given a bean-style interface, generate an instance of the interface by implementing getters and * setters for each property. It will also add implementations to support the {@link * SupportsRdfId} interface and generate simple, default equals, toString and hashCode methods. * * <p>If there are other non-bean style (getter and/or setter's for properties) methods on the * interface, this will likely fail to generate the instance. * * @param theInterface the interface to build an instance of * @param <T> the type of the interface * @return New dynamically generated bytecode of a class that implements the given interface. * @throws Exception if there is an error while generating the bytecode of the new class. */ public static synchronized <T> Class<T> generateInstanceClass(Class<T> theInterface) throws Exception { processedMethods.clear(); // TODO: can we use some sort of template language for this? ClassPool aPool = ClassPool.getDefault(); aPool.appendClassPath(new LoaderClassPath(theInterface.getClassLoader())); CtClass aInterface = aPool.get(theInterface.getName()); CtClass aSupportsRdfIdInterface = aPool.get(SupportsRdfId.class.getName()); CtClass aEmpireGeneratedInterface = aPool.get(EmpireGenerated.class.getName()); if (!Arrays.asList(aInterface.getInterfaces()).contains(aSupportsRdfIdInterface) && !SupportsRdfId.class.isAssignableFrom(theInterface)) { throw new IllegalArgumentException( "Class '" + theInterface.getName() + "' does not implement SupportsRdfId, cannot generate Empire suitable implementation."); } String aName = aInterface.getPackageName() + ".impl." + aInterface.getSimpleName() + "Impl"; CtClass aClass = null; try { // i had a good reason for doing this, but i dont remember what it is. when i do, i'll // explain it here =) aClass = aPool.get(aName); return (Class<T>) BeanReflectUtil.loadClass(aName); } catch (NotFoundException e) { aClass = aPool.makeClass( aInterface.getPackageName() + ".impl." + aInterface.getSimpleName() + "Impl"); } catch (ClassNotFoundException e) { throw new Exception("Previously created class cannot be loaded.", e); } if (aClass.isFrozen()) { aClass.defrost(); } if (aInterface.isInterface()) { aClass.addInterface(aInterface); } else { aClass.setSuperclass(aInterface); } aClass.addInterface(aSupportsRdfIdInterface); aClass.addInterface(aEmpireGeneratedInterface); CtField aInterfaceField = new CtField(aPool.get(Class.class.getName()), "mInterfaceClass", aClass); aClass.addField( aInterfaceField, CtField.Initializer.byExpr(theInterface.getName() + ".class;")); CtField aAllTriplesField = new CtField(aPool.get(Graph.class.getName()), "mAllTriples", aClass); aClass.addField( aAllTriplesField, CtField.Initializer.byExpr("new com.clarkparsia.openrdf.ExtGraph();")); CtField aInstanceTriplesField = new CtField(aPool.get(Graph.class.getName()), "mInstanceTriples", aClass); aClass.addField( aInstanceTriplesField, CtField.Initializer.byExpr("new com.clarkparsia.openrdf.ExtGraph();")); aClass.addConstructor(CtNewConstructor.defaultConstructor(aClass)); generateMethods(theInterface, aPool, aClass); generateMethodsForSuperInterfaces(theInterface, aPool, aClass); CtField aIdField = new CtField(aPool.get(SupportsRdfId.class.getName()), "supportsId", aClass); aClass.addField( aIdField, CtField.Initializer.byExpr("new com.clarkparsia.empire.annotation.SupportsRdfIdImpl();")); if (!hasMethod(aClass, "getRdfId")) { aClass.addMethod( CtNewMethod.make( "public com.clarkparsia.empire.SupportsRdfId.RdfKey getRdfId() { return supportsId.getRdfId(); } ", aClass)); } if (!hasMethod(aClass, "setRdfId")) { aClass.addMethod( CtNewMethod.make( "public void setRdfId(com.clarkparsia.empire.SupportsRdfId.RdfKey theURI) { supportsId.setRdfId(theURI); } ", aClass)); } if (!hasMethod(aClass, "getAllTriples")) { aClass.addMethod( CtNewMethod.make( "public org.openrdf.model.Graph getAllTriples() { return mAllTriples; } ", aClass)); } if (!hasMethod(aClass, "setAllTriples")) { aClass.addMethod( CtNewMethod.make( "public void setAllTriples(org.openrdf.model.Graph theGraph) { mAllTriples = theGraph; } ", aClass)); } if (!hasMethod(aClass, "getInstanceTriples")) { aClass.addMethod( CtNewMethod.make( "public org.openrdf.model.Graph getInstanceTriples() { return mInstanceTriples; } ", aClass)); } if (!hasMethod(aClass, "setInstanceTriples")) { aClass.addMethod( CtNewMethod.make( "public void setInstanceTriples(org.openrdf.model.Graph theGraph) { mInstanceTriples = theGraph; } ", aClass)); } String equalsMethodBody = "public boolean equals(Object theObj) {\n" + " if (theObj == this) return true;\n" + " if (!(theObj instanceof com.clarkparsia.empire.SupportsRdfId)) return false;\n" + " if (!(mInterfaceClass.isAssignableFrom(theObj.getClass()))) return false;\n" + " return getRdfId().equals( ((com.clarkparsia.empire.SupportsRdfId) theObj).getRdfId()) && super.equals(theObj);\n" + "}\n"; aClass.addMethod(CtNewMethod.make(equalsMethodBody, aClass)); if (theInterface.isInterface()) { aClass.addMethod( CtNewMethod.make( "public String toString() { return getRdfId() != null ? getRdfId().toString() : super.toString(); } ", aClass)); aClass.addMethod( CtNewMethod.make( "public int hashCode() { return getRdfId() != null ? getRdfId().hashCode() : 0; } ", aClass)); } aClass.freeze(); Class<T> aResult = (Class<T>) aClass.toClass(); try { // make sure this is a valid class, that is, we can create instances of it! aResult.newInstance(); } catch (Exception ex) { // TODO: log this? throw ex; } return aResult; }
/* Hibernate 的关联关系太复杂了。要么你区分控制端和被控制端。要么你必须在使用的时候将两端都设置好关联关系。 对于mappedBy也是一个无语的设计。为什么我要通过它来区分控制端? */ @Override public void enhance(CtClass ctClass) throws Exception { CtField[] fields = ctClass.getDeclaredFields(); // String entityListener = "javax.persistence.EntityListeners"; // if (ctClass.hasAnnotation(EntityCallback.class)) { // EntityCallback entityListeners = (EntityCallback) // ctClass.getAnnotation(EntityCallback.class); // String clzzName = entityListeners.value(); // CtClass clzz = ServiceFramwork.classPool.get(clzzName); // enhanceJPACallback(clzz); // AnnotationsAttribute annotationsAttribute = // EnhancerHelper.getAnnotations(ctClass); // ArrayMemberValue arrayMemberValue = new // ArrayMemberValue(annotationsAttribute.getConstPool()); // ClassMemberValue[] clzzes = new ClassMemberValue[]{new ClassMemberValue(clzzName, // annotationsAttribute.getConstPool())}; // arrayMemberValue.setValue(clzzes); // EnhancerHelper.createAnnotation(annotationsAttribute, EntityListeners.class, // map("value", arrayMemberValue)); // // } else { // // } enhanceJPACallback(ctClass); for (CtField ctField : fields) { if (EnhancerHelper.hasAnnotation(ctField, "javax.persistence.OneToOne")) { DBInfo dbInfo = ServiceFramwork.injector.getInstance(DBInfo.class); Map<String, String> columns = dbInfo.tableColumns.get(ctClass.getSimpleName()); String clzzName = findAssociatedClassName(ctField); CtField mappedByField = findAssociatedField(ctClass, clzzName); if (!columns.containsKey(ctField.getName() + "_id")) { setMappedBy(ctField, mappedByField.getName(), "OneToOne"); } else { setMappedBy(mappedByField, mappedByField.getName(), "OneToOne"); } setCascad(mappedByField, "OneToOne"); setCascad(ctField, "OneToOne"); String mappedByClassName = clzzName; String mappedByFieldName = mappedByField.getName(); findAndRemoveMethod(ctClass, ctField, mappedByClassName); findAndRemoveMethod(ctClass, ctField.getName()); CtMethod wow = CtMethod.make( format( "public net.csdn.jpa.association.Association {}() {" + "net.csdn.jpa.association.Association obj = new net.csdn.jpa.association.Association(this,\"{}\",\"{}\",\"{}\");return obj;" + " }", ctField.getName(), ctField.getName(), mappedByFieldName, "javax.persistence.OneToOne"), ctClass); ctClass.addMethod(wow); CtMethod wow2 = CtMethod.make( format( "public {} {}({} obj) {" + " this.attr(\"{}\",obj);" + " obj.attr(\"{}\",this);" + " return this;" + " }", ctClass.getName(), ctField.getName(), mappedByClassName, ctField.getName(), mappedByFieldName), ctClass); ctClass.addMethod(wow2); } if (EnhancerHelper.hasAnnotation(ctField, "javax.persistence.OneToMany")) { String clzzName = findAssociatedClassName(ctField); String mappedByFieldName = findAssociatedFieldName(ctClass, clzzName); String mappedByClassName = ctClass.getName(); // 如果没有设置mappedBy我们帮他设置吧 setMappedBy(ctField, mappedByFieldName, "OneToMany"); setCascad(ctField, "OneToMany"); findAndRemoveMethod(ctClass, ctField, mappedByClassName); findAndRemoveMethod(ctClass, ctField.getName()); String propertyName = mappedByFieldName.substring(0, 1).toUpperCase() + mappedByFieldName.substring(1); String getter = "set" + propertyName; CtMethod wow = CtMethod.make( format( "public net.csdn.jpa.association.Association {}() {" + "net.csdn.jpa.association.Association obj = new net.csdn.jpa.association.Association(this,\"{}\",\"{}\",\"{}\");return obj;" + " }", ctField.getName(), ctField.getName(), mappedByFieldName, "javax.persistence.OneToMany"), ctClass); ctClass.addMethod(wow); CtMethod wow2 = CtMethod.make( format( "public {} {}({} obj) {" + " this.{}.add(obj);" + " obj.{}(this);" + " return this;" + " }", ctClass.getName(), ctField.getName(), clzzName, ctField.getName(), getter), ctClass); ctClass.addMethod(wow2); } if (EnhancerHelper.hasAnnotation(ctField, "javax.persistence.ManyToOne")) { String clzzName = ctField.getType().getName(); String mappedByFieldName = findAssociatedFieldName(ctClass, clzzName); String mappedByClassName = ctClass.getName(); // 默认设置为cascade = CascadeType.PERSIST setCascad(ctField, "ManyToOne"); findAndRemoveMethod(ctClass, ctField, mappedByClassName); findAndRemoveMethod(ctClass, ctField.getName()); String propertyName = mappedByFieldName.substring(0, 1).toUpperCase() + mappedByFieldName.substring(1); String getter = "get" + propertyName; CtMethod wow = CtMethod.make( format( "public net.csdn.jpa.association.Association {}() {" + "net.csdn.jpa.association.Association obj = new net.csdn.jpa.association.Association(this,\"{}\",\"{}\",\"{}\");return obj;" + " }", ctField.getName(), ctField.getName(), mappedByFieldName, "javax.persistence.ManyToOne"), ctClass); ctClass.addMethod(wow); CtMethod wow2 = CtMethod.make( format( "public {} {}({} obj) {" + " this.{} = obj;" + " obj.{}().add(this);" + " return this;" + " }", ctClass.getName(), ctField.getName(), clzzName, ctField.getName(), getter), ctClass); ctClass.addMethod(wow2); } if (EnhancerHelper.hasAnnotation(ctField, "javax.persistence.ManyToMany")) { String clzzName = findAssociatedClassName(ctField); String mappedByFieldName = findAssociatedFieldName(ctClass, clzzName); String mappedByClassName = ctClass.getName(); CtField other = findAssociatedField(ctClass, clzzName); DBInfo dbInfo = ServiceFramwork.injector.getInstance(DBInfo.class); String otherClassSimpleName = findAssociatedClass(ctClass.getClassPool(), ctField).getSimpleName(); String maybeTable1 = ctClass.getSimpleName() + "_" + otherClassSimpleName; String maybeTable2 = otherClassSimpleName + "_" + ctClass.getSimpleName(); String finalTableName = dbInfo.tableNames.contains(maybeTable1) ? maybeTable1 : maybeTable2; setCascad(ctField, "ManyToMany"); boolean isMaster = false; if (!ctField.hasAnnotation(ManyToManyHint.class)) { if (dbInfo.tableNames.contains(maybeTable1)) { setMappedBy(other, ctField.getName(), "ManyToMany"); isMaster = true; finalTableName = maybeTable1; } if (dbInfo.tableNames.contains(maybeTable2)) { setMappedBy(ctField, mappedByFieldName, "ManyToMany"); finalTableName = maybeTable2; } setManyToManyHint(other); } findAndRemoveMethod(ctClass, ctField, mappedByClassName); findAndRemoveMethod(ctClass, ctField.getName()); String propertyName = mappedByFieldName.substring(0, 1).toUpperCase() + mappedByFieldName.substring(1); String getter = "get" + propertyName; CtMethod wow = CtMethod.make( format( "public net.csdn.jpa.association.Association {}() {" + "net.csdn.jpa.association.Association obj = new net.csdn.jpa.association.Association(this,\"{}\",\"{}\",\"{}\",\"{}\",\"{}\");return obj;" + " }", ctField.getName(), ctField.getName(), mappedByFieldName, "javax.persistence.ManyToMany", finalTableName, isMaster), ctClass); ctClass.addMethod(wow); CtMethod wow2 = CtMethod.make( format( "public {} {}({} obj) {" + " {}.add(obj);" + " obj.{}().add(this);" + " return this;" + " }", ctClass.getName(), ctField.getName(), clzzName, ctField.getName(), getter), ctClass); ctClass.addMethod(wow2); } } ctClass.defrost(); }
private void enhanceModelMethods(CtClass ctClass) throws Exception { String entityName = ctClass.getName(); String simpleEntityName = ctClass.getSimpleName(); // count CtMethod count = CtMethod.make( "public static long count() { return getJPAContext().jpql().count(\"" + entityName + "\"); }", ctClass); ctClass.addMethod(count); // count2 CtMethod count2 = CtMethod.make( "public static long count(String query, Object[] params) { return getJPAContext().jpql().count(\"" + entityName + "\", query, params); }", ctClass); ctClass.addMethod(count2); // findAll CtMethod findAll = CtMethod.make( "public static java.util.List findAll() { return getJPAContext().jpql().findAll(\"" + entityName + "\"); }", ctClass); ctClass.addMethod(findAll); // findById CtMethod findById = CtMethod.make( "public static net.csdn.jpa.model.JPABase findById(Object id) { return getJPAContext().jpql().findById(" + entityName + ".class, id); }", ctClass); ctClass.addMethod(findById); // find CtMethod find = CtMethod.make( "public static net.csdn.jpa.model.Model.JPAQuery find(String query, Object[] params) { return getJPAContext().jpql().find(\"" + entityName + "\", query, params); }", ctClass); ctClass.addMethod(find); // find CtMethod find2 = CtMethod.make( "public static net.csdn.jpa.model.Model.JPAQuery find() { return getJPAContext().jpql().find(\"" + entityName + "\"); }", ctClass); ctClass.addMethod(find2); // all CtMethod all = CtMethod.make( "public static net.csdn.jpa.model.Model.JPAQuery all() { return getJPAContext().jpql().all(\"" + entityName + "\"); }", ctClass); ctClass.addMethod(all); // delete CtMethod delete = CtMethod.make( "public static int delete(String query, Object[] params) { return getJPAContext().jpql().delete(\"" + entityName + "\", query, params); }", ctClass); ctClass.addMethod(delete); // deleteAll CtMethod deleteAll = CtMethod.make( "public static int deleteAll() { return getJPAContext().jpql().deleteAll(\"" + entityName + "\"); }", ctClass); ctClass.addMethod(deleteAll); // findOneBy CtMethod findOneBy = CtMethod.make( "public static net.csdn.jpa.model.JPABase findOneBy(String query, Object[] params) { return getJPAContext().jpql().findOneBy(\"" + entityName + "\", query, params); }", ctClass); ctClass.addMethod(findOneBy); // create CtMethod create = CtMethod.make( "public static net.csdn.jpa.model.JPABase create(java.util.Map params) { return getJPAContext().jpql().create(" + entityName + ".class, params); }", ctClass); ctClass.addMethod(create); // where CtMethod where = CtMethod.make( "public static net.csdn.jpa.model.JPQL where(String cc){return getJPAContext().jpql(\"" + simpleEntityName + "\").where(cc);}", ctClass); ctClass.addMethod(where); // where2 CtMethod where2 = CtMethod.make( "public static net.csdn.jpa.model.JPQL where(String cc,java.util.Map params){return getJPAContext().jpql(\"" + simpleEntityName + "\").where(cc,params);}", ctClass); ctClass.addMethod(where2); // select CtMethod select = CtMethod.make( "public static net.csdn.jpa.model.JPQL select(String cc){return getJPAContext().jpql(\"" + simpleEntityName + "\").select(cc);}", ctClass); ctClass.addMethod(select); // joins CtMethod joins = CtMethod.make( "public static net.csdn.jpa.model.JPQL joins(String cc){return getJPAContext().jpql(\"" + simpleEntityName + "\").joins(cc);}", ctClass); ctClass.addMethod(joins); // order CtMethod order = CtMethod.make( "public static net.csdn.jpa.model.JPQL order(String cc){return getJPAContext().jpql(\"" + simpleEntityName + "\").order(cc);}", ctClass); ctClass.addMethod(order); // limit CtMethod limit = CtMethod.make( "public static net.csdn.jpa.model.JPQL limit(int cc){return getJPAContext().jpql(\"" + simpleEntityName + "\").limit(cc);}", ctClass); ctClass.addMethod(limit); // offset CtMethod offset = CtMethod.make( "public static net.csdn.jpa.model.JPQL offset(int cc){return getJPAContext().jpql(\"" + simpleEntityName + "\").offset(cc);}", ctClass); ctClass.addMethod(offset); CtMethod findWithSingleId = CtMethod.make( "public static net.csdn.jpa.model.JPABase find(Integer cc){return getJPAContext().jpql(\"" + simpleEntityName + "\").find(cc);}", ctClass); ctClass.addMethod(findWithSingleId); CtMethod findWithMultiId = CtMethod.make( "public static java.util.List find(java.util.List cc){return getJPAContext().jpql(\"" + simpleEntityName + "\").find(cc);}", ctClass); ctClass.addMethod(findWithMultiId); ctClass.defrost(); }