目的:解决native-image中gson功能无效的问题。 可以通过项目的 native-image Profile 来启用: mvn -P native-image -Dmaven.test.skip=true clean source:jar install 编译时会在各包中增加2个文件: META-INF/native-image/.../reflection-config.json META-INF/native-image/.../native-image.propertiesdev1
@@ -99,6 +99,7 @@ | |||
</scm> | |||
<modules> | |||
<module>weixin-graal</module> | |||
<module>weixin-java-common</module> | |||
<module>weixin-java-cp</module> | |||
<module>weixin-java-mp</module> | |||
@@ -331,6 +332,14 @@ | |||
</plugins> | |||
</build> | |||
</profile> | |||
<profile> | |||
<id>native-image</id> | |||
<activation> | |||
<activeByDefault>false</activeByDefault> | |||
</activation> | |||
</profile> | |||
</profiles> | |||
<build> | |||
@@ -0,0 +1,40 @@ | |||
<?xml version="1.0"?> | |||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | |||
xmlns="http://maven.apache.org/POM/4.0.0"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<parent> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>wx-java</artifactId> | |||
<version>3.6.7.B</version> | |||
</parent> | |||
<artifactId>weixin-graal</artifactId> | |||
<name>WxJava - Graal</name> | |||
<description>微信开发Java内部配合graal以产生native-image配置的辅助工具, 可以通过项目的 native-image Profile 来启用: mvn -P native-image ... | |||
</description> | |||
<dependencies> | |||
<dependency> | |||
<groupId>org.projectlombok</groupId> | |||
<artifactId>lombok</artifactId> | |||
<scope>compile</scope> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-compiler-plugin</artifactId> | |||
<version>3.5.1</version> | |||
<configuration> | |||
<proc>none</proc> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</project> |
@@ -0,0 +1,167 @@ | |||
package cn.binarywang.wx.graal; | |||
import lombok.Data; | |||
import javax.annotation.processing.AbstractProcessor; | |||
import javax.annotation.processing.RoundEnvironment; | |||
import javax.annotation.processing.SupportedAnnotationTypes; | |||
import javax.annotation.processing.SupportedSourceVersion; | |||
import javax.lang.model.SourceVersion; | |||
import javax.lang.model.element.TypeElement; | |||
import javax.lang.model.type.DeclaredType; | |||
import javax.lang.model.type.TypeKind; | |||
import javax.lang.model.type.TypeMirror; | |||
import javax.lang.model.util.ElementFilter; | |||
import javax.tools.FileObject; | |||
import javax.tools.StandardLocation; | |||
import java.io.IOException; | |||
import java.io.Writer; | |||
import java.util.Set; | |||
import java.util.SortedSet; | |||
import java.util.TreeSet; | |||
// 目前仅仅处理@Data,且必须在lombok自己的processor之前执行,千万注意!!!!! | |||
@SupportedAnnotationTypes("lombok.Data") | |||
@SupportedSourceVersion(SourceVersion.RELEASE_7) | |||
public class GraalProcessor extends AbstractProcessor { | |||
private static final String REFLECTION_CONFIG_JSON = "reflection-config.json"; | |||
private static final String NATIVE_IMAGE_PROPERTIES = "native-image.properties"; | |||
private SortedSet<String> classSet = new TreeSet<>(); | |||
private String shortestPackageName = null; | |||
@Override | |||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { | |||
for (TypeElement annotatedClass : ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(Data.class))) { | |||
registerClass(annotatedClass.getQualifiedName().toString()); | |||
handleSuperClass(annotatedClass); | |||
} | |||
//只有最后一轮才可以写文件,否则文件会被重复打开,报错! | |||
if (!roundEnv.processingOver()) return false; | |||
// 如果没有文件要写,跳过 | |||
if (classSet.isEmpty()) return false; | |||
writeFiles(); | |||
//必须返回false,以便让lombok能继续处理。 | |||
return false; | |||
} | |||
/** | |||
* 设置当前最短的package名称 | |||
* | |||
* @param packageName 包名 | |||
*/ | |||
private void setShortestPackageName(String packageName) { | |||
if (shortestPackageName == null) { | |||
shortestPackageName = packageName; | |||
} else if (packageName.length() < shortestPackageName.length()) { | |||
shortestPackageName = packageName; | |||
} | |||
} | |||
/** | |||
* 更加完整的类名来获取package名称 | |||
* | |||
* @param fullClassName 完整的类名 | |||
* @return package name | |||
*/ | |||
private String getPackageName(String fullClassName) { | |||
int last = fullClassName.lastIndexOf('.'); | |||
if (last == -1) return fullClassName; | |||
return fullClassName.substring(0, last); | |||
} | |||
/** | |||
* 保存文件 | |||
* META-INF/native-image/.../reflection-config.json | |||
* META-INF/native-image/.../native-image.properties | |||
*/ | |||
private void writeFiles() { | |||
String basePackage = shortestPackageName; | |||
String module; | |||
if (basePackage.contains(".")) { | |||
final int i = basePackage.lastIndexOf('.'); | |||
module = basePackage.substring(i + 1); | |||
basePackage = basePackage.substring(0, i); | |||
} else { | |||
module = basePackage; | |||
} | |||
String path = "META-INF/native-image/" + basePackage + "/" + module + "/"; | |||
String reflectFile = path + REFLECTION_CONFIG_JSON; | |||
String propsFile = path + NATIVE_IMAGE_PROPERTIES; | |||
try { | |||
FileObject fileObject = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", propsFile); | |||
Writer writer = fileObject.openWriter(); | |||
writer.append("Args = -H:ReflectionConfigurationResources=${.}/" + REFLECTION_CONFIG_JSON); | |||
writer.close(); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} | |||
try { | |||
FileObject fileObject = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", reflectFile); | |||
Writer writer = fileObject.openWriter(); | |||
writer.write("[\n"); | |||
boolean first = true; | |||
for (String name : classSet) { | |||
if (first) { | |||
first = false; | |||
} else { | |||
writer.write(","); | |||
} | |||
writer.write(assetGraalJsonElement(name)); | |||
writer.append('\n'); | |||
} | |||
writer.write("]"); | |||
writer.close(); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} | |||
} | |||
private String assetGraalJsonElement(String className) { | |||
return "{\n" + | |||
" \"name\" : \"" + className + "\",\n" + | |||
" \"allDeclaredFields\":true,\n" + | |||
" \"allDeclaredMethods\":true,\n" + | |||
" \"allDeclaredConstructors\":true,\n" + | |||
" \"allPublicMethods\" : true\n" + | |||
"}"; | |||
} | |||
/** | |||
* 登记一个class | |||
* | |||
* @param className 完整的类名 | |||
*/ | |||
private void registerClass(String className) { | |||
classSet.add(className); | |||
setShortestPackageName(getPackageName(className)); | |||
} | |||
/** | |||
* 获取一个类型的所有的父类,并登记 | |||
* | |||
* @param typeElement 类型元素 | |||
*/ | |||
private void handleSuperClass(TypeElement typeElement) { | |||
TypeMirror superclass = typeElement.getSuperclass(); | |||
if (superclass.getKind() == TypeKind.DECLARED) { | |||
TypeElement s = (TypeElement) ((DeclaredType) superclass).asElement(); | |||
String sName = s.toString(); | |||
// ignore java.**/javax.** | |||
if (sName.startsWith("java.") || sName.startsWith("javax.")) return; | |||
registerClass(sName); | |||
handleSuperClass(s); | |||
} | |||
} | |||
} |
@@ -0,0 +1 @@ | |||
cn.binarywang.wx.graal.GraalProcessor |
@@ -1,7 +1,7 @@ | |||
<?xml version="1.0"?> | |||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | |||
xmlns="http://maven.apache.org/POM/4.0.0"> | |||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | |||
xmlns="http://maven.apache.org/POM/4.0.0"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<parent> | |||
<groupId>com.github.binarywang</groupId> | |||
@@ -134,4 +134,36 @@ | |||
</plugins> | |||
</build> | |||
<profiles> | |||
<profile> | |||
<id>native-image</id> | |||
<activation> | |||
<activeByDefault>false</activeByDefault> | |||
</activation> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-compiler-plugin</artifactId> | |||
<version>3.5.1</version> | |||
<configuration> | |||
<annotationProcessors> | |||
cn.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor | |||
</annotationProcessors> | |||
<annotationProcessorPaths> | |||
<path> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>weixin-graal</artifactId> | |||
<version>${project.version}</version> | |||
</path> | |||
</annotationProcessorPaths> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</profile> | |||
</profiles> | |||
</project> |
@@ -95,4 +95,36 @@ | |||
</plugins> | |||
</build> | |||
<profiles> | |||
<profile> | |||
<id>native-image</id> | |||
<activation> | |||
<activeByDefault>false</activeByDefault> | |||
</activation> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-compiler-plugin</artifactId> | |||
<version>3.5.1</version> | |||
<configuration> | |||
<annotationProcessors> | |||
cn.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor | |||
</annotationProcessors> | |||
<annotationProcessorPaths> | |||
<path> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>weixin-graal</artifactId> | |||
<version>${project.version}</version> | |||
</path> | |||
</annotationProcessorPaths> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</profile> | |||
</profiles> | |||
</project> |
@@ -80,12 +80,12 @@ | |||
<groupId>org.projectlombok</groupId> | |||
<artifactId>lombok</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.github.jedis-lock</groupId> | |||
<artifactId>jedis-lock</artifactId> | |||
<version>1.0.0</version> | |||
<optional>true</optional> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.github.jedis-lock</groupId> | |||
<artifactId>jedis-lock</artifactId> | |||
<version>1.0.0</version> | |||
<optional>true</optional> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
@@ -102,4 +102,35 @@ | |||
</plugins> | |||
</build> | |||
<profiles> | |||
<profile> | |||
<id>native-image</id> | |||
<activation> | |||
<activeByDefault>false</activeByDefault> | |||
</activation> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-compiler-plugin</artifactId> | |||
<version>3.5.1</version> | |||
<configuration> | |||
<annotationProcessors> | |||
cn.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor | |||
</annotationProcessors> | |||
<annotationProcessorPaths> | |||
<path> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>weixin-graal</artifactId> | |||
<version>${project.version}</version> | |||
</path> | |||
</annotationProcessorPaths> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</profile> | |||
</profiles> | |||
</project> |
@@ -96,4 +96,35 @@ | |||
</plugins> | |||
</build> | |||
<profiles> | |||
<profile> | |||
<id>native-image</id> | |||
<activation> | |||
<activeByDefault>false</activeByDefault> | |||
</activation> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-compiler-plugin</artifactId> | |||
<version>3.5.1</version> | |||
<configuration> | |||
<annotationProcessors> | |||
cn.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor | |||
</annotationProcessors> | |||
<annotationProcessorPaths> | |||
<path> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>weixin-graal</artifactId> | |||
<version>${project.version}</version> | |||
</path> | |||
</annotationProcessorPaths> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</profile> | |||
</profiles> | |||
</project> |
@@ -107,5 +107,35 @@ | |||
</plugins> | |||
</build> | |||
<profiles> | |||
<profile> | |||
<id>native-image</id> | |||
<activation> | |||
<activeByDefault>false</activeByDefault> | |||
</activation> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-compiler-plugin</artifactId> | |||
<version>3.5.1</version> | |||
<configuration> | |||
<annotationProcessors> | |||
cn.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor | |||
</annotationProcessors> | |||
<annotationProcessorPaths> | |||
<path> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>weixin-graal</artifactId> | |||
<version>${project.version}</version> | |||
</path> | |||
</annotationProcessorPaths> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</profile> | |||
</profiles> | |||
</project> |
@@ -72,4 +72,35 @@ | |||
</dependency> | |||
</dependencies> | |||
<profiles> | |||
<profile> | |||
<id>native-image</id> | |||
<activation> | |||
<activeByDefault>false</activeByDefault> | |||
</activation> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-compiler-plugin</artifactId> | |||
<version>3.5.1</version> | |||
<configuration> | |||
<annotationProcessors> | |||
cn.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor | |||
</annotationProcessors> | |||
<annotationProcessorPaths> | |||
<path> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>weixin-graal</artifactId> | |||
<version>${project.version}</version> | |||
</path> | |||
</annotationProcessorPaths> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</profile> | |||
</profiles> | |||
</project> |