Feat:动态代码编译引擎成熟!
This commit is contained in:
parent
392b1ebc09
commit
4bfc72dcea
@ -59,10 +59,6 @@
|
|||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.itranswarp</groupId>
|
|
||||||
<artifactId>compiler</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.reflections</groupId>
|
<groupId>org.reflections</groupId>
|
||||||
<artifactId>reflections</artifactId>
|
<artifactId>reflections</artifactId>
|
||||||
|
@ -3,6 +3,7 @@ package com.flyfish.framework.compiler;
|
|||||||
import com.flyfish.framework.compiler.support.DelegateJavaCompiler;
|
import com.flyfish.framework.compiler.support.DelegateJavaCompiler;
|
||||||
import com.flyfish.framework.compiler.support.SimpleJavaCompiler;
|
import com.flyfish.framework.compiler.support.SimpleJavaCompiler;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,10 +12,11 @@ import java.io.IOException;
|
|||||||
*
|
*
|
||||||
* @author wangyu
|
* @author wangyu
|
||||||
*/
|
*/
|
||||||
public interface DynamicJavaCompiler {
|
public interface DynamicJavaCompiler extends Closeable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代理的java编译器,使用库文件
|
* 代理的java编译器,使用库文件
|
||||||
|
*
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
static DynamicJavaCompiler delegate() {
|
static DynamicJavaCompiler delegate() {
|
||||||
|
@ -0,0 +1,82 @@
|
|||||||
|
package com.flyfish.framework.compiler.core;
|
||||||
|
|
||||||
|
import javax.tools.JavaCompiler;
|
||||||
|
import javax.tools.JavaFileObject;
|
||||||
|
import javax.tools.StandardJavaFileManager;
|
||||||
|
import javax.tools.ToolProvider;
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In-memory compile Java source code as String.
|
||||||
|
*
|
||||||
|
* @author michael
|
||||||
|
*/
|
||||||
|
public class JavaStringCompiler implements Closeable {
|
||||||
|
|
||||||
|
private final JavaCompiler compiler;
|
||||||
|
private final MemoryJavaFileManager manager;
|
||||||
|
private final MemoryClassLoader classLoader;
|
||||||
|
|
||||||
|
public JavaStringCompiler() {
|
||||||
|
this.compiler = ToolProvider.getSystemJavaCompiler();
|
||||||
|
StandardJavaFileManager stdManager = compiler.getStandardFileManager(null, null, null);
|
||||||
|
this.manager = new MemoryJavaFileManager(stdManager);
|
||||||
|
this.classLoader = new MemoryClassLoader(manager.getClassBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile a Java source file in memory.
|
||||||
|
*
|
||||||
|
* @param fileName Java file name, e.g. "Test.java"
|
||||||
|
* @param source The source code as String.
|
||||||
|
* @return The compiled results as Map that contains class name as key,
|
||||||
|
* class binary as value.
|
||||||
|
* @throws IOException If compile error.
|
||||||
|
*/
|
||||||
|
public Map<String, byte[]> compile(String fileName, String source) {
|
||||||
|
JavaFileObject javaFileObject = manager.makeStringSource(fileName, source);
|
||||||
|
JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, Collections.singletonList(javaFileObject));
|
||||||
|
Boolean result = task.call();
|
||||||
|
if (result == null || !result) {
|
||||||
|
throw new RuntimeException("Compilation failed.");
|
||||||
|
}
|
||||||
|
return manager.getClassBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load class from compiled classes.
|
||||||
|
*
|
||||||
|
* @param name Full class name.
|
||||||
|
* @return The Class instance.
|
||||||
|
* @throws ClassNotFoundException If class not found.
|
||||||
|
*/
|
||||||
|
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||||
|
return classLoader.loadClass(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the classLoader
|
||||||
|
*
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public ClassLoader getClassLoader() {
|
||||||
|
return classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
try {
|
||||||
|
if (null != manager) {
|
||||||
|
manager.close();
|
||||||
|
}
|
||||||
|
if (null != classLoader) {
|
||||||
|
classLoader.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.flyfish.framework.compiler.core;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load class from byte[] which is compiled in memory.
|
||||||
|
*
|
||||||
|
* @author michael
|
||||||
|
*/
|
||||||
|
class MemoryClassLoader extends URLClassLoader {
|
||||||
|
|
||||||
|
// class name to class bytes:
|
||||||
|
private final Map<String, byte[]> classBytes;
|
||||||
|
|
||||||
|
public MemoryClassLoader(Map<String, byte[]> classBytes) {
|
||||||
|
super(new URL[0], MemoryClassLoader.class.getClassLoader());
|
||||||
|
this.classBytes = classBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||||
|
byte[] buf = classBytes.get(name);
|
||||||
|
if (buf == null) {
|
||||||
|
return super.findClass(name);
|
||||||
|
}
|
||||||
|
classBytes.remove(name);
|
||||||
|
return defineClass(name, buf, 0, buf.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package com.flyfish.framework.compiler.core;
|
||||||
|
|
||||||
|
import javax.tools.*;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.FilterOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.CharBuffer;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In-memory java file manager.
|
||||||
|
*
|
||||||
|
* @author michael
|
||||||
|
*/
|
||||||
|
class MemoryJavaFileManager extends ForwardingJavaFileManager<JavaFileManager> {
|
||||||
|
|
||||||
|
// compiled classes in bytes:
|
||||||
|
final Map<String, byte[]> classBytes = new HashMap<>();
|
||||||
|
|
||||||
|
MemoryJavaFileManager(JavaFileManager fileManager) {
|
||||||
|
super(fileManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, byte[]> getClassBytes() {
|
||||||
|
return this.classBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flush() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
classBytes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind,
|
||||||
|
FileObject sibling) throws IOException {
|
||||||
|
if (kind == JavaFileObject.Kind.CLASS) {
|
||||||
|
return new MemoryOutputJavaFileObject(className);
|
||||||
|
} else {
|
||||||
|
return super.getJavaFileForOutput(location, className, kind, sibling);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JavaFileObject makeStringSource(String name, String code) {
|
||||||
|
return new MemoryInputJavaFileObject(name, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class MemoryInputJavaFileObject extends SimpleJavaFileObject {
|
||||||
|
|
||||||
|
final String code;
|
||||||
|
|
||||||
|
MemoryInputJavaFileObject(String name, String code) {
|
||||||
|
super(URI.create("string:///" + name), Kind.SOURCE);
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
|
||||||
|
return CharBuffer.wrap(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MemoryOutputJavaFileObject extends SimpleJavaFileObject {
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
MemoryOutputJavaFileObject(String name) {
|
||||||
|
super(URI.create("string:///" + name), Kind.CLASS);
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OutputStream openOutputStream() {
|
||||||
|
return new FilterOutputStream(new ByteArrayOutputStream()) {
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
out.close();
|
||||||
|
ByteArrayOutputStream bos = (ByteArrayOutputStream) out;
|
||||||
|
classBytes.put(name, bos.toByteArray());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package com.flyfish.framework.compiler.support;
|
package com.flyfish.framework.compiler.support;
|
||||||
|
|
||||||
import com.flyfish.framework.compiler.DynamicJavaCompiler;
|
import com.flyfish.framework.compiler.DynamicJavaCompiler;
|
||||||
import com.itranswarp.compiler.JavaStringCompiler;
|
import com.flyfish.framework.compiler.core.JavaStringCompiler;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.util.StreamUtils;
|
import org.springframework.util.StreamUtils;
|
||||||
|
|
||||||
@ -19,7 +19,6 @@ public class DelegateJavaCompiler implements DynamicJavaCompiler {
|
|||||||
// 第三方编译器
|
// 第三方编译器
|
||||||
private final JavaStringCompiler compiler = new JavaStringCompiler();
|
private final JavaStringCompiler compiler = new JavaStringCompiler();
|
||||||
|
|
||||||
|
|
||||||
private DelegateJavaCompiler() {
|
private DelegateJavaCompiler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +26,9 @@ public class DelegateJavaCompiler implements DynamicJavaCompiler {
|
|||||||
return SingletonHolder.INSTANCE;
|
return SingletonHolder.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ClassLoader classLoader() {
|
||||||
|
return getInstance().compiler.getClassLoader();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 编译java源码,通过字符串
|
* 编译java源码,通过字符串
|
||||||
@ -37,22 +38,26 @@ public class DelegateJavaCompiler implements DynamicJavaCompiler {
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Class<?> compile(String name, String source) throws IOException, ClassNotFoundException {
|
public Class<?> compile(String name, String source) throws ClassNotFoundException {
|
||||||
Map<String, byte[]> byteMap = compiler.compile(name, source);
|
Map<String, byte[]> byteMap = compiler.compile(name, source);
|
||||||
String className = StringUtils.substringBeforeLast(name, ".");
|
String className = StringUtils.substringBeforeLast(name, ".");
|
||||||
for (String key : byteMap.keySet()) {
|
for (String key : byteMap.keySet()) {
|
||||||
if (key.contains(className)) {
|
if (key.contains(className)) {
|
||||||
return compiler.loadClass(key, byteMap);
|
return compiler.loadClass(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new RuntimeException("【java编译器】源码中没有可以编译的类!");
|
throw new RuntimeException("【java编译器】源码中没有可以编译的类!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
compiler.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class SingletonHolder {
|
private static class SingletonHolder {
|
||||||
|
|
||||||
private static final DelegateJavaCompiler INSTANCE = new DelegateJavaCompiler();
|
private static final DelegateJavaCompiler INSTANCE = new DelegateJavaCompiler();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,6 +63,11 @@ public class SimpleJavaCompiler implements DynamicJavaCompiler {
|
|||||||
throw new RuntimeException("【java编译器】尝试编译源代码出现异常!");
|
throw new RuntimeException("【java编译器】尝试编译源代码出现异常!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static class SingletonHolder {
|
private static class SingletonHolder {
|
||||||
|
|
||||||
private static final SimpleJavaCompiler INSTANCE = new SimpleJavaCompiler();
|
private static final SimpleJavaCompiler INSTANCE = new SimpleJavaCompiler();
|
||||||
|
@ -32,6 +32,7 @@ public class CustomRepositoryRegistrar {
|
|||||||
// 构建器
|
// 构建器
|
||||||
this.builder = new CustomRepositoryBuilder(registry, extension,
|
this.builder = new CustomRepositoryBuilder(registry, extension,
|
||||||
configurationSource, resourceLoader, environment);
|
configurationSource, resourceLoader, environment);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,6 +51,7 @@ public class CustomRepositoryRegistrar {
|
|||||||
extension.postProcess(definitionBuilder, configurationSource);
|
extension.postProcess(definitionBuilder, configurationSource);
|
||||||
extension.postProcess(definitionBuilder, (AnnotationRepositoryConfigurationSource) configurationSource);
|
extension.postProcess(definitionBuilder, (AnnotationRepositoryConfigurationSource) configurationSource);
|
||||||
|
|
||||||
|
|
||||||
AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition();
|
AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition();
|
||||||
beanDefinition.setPrimary(configuration.isPrimary());
|
beanDefinition.setPrimary(configuration.isPrimary());
|
||||||
String beanName = StringUtils.uncapitalize(clazz.getSimpleName());
|
String beanName = StringUtils.uncapitalize(clazz.getSimpleName());
|
||||||
|
@ -1,10 +1,52 @@
|
|||||||
package com.flyfish.framework.beans.resolver;
|
package com.flyfish.framework.beans.resolver;
|
||||||
|
|
||||||
|
import com.flyfish.framework.compiler.DynamicJavaCompiler;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.web.reactive.result.method.AbstractHandlerMethodMapping;
|
||||||
|
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动态Bean生成解析器
|
* 动态Bean生成解析器
|
||||||
*
|
*
|
||||||
* @author wangyu
|
* @author wangyu
|
||||||
*/
|
*/
|
||||||
public class DynamicRestBeanResolver {
|
@Slf4j
|
||||||
|
@Lazy(false)
|
||||||
|
public class DynamicRestBeanResolver implements InitializingBean, DisposableBean {
|
||||||
|
|
||||||
|
private static final List<String> controllers = new ArrayList<>();
|
||||||
|
private final Method handlerRegister;
|
||||||
|
private final RequestMappingHandlerMapping mapping;
|
||||||
|
|
||||||
|
public DynamicRestBeanResolver(RequestMappingHandlerMapping mapping) throws NoSuchMethodException {
|
||||||
|
this.mapping = mapping;
|
||||||
|
this.handlerRegister = AbstractHandlerMethodMapping.class.getDeclaredMethod("detectHandlerMethods", Object.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addController(String controller) {
|
||||||
|
controllers.add(controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() throws Exception {
|
||||||
|
log.info("正在销毁rest自动配置器");
|
||||||
|
DynamicJavaCompiler.delegate().close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
log.info("正在注册controller...");
|
||||||
|
for (String bean : controllers) {
|
||||||
|
log.info("注册controller:{}", bean);
|
||||||
|
handlerRegister.setAccessible(true);
|
||||||
|
handlerRegister.invoke(mapping, bean);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.flyfish.framework.boot;
|
||||||
|
|
||||||
|
|
||||||
|
import com.flyfish.framework.compiler.support.DelegateJavaCompiler;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动类包装
|
||||||
|
*
|
||||||
|
* @author wangyu
|
||||||
|
* 实现了自定义的类加载器
|
||||||
|
*/
|
||||||
|
public class FlyfishAppRunner {
|
||||||
|
|
||||||
|
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
|
||||||
|
Thread.currentThread().setContextClassLoader(DelegateJavaCompiler.classLoader());
|
||||||
|
return SpringApplication.run(new Class[]{primarySource}, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,10 +1,14 @@
|
|||||||
package com.flyfish.framework.config;
|
package com.flyfish.framework.config;
|
||||||
|
|
||||||
|
import com.flyfish.framework.beans.resolver.DynamicRestBeanResolver;
|
||||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
|
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
|
||||||
import org.springframework.web.server.WebFilter;
|
import org.springframework.web.server.WebFilter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认初始化的Bean配置
|
* 默认初始化的Bean配置
|
||||||
*
|
*
|
||||||
@ -33,4 +37,11 @@ public class BeanConfig {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DynamicRestBeanResolver dynamicRestBeanResolver(RequestMappingHandlerMapping requestMappingHandlerMapping)
|
||||||
|
throws NoSuchMethodException {
|
||||||
|
return new DynamicRestBeanResolver(requestMappingHandlerMapping);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.flyfish.framework.config;
|
|||||||
import com.flyfish.framework.beans.annotations.EnableRestBeanDetect;
|
import com.flyfish.framework.beans.annotations.EnableRestBeanDetect;
|
||||||
import com.flyfish.framework.beans.annotations.RestBean;
|
import com.flyfish.framework.beans.annotations.RestBean;
|
||||||
import com.flyfish.framework.beans.repository.CustomRepositoryRegistrar;
|
import com.flyfish.framework.beans.repository.CustomRepositoryRegistrar;
|
||||||
|
import com.flyfish.framework.beans.resolver.DynamicRestBeanResolver;
|
||||||
import com.flyfish.framework.compiler.DynamicJavaCompiler;
|
import com.flyfish.framework.compiler.DynamicJavaCompiler;
|
||||||
import com.flyfish.framework.compiler.support.JavaSource;
|
import com.flyfish.framework.compiler.support.JavaSource;
|
||||||
import com.flyfish.framework.compiler.template.TemplateCompiler;
|
import com.flyfish.framework.compiler.template.TemplateCompiler;
|
||||||
@ -11,7 +12,6 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.reflections.Reflections;
|
import org.reflections.Reflections;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
@ -22,13 +22,8 @@ import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
|||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
import org.springframework.core.type.AnnotationMetadata;
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
import org.springframework.web.reactive.result.method.AbstractHandlerMethodMapping;
|
|
||||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -41,24 +36,19 @@ import java.util.stream.Stream;
|
|||||||
* @author wangyu
|
* @author wangyu
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware, InitializingBean {
|
public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
|
||||||
|
|
||||||
// 预编译模板
|
// 预编译模板
|
||||||
private final Map<String, Function<JavaSource, String>> templates = Stream.of("Repository", "Service", "Controller")
|
private final Map<String, Function<JavaSource, String>> templates = Stream.of("Repository", "Service", "Controller")
|
||||||
.collect(Collectors.toMap(key -> key, filename -> TemplateCompiler.compile("/templates/" + filename + ".tpl")));
|
.collect(Collectors.toMap(key -> key, filename -> TemplateCompiler.compile("/templates/" + filename + ".tpl")));
|
||||||
private final Map<String, Function<RestBean, Class<?>>> superClasses;
|
private final Map<String, Function<RestBean, Class<?>>> superClasses;
|
||||||
private final Method handlerRegister;
|
|
||||||
private final List<String> controllers = new ArrayList<>();
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private RequestMappingHandlerMapping requestMappingHandlerMapping;
|
|
||||||
// 资源加载器
|
// 资源加载器
|
||||||
private ResourceLoader resourceLoader;
|
private ResourceLoader resourceLoader;
|
||||||
// 环境变量
|
// 环境变量
|
||||||
private Environment environment;
|
private Environment environment;
|
||||||
|
|
||||||
public RestBeanAutoConfigure() throws NoSuchMethodException {
|
public RestBeanAutoConfigure() {
|
||||||
this.handlerRegister = AbstractHandlerMethodMapping.class.getDeclaredMethod("detectHandlerMethods", Object.class);
|
|
||||||
superClasses = new HashMap<>();
|
superClasses = new HashMap<>();
|
||||||
superClasses.put("Controller", RestBean::controllerClass);
|
superClasses.put("Controller", RestBean::controllerClass);
|
||||||
superClasses.put("Repository", RestBean::repoClass);
|
superClasses.put("Repository", RestBean::repoClass);
|
||||||
@ -138,7 +128,7 @@ public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, Res
|
|||||||
registry.registerBeanDefinition(beanName, builder.getBeanDefinition());
|
registry.registerBeanDefinition(beanName, builder.getBeanDefinition());
|
||||||
// 如果是controller,注册
|
// 如果是controller,注册
|
||||||
if (clazz.getSimpleName().endsWith("Controller")) {
|
if (clazz.getSimpleName().endsWith("Controller")) {
|
||||||
controllers.add(beanName);
|
DynamicRestBeanResolver.addController(beanName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,15 +150,6 @@ public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, Res
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterPropertiesSet() throws Exception {
|
|
||||||
for (String bean : controllers) {
|
|
||||||
log.info("注册controller:{}", bean);
|
|
||||||
handlerRegister.setAccessible(true);
|
|
||||||
handlerRegister.invoke(requestMappingHandlerMapping, bean);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||||
this.resourceLoader = resourceLoader;
|
this.resourceLoader = resourceLoader;
|
||||||
|
5
pom.xml
5
pom.xml
@ -84,11 +84,6 @@
|
|||||||
<artifactId>commons-io</artifactId>
|
<artifactId>commons-io</artifactId>
|
||||||
<version>2.6</version>
|
<version>2.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.itranswarp</groupId>
|
|
||||||
<artifactId>compiler</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.reflections</groupId>
|
<groupId>org.reflections</groupId>
|
||||||
<artifactId>reflections</artifactId>
|
<artifactId>reflections</artifactId>
|
||||||
|
Loading…
Reference in New Issue
Block a user