mirror of
https://github.com/tiennm99/zfoo.git
synced 2026-08-06 00:24:08 +00:00
feat[graalvm]: orm graalvm support
This commit is contained in:
@@ -15,12 +15,22 @@ package com.zfoo.boot;
|
||||
import com.zfoo.orm.OrmContext;
|
||||
import com.zfoo.orm.accessor.MongodbAccessor;
|
||||
import com.zfoo.orm.manager.OrmManager;
|
||||
import com.zfoo.orm.model.anno.GraalvmNativeEntityCache;
|
||||
import com.zfoo.orm.model.config.OrmConfig;
|
||||
import com.zfoo.orm.query.MongodbQuery;
|
||||
import com.zfoo.protocol.util.ClassUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.aot.hint.BindingReflectionHintsRegistrar;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportRuntimeHints;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* @author godotg
|
||||
@@ -28,8 +38,11 @@ import org.springframework.context.annotation.Configuration;
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnBean(OrmConfig.class)
|
||||
@ImportRuntimeHints(OrmAutoConfiguration.GraalvmOrmHints.class)
|
||||
public class OrmAutoConfiguration {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(OrmAutoConfiguration.class);
|
||||
|
||||
// OrmConfig in the specific business
|
||||
// If the OrmConfig bean is not configured in the business, then the Orm automatic assembly here will not take effect.
|
||||
@Bean
|
||||
@@ -59,4 +72,39 @@ public class OrmAutoConfiguration {
|
||||
return new OrmContext();
|
||||
}
|
||||
|
||||
|
||||
// Register runtime hints for the token library
|
||||
public static class GraalvmOrmHints implements RuntimeHintsRegistrar {
|
||||
|
||||
private final BindingReflectionHintsRegistrar bindingRegistrar = new BindingReflectionHintsRegistrar();
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
logger.info("orm graalvm aot runtime hints register");
|
||||
|
||||
var classes = new HashSet<Class<?>>();
|
||||
classes.add(OrmConfig.class);
|
||||
|
||||
try {
|
||||
for (var className : ClassUtils.getAllClasses("")) {
|
||||
try {
|
||||
var clazz = Class.forName(className);
|
||||
if (!clazz.isAnnotationPresent(GraalvmNativeEntityCache.class)) {
|
||||
continue;
|
||||
}
|
||||
classes.add(clazz);
|
||||
classes.addAll(ClassUtils.relevantClass(clazz));
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
for (var clazz : classes) {
|
||||
this.bindingRegistrar.registerReflectionHints(hints.reflection(), clazz);
|
||||
logger.info("orm graalvm aot hints register serialization [{}]", clazz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ import com.zfoo.storage.model.resource.ResourceData;
|
||||
import com.zfoo.storage.model.resource.ResourceEnum;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.aot.hint.*;
|
||||
import org.springframework.aot.hint.BindingReflectionHintsRegistrar;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -37,7 +39,7 @@ import java.util.HashSet;
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnBean(StorageConfig.class)
|
||||
@ImportRuntimeHints(StorageAutoConfiguration.StorageHints.class)
|
||||
@ImportRuntimeHints(StorageAutoConfiguration.GraalvmStorageHints.class)
|
||||
public class StorageAutoConfiguration {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(StorageAutoConfiguration.class);
|
||||
@@ -59,16 +61,17 @@ public class StorageAutoConfiguration {
|
||||
|
||||
|
||||
// Register runtime hints for the token library
|
||||
public static class StorageHints implements RuntimeHintsRegistrar {
|
||||
public static class GraalvmStorageHints implements RuntimeHintsRegistrar {
|
||||
|
||||
private final BindingReflectionHintsRegistrar bindingRegistrar = new BindingReflectionHintsRegistrar();
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
logger.info("storage aot runtime hints register");
|
||||
logger.info("storage graalvm aot runtime hints register");
|
||||
|
||||
var classes = new HashSet<Class<?>>();
|
||||
classes.add(ResourceData.class);
|
||||
classes.add(StorageConfig.class);
|
||||
|
||||
try {
|
||||
for (var className : ClassUtils.getAllClasses("")) {
|
||||
@@ -88,13 +91,13 @@ public class StorageAutoConfiguration {
|
||||
|
||||
for (var clazz : classes) {
|
||||
this.bindingRegistrar.registerReflectionHints(hints.reflection(), clazz);
|
||||
logger.info("storage aot hints register serialization [{}]", clazz);
|
||||
logger.info("storage graalvm aot hints register serialization [{}]", clazz);
|
||||
}
|
||||
|
||||
for (var resource : ResourceEnum.values()) {
|
||||
var include = StringUtils.format("*.{}", resource.getType());
|
||||
hints.resources().registerPattern(include);
|
||||
logger.info("storage aot hints register resources [{}]", include);
|
||||
logger.info("storage graalvm aot hints register resources [{}]", include);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,10 +34,7 @@ import com.zfoo.orm.model.vo.IndexTextDef;
|
||||
import com.zfoo.protocol.collection.ArrayUtils;
|
||||
import com.zfoo.protocol.collection.CollectionUtils;
|
||||
import com.zfoo.protocol.exception.RunException;
|
||||
import com.zfoo.protocol.util.AssertionUtils;
|
||||
import com.zfoo.protocol.util.JsonUtils;
|
||||
import com.zfoo.protocol.util.ReflectionUtils;
|
||||
import com.zfoo.protocol.util.StringUtils;
|
||||
import com.zfoo.protocol.util.*;
|
||||
import com.zfoo.util.math.RandomUtils;
|
||||
import com.zfoo.util.net.HostAndPort;
|
||||
import org.bson.Document;
|
||||
@@ -52,7 +49,6 @@ import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
@@ -92,7 +88,7 @@ public class OrmManager implements IOrmManager {
|
||||
|
||||
@Override
|
||||
public void initBefore() {
|
||||
var entityDefMap = scanEntityClass();
|
||||
var entityDefMap = entityClass();
|
||||
|
||||
for (var entityDef : entityDefMap.values()) {
|
||||
var entityCaches = new EntityCaches(entityDef);
|
||||
@@ -187,7 +183,7 @@ public class OrmManager implements IOrmManager {
|
||||
@Override
|
||||
public void inject() {
|
||||
var applicationContext = OrmContext.getApplicationContext();
|
||||
var componentBeans = applicationContext.getBeansWithAnnotation(Component.class);
|
||||
var componentBeans = applicationContext.getBeansWithAnnotation(Component.class);
|
||||
for (var bean : componentBeans.values()) {
|
||||
ReflectionUtils.filterFieldsInClass(bean.getClass()
|
||||
, field -> field.isAnnotationPresent(EntityCachesInjection.class)
|
||||
@@ -259,25 +255,32 @@ public class OrmManager implements IOrmManager {
|
||||
return mongodbDatabase.getCollection(collection);
|
||||
}
|
||||
|
||||
private Map<Class<? extends IEntity<?>>, EntityDef> scanEntityClass() {
|
||||
var cacheDefMap = new HashMap<Class<? extends IEntity<?>>, EntityDef>();
|
||||
private Map<Class<? extends IEntity<?>>, EntityDef> entityClass() {
|
||||
var classSet = new HashSet<>();
|
||||
// in graalvm environment, PathMatchingResourcePatternResolver/CachingMetadataReaderFactory unable to use, so get it directly in the spring container
|
||||
if (GraalVmUtils.isGraalVM()) {
|
||||
var applicationContext = OrmContext.getApplicationContext();
|
||||
var classes = applicationContext.getBeansWithAnnotation(GraalvmNativeEntityCache.class)
|
||||
.values()
|
||||
.stream()
|
||||
.map(it -> it.getClass())
|
||||
.collect(Collectors.toList());
|
||||
classSet.addAll(classes);
|
||||
} else {
|
||||
var classes = scanEntityCacheAnno();
|
||||
classSet.addAll(classes);
|
||||
}
|
||||
|
||||
var locationSet = scanEntityCacheAnno(ormConfig.getEntityPackage());
|
||||
for (var location : locationSet) {
|
||||
Class<? extends IEntity<?>> entityClazz;
|
||||
try {
|
||||
entityClazz = (Class<? extends IEntity<?>>) Class.forName(location);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RunException("无法获取实体类[{}]", location);
|
||||
}
|
||||
var cacheDef = parserEntityDef(entityClazz);
|
||||
var previousCacheDef = cacheDefMap.putIfAbsent(entityClazz, cacheDef);
|
||||
AssertionUtils.isNull(previousCacheDef, "缓存实体不能包含重复的[class:{}]", entityClazz.getSimpleName());
|
||||
var cacheDefMap = new HashMap<Class<? extends IEntity<?>>, EntityDef>();
|
||||
for (var clazz : classSet) {
|
||||
var cacheDef = parserEntityDef((Class<? extends IEntity<?>>) clazz);
|
||||
cacheDefMap.putIfAbsent((Class<? extends IEntity<?>>) clazz, cacheDef);
|
||||
}
|
||||
return cacheDefMap;
|
||||
}
|
||||
|
||||
private Set<String> scanEntityCacheAnno(String scanLocation) {
|
||||
private Set<Class<?>> scanEntityCacheAnno() {
|
||||
var scanLocation = ormConfig.getEntityPackage();
|
||||
var prefixPattern = "classpath*:";
|
||||
var suffixPattern = "**/*.class";
|
||||
|
||||
@@ -287,7 +290,7 @@ public class OrmManager implements IOrmManager {
|
||||
try {
|
||||
String packageSearchPath = prefixPattern + scanLocation.replace(StringUtils.PERIOD, StringUtils.SLASH) + StringUtils.SLASH + suffixPattern;
|
||||
Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);
|
||||
Set<String> result = new HashSet<>();
|
||||
var result = new HashSet<Class<?>>();
|
||||
String name = EntityCache.class.getName();
|
||||
for (Resource resource : resources) {
|
||||
if (resource.isReadable()) {
|
||||
@@ -295,19 +298,21 @@ public class OrmManager implements IOrmManager {
|
||||
AnnotationMetadata annoMeta = metadataReader.getAnnotationMetadata();
|
||||
if (annoMeta.hasAnnotation(name)) {
|
||||
ClassMetadata clazzMeta = metadataReader.getClassMetadata();
|
||||
result.add(clazzMeta.getClassName());
|
||||
result.add(Class.forName(clazzMeta.getClassName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch (IOException e) {
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("无法读取实体信息:" + e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public EntityDef parserEntityDef(Class<? extends IEntity<?>> clazz) {
|
||||
analyze(clazz);
|
||||
if (!GraalVmUtils.isGraalVM()) {
|
||||
analyze(clazz);
|
||||
}
|
||||
|
||||
var cacheStrategies = ormConfig.getCaches();
|
||||
var persisterStrategies = ormConfig.getPersisters();
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
package com.zfoo.orm.model.anno;
|
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
@@ -22,6 +24,7 @@ import java.lang.annotation.*;
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Reflective
|
||||
public @interface Cache {
|
||||
|
||||
String value() default "default";
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
package com.zfoo.orm.model.anno;
|
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
@@ -22,6 +24,7 @@ import java.lang.annotation.*;
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Reflective
|
||||
public @interface EntityCache {
|
||||
|
||||
Cache cache() default @Cache;
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
package com.zfoo.orm.model.anno;
|
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
@@ -22,5 +24,6 @@ import java.lang.annotation.*;
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
@Reflective
|
||||
public @interface EntityCachesInjection {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The zfoo 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.zfoo.orm.model.anno;
|
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @author godotg
|
||||
* @version 3.0
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Reflective
|
||||
@Component
|
||||
public @interface GraalvmNativeEntityCache {
|
||||
|
||||
}
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
package com.zfoo.orm.model.anno;
|
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
@@ -22,5 +24,6 @@ import java.lang.annotation.*;
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
@Reflective
|
||||
public @interface Id {
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
package com.zfoo.orm.model.anno;
|
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
@@ -22,6 +24,7 @@ import java.lang.annotation.*;
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
@Reflective
|
||||
public @interface Index {
|
||||
boolean ascending();
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
package com.zfoo.orm.model.anno;
|
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
@@ -24,6 +26,7 @@ import java.lang.annotation.*;
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
@Reflective
|
||||
public @interface IndexText {
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
package com.zfoo.orm.model.anno;
|
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
@@ -22,6 +24,7 @@ import java.lang.annotation.*;
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Reflective
|
||||
public @interface Persister {
|
||||
|
||||
String value() default "default";
|
||||
|
||||
@@ -13,15 +13,19 @@
|
||||
|
||||
package com.zfoo.orm.entity;
|
||||
|
||||
import com.zfoo.orm.model.anno.*;
|
||||
import com.zfoo.orm.model.anno.EntityCache;
|
||||
import com.zfoo.orm.model.anno.Id;
|
||||
import com.zfoo.orm.model.anno.Index;
|
||||
import com.zfoo.orm.model.anno.IndexText;
|
||||
import com.zfoo.orm.model.entity.IEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @EntityCache(persister = @Persister("time30s"))
|
||||
* @author godotg
|
||||
* @version 3.0@EntityCache(persister = @Persister("time30s"))
|
||||
* @version 3.0
|
||||
*/
|
||||
@EntityCache
|
||||
public class UserEntity implements IEntity<Long> {
|
||||
|
||||
Reference in New Issue
Block a user