org.fastquery.asm.AsmRepository Maven / Gradle / Ivy
/*
* Copyright (c) 2016-2088, fastquery.org and/or its affiliates. All rights reserved.
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* For more information, please see http://www.fastquery.org/.
*
*/
package org.fastquery.asm;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import javassist.CannotCompileException;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.fastquery.analysis.GenerateExtends;
import org.fastquery.core.AbstractQueryRepository;
import org.fastquery.core.QueryRepository;
import org.fastquery.core.StrConst;
import org.fastquery.mapper.QueryValidator;
/**
* @author xixifeng ([email protected])
*/
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class AsmRepository
{
private static String getReturnTypeName(Method method)
{
Class> returnType = method.getReturnType();
String rtName = returnType.getName();
if (returnType.getComponentType() != null)
{
return returnType.getComponentType().getName() + "[]";
}
else
{
return rtName;
}
}
static String getMethodDef(Method method)
{
return "public " + getReturnTypeName(method) +
' ' +
method.getName() +
'(' +
getParameterDef(method.getParameterTypes()) +
')';
}
public static String getParameterDef(Class>[] parameterTypes)
{
int len = parameterTypes.length;
if (len > 0)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++)
{
if (parameterTypes[i].getComponentType() != null)
{
Class> clazz = parameterTypes[i].getComponentType();
sb.append(clazz.getName().replace("[L", StringUtils.EMPTY).replace("[", StringUtils.EMPTY).replace(";", StringUtils.EMPTY));
sb.append("[]");
while ((clazz = clazz.getComponentType()) != null)
{
sb.append("[]");
}
}
else
{
sb.append(parameterTypes[i].getName());
}
sb.append(' ');
sb.append("p");
sb.append(i);
sb.append(',');
}
return sb.deleteCharAt(sb.length() - 1).toString();
}
else
{
return StringUtils.EMPTY;
}
}
private static String getParameterNames(Class>[] parameterTypes)
{
int len = parameterTypes.length;
if (len > 0)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++)
{
Class> currentType = parameterTypes[i];
if (currentType == int.class)
{
sb.append("Integer.valueOf");
}
else if (currentType == double.class)
{
sb.append("Double.valueOf");
}
else if (currentType == long.class)
{
sb.append("Long.valueOf");
}
else if (currentType == short.class)
{
sb.append("Short.valueOf");
}
else if (currentType == byte.class)
{
sb.append("Byte.valueOf");
}
else if (currentType == boolean.class)
{
sb.append("Boolean.valueOf");
}
else if (currentType == char.class)
{
sb.append("Character.valueOf");
}
else if (currentType == float.class)
{
sb.append("Float.valueOf");
}
sb.append("(p");
sb.append(i);
sb.append("),");
}
sb.deleteCharAt(sb.length() - 1);
return "new Object[] { " + sb + " }";
}
else
{
return "org.apache.commons.lang3.ArrayUtils.EMPTY_OBJECT_ARRAY";
}
}
/**
* 自动生成Repository接口的实现类并以字节的形式返回.
*
* @param repositoryClazz repository class
* @return 生成的类字节码
*/
public static byte[] generateBytes(Class> repositoryClazz)
{
// 安全检测
GenerateExtends.safeCheck(repositoryClazz);
// 生成Judge
Script2Class.generate(repositoryClazz);
// 生成类
ClassPool pool = ClassPool.getDefault();
// web容器中的repository 需要增加classPath
ClassClassPath classClassPath = new ClassClassPath(repositoryClazz);
pool.removeClassPath(classClassPath);
pool.insertClassPath(classClassPath);
String className = repositoryClazz.getName() + StrConst.DB_SUF;
CtClass ctClass = pool.makeClass(className);
try
{
if (QueryRepository.class.isAssignableFrom(repositoryClazz))
{
// 设置父类
ctClass.setSuperclass(pool.get(AbstractQueryRepository.class.getName()));
}
// 增加接口
ctClass.setInterfaces(new CtClass[]{pool.get(repositoryClazz.getName())});
addGetInterfaceClassMethod(repositoryClazz, ctClass);
makeSingleton(className, ctClass);
makeMethod(repositoryClazz, ctClass);
return ctClass.toBytecode();
}
catch (Exception e)
{
throw new ExceptionInInitializerError(e);
}
}
static void addGetInterfaceClassMethod(Class> repositoryClazz, CtClass ctClass) throws CannotCompileException
{
// 增加字段
CtField field = CtField.make("private Class c = " + repositoryClazz.getName() + ".class;", ctClass);
ctClass.addField(field);
// 覆盖部分default 方法
CtMethod cm = CtMethod.make("public Class getInterfaceClass() {return c;}", ctClass);
ctClass.addMethod(cm);
}
private static void makeMethod(Class> repositoryClazz, CtClass ctClass) throws CannotCompileException
{
// 实现抽象方法
Method[] methods = repositoryClazz.getDeclaredMethods();
int len = methods.length;
if (len > 0)
{
// 新增MethodInfo缓存数组
CtField field = CtField.make("private org.fastquery.core.MethodInfo[] m = new org.fastquery.core.MethodInfo[" + len + "];", ctClass);
ctClass.addField(field);
int index = 0;
for (Method method : methods)
{
Class>[] ps = method.getParameterTypes();
String bodyBuilder = '{' +
"int j = " + index++ + ';' +
// 缓存method...
"if(this.m[j]==null) {" +
"java.lang.reflect.Method m;" +
"try {m = c.getMethod(\"" + method.getName() + "\", $sig);} catch (Exception e) {throw new org.fastquery.core.RepositoryException(e);}" +
"this.m[j] = new org.fastquery.core.MethodInfo(m); " +
"}" +
// 缓存method... End
"return ($r) org.fastquery.core.Prepared.excute(this.m[j]," + getParameterNames(ps) + ", this) ;" +
'}';
CtMethod cm = CtMethod.make(getMethodDef(method) + bodyBuilder, ctClass);
ctClass.addMethod(cm);
}
}
}
private static void makeSingleton(String className, CtClass ctClass) throws CannotCompileException
{
// 创建一个私有的静态变量
ctClass.addField(CtField.make("private static " + className + " i;", ctClass));
// 不带参数的私有方法
CtConstructor privateConstructor = new CtConstructor(new CtClass[]{}, ctClass);
privateConstructor.setModifiers(Modifier.PRIVATE);
privateConstructor.setBody("{}");
ctClass.addConstructor(privateConstructor);
// 创建getInstance方法
String getInstanceMethodSrc = "public static " + className + " g() { if(i == null) { i = new " + className + "();}return i;}";
ctClass.addMethod(CtMethod.make(getInstanceMethodSrc, ctClass));
}
/**
* 所有的代码生成之后
*
* @param classes Repository class 集合
*/
public static void after(List> classes)
{
QueryValidator.check(classes);
log.debug("\n\n\n\n初始化阶段结束\n");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy