Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.noear.solon.aot.proxy.ProxyClassFileBuilder Maven / Gradle / Ivy
/*
* Copyright 2017-2024 noear.org and authors
*
* Licensed 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
*
* https://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.
*/
package org.noear.solon.aot.proxy;
import com.squareup.javapoet.*;
import org.noear.solon.core.util.GenericUtil;
import javax.lang.model.element.Modifier;
import java.lang.reflect.*;
import java.util.Map;
/**
* 类文件构建器
*
* @author noear
* @since 2.2
*/
public class ProxyClassFileBuilder {
public static final String PROXY_CLASSNAME_SUFFIX ="$$SolonAotProxy";
public JavaFile build(Class typeElement) {
//::1.准备
//获取包路径
Package packageElement = typeElement.getPackage();
String packageName = packageElement.getName();
//获取类名(支持成员类)
String className = typeElement.getSimpleName();
ClassName supperClassName = ClassName.get(packageName, className);
String proxyClassName = className + PROXY_CLASSNAME_SUFFIX;
//获取所有函数
Map methodAll = MethodFinder.findMethodAll(typeElement);
//::2.开始
//生成的类
TypeSpec.Builder proxyTypeBuilder = TypeSpec
.classBuilder(proxyClassName)
.superclass(supperClassName)
.addModifiers(Modifier.PUBLIC, Modifier.FINAL);
//添加构造函数
addConstructor(proxyTypeBuilder, typeElement, proxyClassName);
if(methodAll.size() > 0) {
//添加代理函数
addMethodAll(proxyTypeBuilder, typeElement, methodAll);
//添加静态代码块
addStaticBlock(proxyTypeBuilder, packageName, className, methodAll);
}
//创建javaFile文件对象
TypeSpec proxyType = proxyTypeBuilder.build();
return JavaFile.builder(packageName, proxyType).build();
}
/**
* 添加构造函数
*/
private void addConstructor(TypeSpec.Builder proxyTypeBuilder, Class typeElement, String proxyClassName) {
//添加字段
proxyTypeBuilder.addField(InvocationHandler.class, "handler", Modifier.PRIVATE);
//添加构造函数
MethodSpec.Builder methodBuilder = MethodSpec
.constructorBuilder()
.addModifiers(Modifier.PUBLIC);
methodBuilder.addParameter(InvocationHandler.class, "handler");
methodBuilder.addParameter(Object[].class, "args");
Constructor constructor = typeElement.getDeclaredConstructors()[0];
if (constructor.getParameterCount() > 0) {
//支持"有参"构造函数
Class[] parameterTypes = constructor.getParameterTypes();
StringBuilder buf = new StringBuilder("super(");
for (int i = 0; i < parameterTypes.length; i++) {
Class t1 = parameterTypes[i];
buf.append("(").append(t1.getName()).append(")args[").append(i).append("],");
}
buf.setLength(buf.length() - 1);
buf.append(")");
methodBuilder.addStatement(buf.toString());
}
methodBuilder.addStatement("this.handler = handler");
proxyTypeBuilder.addMethod(methodBuilder.build());
}
/**
* 添加静态代码块
*/
private void addStaticBlock(TypeSpec.Builder proxyTypeBuilder, String packageName, String className, Map methodAll) {
int methodIndex = 0;
StringBuilder codeBuilder = new StringBuilder(150);
codeBuilder.append("try {\n");
codeBuilder.append(" Class clazz = $T.class;\n\n");
for (Method methodElement : methodAll.values()) {
//添加函数
if (MethodFinder.allowMethod(methodElement) == false) {
//静态 或 只读 或 私有;不需要重写
continue;
}
String methodFieldName = " method" + methodIndex;
codeBuilder.append(methodFieldName)
.append("=clazz.getMethod(\"")
.append(methodElement.getName())
.append("\"");
for (Parameter p0 : methodElement.getParameters()) {
if (p0.getParameterizedType() != null) {
Type p1 = p0.getType();
String p1Name = p1.getTypeName();
int p1NameIdx = p1Name.indexOf("<");
if (p1NameIdx > 0) {
p1Name = p1Name.substring(0, p1NameIdx);
}
if (p1 instanceof TypeVariable) {
codeBuilder.append(",Object.class");
} else {
codeBuilder.append(",")
.append(p1Name)
.append(".class");
}
} else {
Type p1 = p0.getType();
String p1Name = p1.toString();
int p1NameIdx = p1Name.indexOf("<");
if (p1NameIdx > 0) {
p1Name = p1Name.substring(0, p1NameIdx);
}
codeBuilder.append(",")
.append(p1Name)
.append(".class");
}
}
codeBuilder.append(");\n");
++methodIndex;
}
codeBuilder.append("} catch (Throwable e) {\n" +
" throw new IllegalStateException(e);\n" +
"}\n");
CodeBlock codeBlock = CodeBlock.of(codeBuilder.toString(), ClassName.get(packageName, className));
proxyTypeBuilder.addStaticBlock(codeBlock);
}
/**
* 添加所有函数
*/
private void addMethodAll(TypeSpec.Builder proxyTypeBuilder,Class typeElement, Map methodAll) {
int methodIndex = 0;
Map typeGenericMap = GenericUtil.getGenericInfo(typeElement);
for (Method e : methodAll.values()) {
//添加函数
methodIndex = addMethod(proxyTypeBuilder, typeGenericMap, e, methodIndex);
}
}
/**
* 添加具本函数
*/
private int addMethod(TypeSpec.Builder proxyTypeBuilder, Map typeGenericMap, Method methodElement, int methodIndex) {
if (MethodFinder.allowMethod(methodElement) == false) {
//静态 或 只读 或 私有;不需要重写
return methodIndex;
}
String methodFieldName = "method" + methodIndex;
proxyTypeBuilder.addField(Method.class, methodFieldName, Modifier.PRIVATE, Modifier.STATIC);
//Type returnType = TypeNameUtil.getType(typeGenericMap, methodElement.getReturnType(), methodElement.getGenericReturnType());
TypeName returnTypeName = TypeNameUtil.getTypeName(typeGenericMap, methodElement.getReturnType(), methodElement.getGenericReturnType());
StringBuilder codeBuilder = new StringBuilder(150);
boolean isPublic = java.lang.reflect.Modifier.isPublic(methodElement.getModifiers());
//生成方法
MethodSpec.Builder methodBuilder = MethodSpec
.methodBuilder(methodElement.getName().toString())
.addModifiers(isPublic ? Modifier.PUBLIC : Modifier.PROTECTED)
.addAnnotation(Override.class)
.returns(returnTypeName);
//添加可抛类型
for (Class tt : methodElement.getExceptionTypes()) {
methodBuilder.addException(TypeName.get(tt));
}
//添加函数泛型
for (TypeVariable te : methodElement.getTypeParameters()) {
methodBuilder.addTypeVariable(TypeVariableName.get(te));
}
//构建代码块和参数
codeBuilder.append("handler.invoke(this, ")
.append(methodFieldName).append(", ")
.append("new Object[]{");
//添加函数参数
for (Parameter pe : methodElement.getParameters()) {
TypeName paramType = TypeNameUtil.getTypeName(typeGenericMap, pe.getType(), pe.getParameterizedType());
String paramName = pe.getName();
methodBuilder.addParameter(paramType, paramName);
codeBuilder.append(paramName).append(",");
}
if (codeBuilder.charAt(codeBuilder.length() - 1) == ',') {
codeBuilder.setLength(codeBuilder.length() - 1);
}
codeBuilder.append("});");
//添加函数代码
if (Void.TYPE.equals(methodElement.getReturnType())) {
codeBuilder.insert(0, "try { \n ");
codeBuilder.append("\n} catch (RuntimeException _ex) {\n" +
" throw _ex;\n" +
"} catch (Throwable _ex) {\n" +
" throw new RuntimeException(_ex);\n" +
"}\n");
methodBuilder.addCode(codeBuilder.toString());
} else {
codeBuilder.insert(0, "try { \n return (" + returnTypeName + ")");
codeBuilder.append("\n} catch (RuntimeException _ex) {\n" +
" throw _ex;\n" +
"} catch (Throwable _ex) {\n" +
" throw new RuntimeException(_ex);\n" +
"}\n");
methodBuilder.addCode(codeBuilder.toString());
}
proxyTypeBuilder.addMethod(methodBuilder.build());
return ++methodIndex;
}
/**
* 根据类型和包名获取类名
*
* @param type 类型
* @param packageName 包名
*/
public static String getClassName(Class type, String packageName) {
return type.getSimpleName().replace('.', '$');
}
}