diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 221cb57..e4e8dcb 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -16,8 +16,8 @@ jobs: matrix: cache: [maven] distribution: [temurin] - java: [21, 25, 26-ea] - os: [macos-latest, ubuntu-latest, windows-latest] + java: [17, 21] + os: [ubuntu-latest, windows-latest] fail-fast: false max-parallel: 6 name: Test JDK ${{ matrix.java }}, ${{ matrix.os }} diff --git a/.github/workflows/samples.yaml b/.github/workflows/samples.yaml index 7837050..21cc7b6 100644 --- a/.github/workflows/samples.yaml +++ b/.github/workflows/samples.yaml @@ -36,9 +36,8 @@ jobs: - name: Set up GraalVM uses: graalvm/setup-graalvm@03e8abf916fd0e281b2efe7b2da3378bb0a1d085 # v1 with: - version: 'dev' java-version: ${{ matrix.java }} - components: 'native-image' + distribution: 'graalvm-community' github-token: ${{ secrets.GITHUB_TOKEN }} - name: Cache local Maven repository uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5 @@ -54,11 +53,11 @@ jobs: java --version native-image --version - name: Build native image - run: ./mvnw -pl core,extensions,samples/${{ matrix.sample }} -U -D"maven.test.skip" -Pnative -D"license.skip=true" clean package -B -V --no-transfer-progress + run: ./mvnw -pl core,extensions,samples,samples/${{ matrix.sample }} -U -D"maven.test.skip" -Pnative -D"license.skip=true" clean package -B -V --no-transfer-progress - name: Run with native image run: ./samples/${{ matrix.sample }}/target/mybatis-spring-native-sample-${{ matrix.sample }} - name: Run with executable jar on AOT mode - run: java -DspringAot=true -jar ./samples/${{ matrix.sample }}/target/mybatis-spring-native-sample-${{ matrix.sample }}-exec.jar + run: java -Dspring.aot.enabled=true -jar ./samples/${{ matrix.sample }}/target/mybatis-spring-native-sample-${{ matrix.sample }}-exec.jar - name: Run with executable jar run: java -jar ./samples/${{ matrix.sample }}/target/mybatis-spring-native-sample-${{ matrix.sample }}-exec.jar - name: Verify running with native image for ubuntu diff --git a/core/pom.xml b/core/pom.xml index 17102f5..6a4549e 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -50,16 +50,6 @@ ${mybatis-spring-boot.version} provided - - org.springframework.experimental - spring-native - provided - - - org.springframework.experimental - spring-aot - provided - org.springframework.boot spring-boot-starter-test diff --git a/core/src/main/java/org/mybatis/spring/nativex/MyBatisCoreNativeConfiguration.java b/core/src/main/java/org/mybatis/spring/nativex/MyBatisCoreNativeConfiguration.java index 7af0522..d4002d5 100644 --- a/core/src/main/java/org/mybatis/spring/nativex/MyBatisCoreNativeConfiguration.java +++ b/core/src/main/java/org/mybatis/spring/nativex/MyBatisCoreNativeConfiguration.java @@ -15,15 +15,6 @@ */ package org.mybatis.spring.nativex; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_METHODS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_METHODS; - import org.apache.ibatis.cache.decorators.FifoCache; import org.apache.ibatis.cache.decorators.LruCache; import org.apache.ibatis.cache.decorators.SoftCache; @@ -41,12 +32,11 @@ import org.apache.ibatis.scripting.defaults.RawLanguageDriver; import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver; import org.apache.ibatis.session.SqlSessionFactory; -import org.springframework.nativex.hint.InitializationHint; -import org.springframework.nativex.hint.InitializationTime; -import org.springframework.nativex.hint.NativeHint; -import org.springframework.nativex.hint.ResourceHint; -import org.springframework.nativex.hint.TypeHint; -import org.springframework.nativex.type.NativeConfiguration; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.aot.hint.TypeReference; +import org.springframework.util.ClassUtils; /** * Registers hints to make a MyBatis Core components work in a Spring Native context. @@ -56,53 +46,27 @@ * * @see MyBatisMapperNativeConfigurationProcessor */ -// @formatter:off -@NativeHint( - trigger = SqlSessionFactory.class, - initialization = @InitializationHint( - initTime = InitializationTime.BUILD, - types = org.apache.ibatis.type.JdbcType.class - ), - options = "--initialize-at-build-time=org.apache.ibatis.type.JdbcType", - resources = @ResourceHint( - patterns = { - "org/apache/ibatis/builder/xml/.*.dtd", - "org/apache/ibatis/builder/xml/.*.xsd" - } - ) -) -@TypeHint( - types = { - RawLanguageDriver.class, - XMLLanguageDriver.class, - RuntimeSupport.class, - ProxyFactory.class, - Slf4jImpl.class, - Log.class, - JakartaCommonsLoggingImpl.class, - Log4j2Impl.class, - Jdk14LoggingImpl.class, - StdOutImpl.class, - NoLoggingImpl.class, - SqlSessionFactory.class, - PerpetualCache.class, - FifoCache.class, - LruCache.class, - SoftCache.class, - WeakCache.class - }, - typeNames = "org.apache.ibatis.logging.log4j.Log4jImpl", - access = { - PUBLIC_CONSTRUCTORS, - PUBLIC_CLASSES, - PUBLIC_FIELDS, - PUBLIC_METHODS, - DECLARED_CLASSES, - DECLARED_CONSTRUCTORS, - DECLARED_FIELDS, - DECLARED_METHODS +public class MyBatisCoreNativeConfiguration implements RuntimeHintsRegistrar { + + private static final MemberCategory[] MEMBER_CATEGORIES = { MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS, + MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS, + MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES }; + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + if (!ClassUtils.isPresent("org.apache.ibatis.session.SqlSessionFactory", classLoader)) { + return; } -) -// @formatter:on -public class MyBatisCoreNativeConfiguration implements NativeConfiguration { + for (Class type : new Class[] { RawLanguageDriver.class, XMLLanguageDriver.class, RuntimeSupport.class, + ProxyFactory.class, Slf4jImpl.class, Log.class, JakartaCommonsLoggingImpl.class, Log4j2Impl.class, + Jdk14LoggingImpl.class, StdOutImpl.class, NoLoggingImpl.class, SqlSessionFactory.class, PerpetualCache.class, + FifoCache.class, LruCache.class, SoftCache.class, WeakCache.class }) { + hints.reflection().registerType(type, MEMBER_CATEGORIES); + } + hints.reflection().registerType(TypeReference.of("org.apache.ibatis.logging.log4j.Log4jImpl"), MEMBER_CATEGORIES); + hints.resources().registerPattern("org/apache/ibatis/builder/xml/*.dtd"); + hints.resources().registerPattern("org/apache/ibatis/builder/xml/*.xsd"); + } + } diff --git a/core/src/main/java/org/mybatis/spring/nativex/MyBatisMapperFactoryBeanPostProcessor.java b/core/src/main/java/org/mybatis/spring/nativex/MyBatisMapperFactoryBeanPostProcessor.java index 44aa809..9238099 100644 --- a/core/src/main/java/org/mybatis/spring/nativex/MyBatisMapperFactoryBeanPostProcessor.java +++ b/core/src/main/java/org/mybatis/spring/nativex/MyBatisMapperFactoryBeanPostProcessor.java @@ -18,61 +18,52 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.mybatis.spring.mapper.MapperFactoryBean; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; +import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor; +import org.springframework.beans.factory.config.ConstructorArgumentValues; +import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.context.annotation.BeanDefinitionPostProcessor; import org.springframework.core.ResolvableType; import org.springframework.util.ClassUtils; /** - * The {@code BeanDefinitionPostProcessor} for customizing a {@code MapperFactoryBean}. + * The {@code BeanRegistrationAotProcessor} for customizing a {@code MapperFactoryBean}. + *

+ * This class is public so that Spring's AOT service loading from {@code META-INF/spring/aot.factories} can instantiate + * it. * * @author Stéphane Nicoll * @author Kazuki Shimizu */ -class MyBatisMapperFactoryBeanPostProcessor implements BeanDefinitionPostProcessor, BeanFactoryAware { +public class MyBatisMapperFactoryBeanPostProcessor implements BeanRegistrationAotProcessor { private static final Log LOG = LogFactory.getLog(MyBatisMapperFactoryBeanPostProcessor.class); private static final String MAPPER_FACTORY_BEAN = "org.mybatis.spring.mapper.MapperFactoryBean"; - private ConfigurableBeanFactory beanFactory; - - @Override - public void setBeanFactory(BeanFactory beanFactory) { - this.beanFactory = (ConfigurableBeanFactory) beanFactory; - } - @Override - public void postProcessBeanDefinition(String beanName, RootBeanDefinition beanDefinition) { - if (ClassUtils.isPresent(MAPPER_FACTORY_BEAN, this.beanFactory.getBeanClassLoader())) { - resolveMapperFactoryBeanTypeIfNecessary(beanDefinition); + public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { + Class beanClass = registeredBean.getBeanClass(); + if (!ClassUtils.isPresent(MAPPER_FACTORY_BEAN, beanClass.getClassLoader())) { + return null; } - } - - private void resolveMapperFactoryBeanTypeIfNecessary(RootBeanDefinition beanDefinition) { - if (!beanDefinition.hasBeanClass() || !MapperFactoryBean.class.isAssignableFrom(beanDefinition.getBeanClass())) { - return; + if (!MapperFactoryBean.class.isAssignableFrom(beanClass)) { + return null; } + RootBeanDefinition beanDefinition = registeredBean.getMergedBeanDefinition(); if (beanDefinition.getResolvableType().hasUnresolvableGenerics()) { - Class mapperInterface = getMapperInterface(beanDefinition); - if (mapperInterface != null) { - // Exposes a generic type information to context for prevent early initializing - beanDefinition - .setTargetType(ResolvableType.forClassWithGenerics(beanDefinition.getBeanClass(), mapperInterface)); + try { + Class mapperInterface = (Class) beanDefinition.getPropertyValues().get("mapperInterface"); + if (mapperInterface != null) { + beanDefinition.setTargetType(ResolvableType.forClassWithGenerics(beanClass, mapperInterface)); + } + } catch (Exception e) { + LOG.debug("Fail getting mapper interface type.", e); } } - } - - private Class getMapperInterface(RootBeanDefinition beanDefinition) { - try { - return (Class) beanDefinition.getPropertyValues().get("mapperInterface"); - } catch (Exception e) { - LOG.debug("Fail getting mapper interface type.", e); - return null; - } + ConstructorArgumentValues constructorArgumentValues = beanDefinition.getConstructorArgumentValues(); + constructorArgumentValues.clear(); + return null; } } diff --git a/core/src/main/java/org/mybatis/spring/nativex/MyBatisMapperNativeConfigurationProcessor.java b/core/src/main/java/org/mybatis/spring/nativex/MyBatisMapperNativeConfigurationProcessor.java index f799f8a..39d3790 100644 --- a/core/src/main/java/org/mybatis/spring/nativex/MyBatisMapperNativeConfigurationProcessor.java +++ b/core/src/main/java/org/mybatis/spring/nativex/MyBatisMapperNativeConfigurationProcessor.java @@ -15,19 +15,6 @@ */ package org.mybatis.spring.nativex; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_METHODS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_METHODS; -import static org.springframework.nativex.hint.TypeAccess.QUERY_DECLARED_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.QUERY_DECLARED_METHODS; -import static org.springframework.nativex.hint.TypeAccess.QUERY_PUBLIC_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.QUERY_PUBLIC_METHODS; - import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.function.Function; @@ -37,14 +24,14 @@ import org.apache.ibatis.annotations.SelectProvider; import org.apache.ibatis.annotations.UpdateProvider; import org.mybatis.spring.mapper.MapperFactoryBean; -import org.springframework.aot.context.bootstrap.generator.infrastructure.nativex.BeanFactoryNativeConfigurationProcessor; -import org.springframework.aot.context.bootstrap.generator.infrastructure.nativex.NativeConfigurationRegistry; -import org.springframework.aot.context.bootstrap.generator.infrastructure.nativex.NativeProxyEntry; -import org.springframework.aot.context.bootstrap.generator.infrastructure.nativex.NativeResourcesEntry; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; import org.springframework.beans.PropertyValue; +import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution; +import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.nativex.hint.TypeAccess; +import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; @@ -54,69 +41,84 @@ * @author Kazuki Shimizu * @author Josh Long */ -public class MyBatisMapperNativeConfigurationProcessor implements BeanFactoryNativeConfigurationProcessor { +public class MyBatisMapperNativeConfigurationProcessor implements BeanFactoryInitializationAotProcessor { private static final String MAPPER_FACTORY_BEAN = "org.mybatis.spring.mapper.MapperFactoryBean"; - private static final TypeAccess[] TYPE_ACCESSES = { PUBLIC_CONSTRUCTORS, PUBLIC_CLASSES, PUBLIC_FIELDS, - PUBLIC_METHODS, DECLARED_CLASSES, DECLARED_CONSTRUCTORS, DECLARED_FIELDS, DECLARED_METHODS, - QUERY_DECLARED_METHODS, QUERY_PUBLIC_METHODS, QUERY_DECLARED_CONSTRUCTORS, QUERY_PUBLIC_CONSTRUCTORS }; + private static final MemberCategory[] MEMBER_CATEGORIES = { MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS, + MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS, + MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES }; /** * {@inheritDoc} */ @Override - public void process(ConfigurableListableBeanFactory beanFactory, NativeConfigurationRegistry registry) { + public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) { if (!ClassUtils.isPresent(MAPPER_FACTORY_BEAN, beanFactory.getBeanClassLoader())) { - return; + return null; } String[] beanNames = beanFactory.getBeanNamesForType(MapperFactoryBean.class); + if (beanNames.length == 0) { + return null; + } for (String beanName : beanNames) { - BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName.substring(1)); - PropertyValue mapperInterface = beanDefinition.getPropertyValues().getPropertyValue("mapperInterface"); - if (mapperInterface != null && mapperInterface.getValue() != null) { - Class mapperInterfaceType = (Class) mapperInterface.getValue(); - if (mapperInterfaceType != null) { - registerReflectionTypeIfNecessary(mapperInterfaceType, registry); - registry.proxy().add(NativeProxyEntry.ofInterfaces(mapperInterfaceType)); - registry.resources() - .add(NativeResourcesEntry.of(mapperInterfaceType.getName().replace('.', '/').concat(".xml"))); - registerMapperRelationships(mapperInterfaceType, registry); - } + BeanDefinition beanDefinition = beanFactory + .getBeanDefinition(beanName.startsWith("&") ? beanName.substring(1) : beanName); + ConstructorArgumentValues constructorArgumentValues = beanDefinition.getConstructorArgumentValues(); + if (!constructorArgumentValues.isEmpty()) { + constructorArgumentValues.clear(); } } + return (generationContext, beanFactoryInitializationCode) -> { + RuntimeHints hints = generationContext.getRuntimeHints(); + for (String beanName : beanNames) { + BeanDefinition beanDefinition = beanFactory + .getBeanDefinition(beanName.startsWith("&") ? beanName.substring(1) : beanName); + PropertyValue mapperInterface = beanDefinition.getPropertyValues().getPropertyValue("mapperInterface"); + if (mapperInterface != null && mapperInterface.getValue() != null) { + Class mapperInterfaceType = (Class) mapperInterface.getValue(); + if (mapperInterfaceType != null) { + registerReflectionTypeIfNecessary(mapperInterfaceType, hints); + hints.proxies().registerJdkProxy(mapperInterfaceType); + hints.resources().registerPattern(mapperInterfaceType.getName().replace('.', '/').concat(".xml")); + registerMapperRelationships(mapperInterfaceType, hints); + } + } + } + }; } - private void registerMapperRelationships(Class mapperInterfaceType, NativeConfigurationRegistry registry) { + private void registerMapperRelationships(Class mapperInterfaceType, RuntimeHints hints) { Method[] methods = ReflectionUtils.getAllDeclaredMethods(mapperInterfaceType); for (Method method : methods) { if (method.getDeclaringClass() != Object.class) { ReflectionUtils.makeAccessible(method); - registerSqlProviderTypes(method, registry, SelectProvider.class, SelectProvider::value, SelectProvider::type); - registerSqlProviderTypes(method, registry, InsertProvider.class, InsertProvider::value, InsertProvider::type); - registerSqlProviderTypes(method, registry, UpdateProvider.class, UpdateProvider::value, UpdateProvider::type); - registerSqlProviderTypes(method, registry, DeleteProvider.class, DeleteProvider::value, DeleteProvider::type); + registerSqlProviderTypes(method, hints, SelectProvider.class, SelectProvider::value, SelectProvider::type); + registerSqlProviderTypes(method, hints, InsertProvider.class, InsertProvider::value, InsertProvider::type); + registerSqlProviderTypes(method, hints, UpdateProvider.class, UpdateProvider::value, UpdateProvider::type); + registerSqlProviderTypes(method, hints, DeleteProvider.class, DeleteProvider::value, DeleteProvider::type); Class returnType = MyBatisMapperTypeUtils.resolveReturnClass(mapperInterfaceType, method); - registerReflectionTypeIfNecessary(returnType, registry); + registerReflectionTypeIfNecessary(returnType, hints); MyBatisMapperTypeUtils.resolveParameterClasses(mapperInterfaceType, method) - .forEach(x -> registerReflectionTypeIfNecessary(x, registry)); + .forEach(x -> registerReflectionTypeIfNecessary(x, hints)); } } } @SafeVarargs - private final void registerSqlProviderTypes(Method method, - NativeConfigurationRegistry registry, Class annotationType, Function>... providerTypeResolvers) { + private final void registerSqlProviderTypes(Method method, RuntimeHints hints, + Class annotationType, Function>... providerTypeResolvers) { for (T annotation : method.getAnnotationsByType(annotationType)) { for (Function> providerTypeResolver : providerTypeResolvers) { - registerReflectionTypeIfNecessary(providerTypeResolver.apply(annotation), registry); + registerReflectionTypeIfNecessary(providerTypeResolver.apply(annotation), hints); } } } - private void registerReflectionTypeIfNecessary(Class type, NativeConfigurationRegistry registry) { + private void registerReflectionTypeIfNecessary(Class type, RuntimeHints hints) { if (!type.isPrimitive() && !type.getName().startsWith("java")) { - registry.reflection().forType(type).withAccess(TYPE_ACCESSES); + hints.reflection().registerType(type, MEMBER_CATEGORIES); } } diff --git a/core/src/main/java/org/mybatis/spring/nativex/MyBatisResourcesScan.java b/core/src/main/java/org/mybatis/spring/nativex/MyBatisResourcesScan.java index 7806f35..5615331 100644 --- a/core/src/main/java/org/mybatis/spring/nativex/MyBatisResourcesScan.java +++ b/core/src/main/java/org/mybatis/spring/nativex/MyBatisResourcesScan.java @@ -19,8 +19,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import org.springframework.aot.hint.MemberCategory; import org.springframework.context.annotation.Import; -import org.springframework.nativex.hint.TypeAccess; /** * The annotation that indicates scan rules of resources for running on native-image. @@ -102,7 +102,7 @@ * * @return access scopes for applying scanned classes to reflection hint */ - TypeAccess[] typeAccesses() default {}; + MemberCategory[] typeAccesses() default {}; /** * Return location patterns for adding resource hint file under classpath. diff --git a/core/src/main/java/org/mybatis/spring/nativex/MyBatisScannedResourcesHolder.java b/core/src/main/java/org/mybatis/spring/nativex/MyBatisScannedResourcesHolder.java index c1ad9ab..a0726e2 100644 --- a/core/src/main/java/org/mybatis/spring/nativex/MyBatisScannedResourcesHolder.java +++ b/core/src/main/java/org/mybatis/spring/nativex/MyBatisScannedResourcesHolder.java @@ -30,6 +30,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.ibatis.type.TypeHandler; +import org.springframework.aot.hint.MemberCategory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; @@ -44,7 +45,6 @@ import org.springframework.core.type.ClassMetadata; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReaderFactory; -import org.springframework.nativex.hint.TypeAccess; import org.springframework.util.ClassUtils; /** @@ -58,7 +58,7 @@ public class MyBatisScannedResourcesHolder { private Set> typeHandlerClasses; private Set mapperLocations; private Set> reflectionClasses; - private TypeAccess[] reflectionTypeAccesses; + private MemberCategory[] reflectionTypeAccesses; private Set resourceLocations; /** @@ -148,7 +148,7 @@ public Set> getReflectionClasses() { * access scopes for applying reflection type that scanned */ @SuppressWarnings("unused") - public void setReflectionTypeAccesses(TypeAccess[] reflectionTypeAccesses) { + public void setReflectionTypeAccesses(MemberCategory[] reflectionTypeAccesses) { this.reflectionTypeAccesses = reflectionTypeAccesses; } @@ -157,7 +157,7 @@ public void setReflectionTypeAccesses(TypeAccess[] reflectionTypeAccesses) { * * @return access scopes for applying reflection type that scanned */ - public TypeAccess[] getReflectionTypeAccesses() { + public MemberCategory[] getReflectionTypeAccesses() { return reflectionTypeAccesses; } @@ -183,7 +183,9 @@ public Set getResourceLocations() { static class Registrar implements ImportBeanDefinitionRegistrar { private static final Log LOG = LogFactory.getLog(Registrar.class); - private static final ResourcePatternResolver RESOURCE_PATTERN_RESOLVER = new PathMatchingResourcePatternResolver(); + // Instance field (not static) to avoid URL caching in PathMatchingResourcePatternResolver + // when used across multiple application contexts (relevant since Spring Framework 6.x) + private final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); private static final MetadataReaderFactory METADATA_READER_FACTORY = new CachingMetadataReaderFactory(); private static final Pattern JAR_RESOURCE_PREFIX_PATTERN = Pattern.compile(".*\\.jar!/"); private static final boolean PRESENT_TYPE_HANDLER = ClassUtils.isPresent("org.apache.ibatis.type.TypeHandler", @@ -238,7 +240,7 @@ protected void registerBeanDefinitions(AnnotationAttributes annoAttrs, BeanDefin private Set> scanClasses(String[] packagePatterns, Class assignableType) throws IOException { Set> classes = new HashSet<>(); for (String packagePattern : packagePatterns) { - Resource[] resources = RESOURCE_PATTERN_RESOLVER.getResources(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + Resource[] resources = resourcePatternResolver.getResources(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(packagePattern) + "/**/*.class"); for (Resource resource : resources) { try { @@ -267,7 +269,7 @@ private Set scanResources(String[] mapperLocationPatterns) { private Resource[] getResources(String locationPattern) { try { - return RESOURCE_PATTERN_RESOLVER.getResources(locationPattern); + return resourcePatternResolver.getResources(locationPattern); } catch (IOException e) { LOG.debug("Fail getting resources. locationPattern: " + locationPattern, e); return new Resource[0]; @@ -297,7 +299,7 @@ private String determineRelativePath(Resource resource) throws IOException { for (int i = path.getNameCount() - 1; i >= 0; i--) { sb.insert(0, path.getName(i)); String relativePath = sb.toString(); - if (RESOURCE_PATTERN_RESOLVER.getResource(relativePath).exists()) { + if (resourcePatternResolver.getResource(relativePath).exists()) { return relativePath; } sb.insert(0, '/'); diff --git a/core/src/main/java/org/mybatis/spring/nativex/MyBatisScannedResourcesNativeConfigurationProcessor.java b/core/src/main/java/org/mybatis/spring/nativex/MyBatisScannedResourcesNativeConfigurationProcessor.java index 23c7bd2..2c7367c 100644 --- a/core/src/main/java/org/mybatis/spring/nativex/MyBatisScannedResourcesNativeConfigurationProcessor.java +++ b/core/src/main/java/org/mybatis/spring/nativex/MyBatisScannedResourcesNativeConfigurationProcessor.java @@ -15,65 +15,60 @@ */ package org.mybatis.spring.nativex; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_METHODS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_METHODS; -import static org.springframework.nativex.hint.TypeAccess.QUERY_DECLARED_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.QUERY_DECLARED_METHODS; -import static org.springframework.nativex.hint.TypeAccess.QUERY_PUBLIC_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.QUERY_PUBLIC_METHODS; - import java.util.Collections; import java.util.Optional; import java.util.Set; -import org.springframework.aot.context.bootstrap.generator.infrastructure.nativex.BeanFactoryNativeConfigurationProcessor; -import org.springframework.aot.context.bootstrap.generator.infrastructure.nativex.NativeConfigurationRegistry; -import org.springframework.aot.context.bootstrap.generator.infrastructure.nativex.NativeResourcesEntry; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; import org.springframework.beans.PropertyValue; +import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution; +import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.nativex.hint.TypeAccess; /** * Finds and registers reflection and resource hints for all MyBatisScannedResourcesHolder in the {@code BeanFactory}. * * @author Kazuki Shimizu */ -public class MyBatisScannedResourcesNativeConfigurationProcessor implements BeanFactoryNativeConfigurationProcessor { +public class MyBatisScannedResourcesNativeConfigurationProcessor implements BeanFactoryInitializationAotProcessor { - private static final TypeAccess[] DEFAULT_TYPE_ACCESSES = { PUBLIC_CONSTRUCTORS, PUBLIC_CLASSES, PUBLIC_FIELDS, - PUBLIC_METHODS, DECLARED_CLASSES, DECLARED_CONSTRUCTORS, DECLARED_FIELDS, DECLARED_METHODS, - QUERY_DECLARED_METHODS, QUERY_PUBLIC_METHODS, QUERY_DECLARED_CONSTRUCTORS, QUERY_PUBLIC_CONSTRUCTORS }; + private static final MemberCategory[] DEFAULT_MEMBER_CATEGORIES = { MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS, + MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS, + MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES }; /** * {@inheritDoc} */ @Override - public void process(ConfigurableListableBeanFactory beanFactory, NativeConfigurationRegistry registry) { + public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) { String[] beanNames = beanFactory.getBeanNamesForType(MyBatisScannedResourcesHolder.class); - for (String beanName : beanNames) { - BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); - @SuppressWarnings("unchecked") - Set resourceLocations = (Set) Optional - .ofNullable(beanDefinition.getPropertyValues().getPropertyValue("resourceLocations")) - .map(PropertyValue::getValue).orElse(Collections.emptySet()); - resourceLocations.forEach(x -> registry.resources().add(NativeResourcesEntry.of(x))); - @SuppressWarnings("unchecked") - Set> reflectionClasses = (Set>) Optional - .ofNullable(beanDefinition.getPropertyValues().getPropertyValue("reflectionClasses")) - .map(PropertyValue::getValue).orElse(Collections.emptySet()); - TypeAccess[] reflectionTypeAccesses = (TypeAccess[]) Optional - .ofNullable(beanDefinition.getPropertyValues().getPropertyValue("reflectionTypeAccesses")) - .map(PropertyValue::getValue).orElse(DEFAULT_TYPE_ACCESSES); - reflectionClasses.forEach(x -> registry.reflection().forType(x) - .withAccess(reflectionTypeAccesses.length == 0 ? DEFAULT_TYPE_ACCESSES : reflectionTypeAccesses).build()); + if (beanNames.length == 0) { + return null; } + return (generationContext, beanFactoryInitializationCode) -> { + RuntimeHints hints = generationContext.getRuntimeHints(); + for (String beanName : beanNames) { + BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); + @SuppressWarnings("unchecked") + Set resourceLocations = (Set) Optional + .ofNullable(beanDefinition.getPropertyValues().getPropertyValue("resourceLocations")) + .map(PropertyValue::getValue).orElse(Collections.emptySet()); + resourceLocations.forEach(hints.resources()::registerPattern); + @SuppressWarnings("unchecked") + Set> reflectionClasses = (Set>) Optional + .ofNullable(beanDefinition.getPropertyValues().getPropertyValue("reflectionClasses")) + .map(PropertyValue::getValue).orElse(Collections.emptySet()); + MemberCategory[] memberCategories = (MemberCategory[]) Optional + .ofNullable(beanDefinition.getPropertyValues().getPropertyValue("reflectionTypeAccesses")) + .map(PropertyValue::getValue).orElse(DEFAULT_MEMBER_CATEGORIES); + MemberCategory[] effectiveCategories = (memberCategories.length == 0) ? DEFAULT_MEMBER_CATEGORIES + : memberCategories; + reflectionClasses.forEach(x -> hints.reflection().registerType(x, effectiveCategories)); + } + }; } } diff --git a/core/src/main/java/org/mybatis/spring/nativex/MyBatisSpringNativeConfiguration.java b/core/src/main/java/org/mybatis/spring/nativex/MyBatisSpringNativeConfiguration.java index 297b6b0..1d24afc 100644 --- a/core/src/main/java/org/mybatis/spring/nativex/MyBatisSpringNativeConfiguration.java +++ b/core/src/main/java/org/mybatis/spring/nativex/MyBatisSpringNativeConfiguration.java @@ -15,47 +15,31 @@ */ package org.mybatis.spring.nativex; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_METHODS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_METHODS; - import org.mybatis.spring.SqlSessionFactoryBean; -import org.mybatis.spring.SqlSessionTemplate; -import org.springframework.nativex.hint.NativeHint; -import org.springframework.nativex.hint.ResourceHint; -import org.springframework.nativex.hint.TypeHint; -import org.springframework.nativex.type.NativeConfiguration; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.util.ClassUtils; /** * Registers hints to make a MyBatis Spring component work in a Spring Native context. * * @author Kazuki Shimizu */ -// @formatter:off -@NativeHint( - trigger = SqlSessionTemplate.class, - resources = @ResourceHint( - patterns = "org/mybatis/spring/config/.*.xsd" - ) -) -@TypeHint( - types = SqlSessionFactoryBean.class, - access = { - PUBLIC_CONSTRUCTORS, - PUBLIC_CLASSES, - PUBLIC_FIELDS, - PUBLIC_METHODS, - DECLARED_CLASSES, - DECLARED_CONSTRUCTORS, - DECLARED_FIELDS, - DECLARED_METHODS +public class MyBatisSpringNativeConfiguration implements RuntimeHintsRegistrar { + + private static final MemberCategory[] MEMBER_CATEGORIES = { MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS, + MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS, + MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES }; + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + if (!ClassUtils.isPresent("org.mybatis.spring.SqlSessionTemplate", classLoader)) { + return; } -) -// @formatter:on -public class MyBatisSpringNativeConfiguration implements NativeConfiguration { + hints.reflection().registerType(SqlSessionFactoryBean.class, MEMBER_CATEGORIES); + hints.resources().registerPattern("org/mybatis/spring/config/*.xsd"); + } + } diff --git a/core/src/main/java/org/mybatis/spring/nativex/autoconfigure/MyBatisSpringNativeAutoConfiguration.java b/core/src/main/java/org/mybatis/spring/nativex/autoconfigure/MyBatisSpringNativeAutoConfiguration.java index afac990..bf0a2f0 100644 --- a/core/src/main/java/org/mybatis/spring/nativex/autoconfigure/MyBatisSpringNativeAutoConfiguration.java +++ b/core/src/main/java/org/mybatis/spring/nativex/autoconfigure/MyBatisSpringNativeAutoConfiguration.java @@ -20,7 +20,9 @@ import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer; import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration; import org.mybatis.spring.boot.autoconfigure.SqlSessionFactoryBeanCustomizer; +import org.mybatis.spring.mapper.MapperFactoryBean; import org.mybatis.spring.nativex.MyBatisScannedResourcesHolder; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -62,4 +64,15 @@ SqlSessionFactoryBeanCustomizer mybatisScannedResourcesHolderSqlSessionFactoryBe }; } + @Bean + static BeanFactoryPostProcessor mybatisMapperFactoryBeanDefinitionPostProcessor() { + return beanFactory -> { + String[] beanNames = beanFactory.getBeanNamesForType(MapperFactoryBean.class); + for (String beanName : beanNames) { + beanFactory.getBeanDefinition(beanName.startsWith("&") ? beanName.substring(1) : beanName) + .getConstructorArgumentValues().clear(); + } + }; + } + } diff --git a/core/src/main/resources/META-INF/native-image/org.mybatis.spring.native/mybatis-spring-native-core/reflect-config.json b/core/src/main/resources/META-INF/native-image/org.mybatis.spring.native/mybatis-spring-native-core/reflect-config.json new file mode 100644 index 0000000..b2ebe5f --- /dev/null +++ b/core/src/main/resources/META-INF/native-image/org.mybatis.spring.native/mybatis-spring-native-core/reflect-config.json @@ -0,0 +1,37 @@ +[ + { + "name": "org.apache.ibatis.logging.slf4j.Slf4jImpl", + "allDeclaredConstructors": true, + "allDeclaredMethods": true + }, + { + "name": "org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl", + "allDeclaredConstructors": true, + "allDeclaredMethods": true + }, + { + "name": "org.apache.ibatis.logging.log4j2.Log4j2Impl", + "allDeclaredConstructors": true, + "allDeclaredMethods": true + }, + { + "name": "org.apache.ibatis.logging.log4j.Log4jImpl", + "allDeclaredConstructors": true, + "allDeclaredMethods": true + }, + { + "name": "org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl", + "allDeclaredConstructors": true, + "allDeclaredMethods": true + }, + { + "name": "org.apache.ibatis.logging.nologging.NoLoggingImpl", + "allDeclaredConstructors": true, + "allDeclaredMethods": true + }, + { + "name": "org.apache.ibatis.logging.stdout.StdOutImpl", + "allDeclaredConstructors": true, + "allDeclaredMethods": true + } +] diff --git a/core/src/main/resources/META-INF/spring.factories b/core/src/main/resources/META-INF/spring.factories index 911d0e7..fb41395 100644 --- a/core/src/main/resources/META-INF/spring.factories +++ b/core/src/main/resources/META-INF/spring.factories @@ -14,13 +14,5 @@ # limitations under the License. # -org.springframework.aot.context.bootstrap.generator.infrastructure.nativex.BeanFactoryNativeConfigurationProcessor=\ - org.mybatis.spring.nativex.MyBatisMapperNativeConfigurationProcessor,\ - org.mybatis.spring.nativex.MyBatisScannedResourcesNativeConfigurationProcessor -org.springframework.context.annotation.BeanDefinitionPostProcessor=\ - org.mybatis.spring.nativex.MyBatisMapperFactoryBeanPostProcessor -org.springframework.nativex.type.NativeConfiguration=\ - org.mybatis.spring.nativex.MyBatisCoreNativeConfiguration,\ - org.mybatis.spring.nativex.MyBatisSpringNativeConfiguration org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.mybatis.spring.nativex.autoconfigure.MyBatisSpringNativeAutoConfiguration diff --git a/core/src/main/resources/META-INF/spring/aot.factories b/core/src/main/resources/META-INF/spring/aot.factories new file mode 100644 index 0000000..17f7a54 --- /dev/null +++ b/core/src/main/resources/META-INF/spring/aot.factories @@ -0,0 +1,6 @@ +org.springframework.beans.factory.aot.BeanRegistrationAotProcessor=\ +org.mybatis.spring.nativex.MyBatisMapperFactoryBeanPostProcessor + +org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor=\ +org.mybatis.spring.nativex.MyBatisMapperNativeConfigurationProcessor,\ +org.mybatis.spring.nativex.MyBatisScannedResourcesNativeConfigurationProcessor diff --git a/core/src/main/resources/META-INF/spring/org.springframework.aot.hint.RuntimeHintsRegistrar b/core/src/main/resources/META-INF/spring/org.springframework.aot.hint.RuntimeHintsRegistrar new file mode 100644 index 0000000..28dbc85 --- /dev/null +++ b/core/src/main/resources/META-INF/spring/org.springframework.aot.hint.RuntimeHintsRegistrar @@ -0,0 +1,2 @@ +org.mybatis.spring.nativex.MyBatisCoreNativeConfiguration +org.mybatis.spring.nativex.MyBatisSpringNativeConfiguration diff --git a/core/src/main/resources/META-INF/spring/org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor b/core/src/main/resources/META-INF/spring/org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor new file mode 100644 index 0000000..18ac79f --- /dev/null +++ b/core/src/main/resources/META-INF/spring/org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor @@ -0,0 +1,2 @@ +org.mybatis.spring.nativex.MyBatisMapperNativeConfigurationProcessor +org.mybatis.spring.nativex.MyBatisScannedResourcesNativeConfigurationProcessor diff --git a/core/src/main/resources/META-INF/spring/org.springframework.beans.factory.aot.BeanRegistrationAotProcessor b/core/src/main/resources/META-INF/spring/org.springframework.beans.factory.aot.BeanRegistrationAotProcessor new file mode 100644 index 0000000..5654ad5 --- /dev/null +++ b/core/src/main/resources/META-INF/spring/org.springframework.beans.factory.aot.BeanRegistrationAotProcessor @@ -0,0 +1 @@ +org.mybatis.spring.nativex.MyBatisMapperFactoryBeanPostProcessor diff --git a/core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..81215fa --- /dev/null +++ b/core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.mybatis.spring.nativex.autoconfigure.MyBatisSpringNativeAutoConfiguration diff --git a/core/src/test/java/org/mybatis/spring/nativex/MyBatisMapperFactoryBeanPostProcessorTest.java b/core/src/test/java/org/mybatis/spring/nativex/MyBatisMapperFactoryBeanPostProcessorTest.java index 8ef4c55..0def189 100644 --- a/core/src/test/java/org/mybatis/spring/nativex/MyBatisMapperFactoryBeanPostProcessorTest.java +++ b/core/src/test/java/org/mybatis/spring/nativex/MyBatisMapperFactoryBeanPostProcessorTest.java @@ -15,12 +15,16 @@ */ package org.mybatis.spring.nativex; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.mybatis.spring.mapper.MapperFactoryBean; import org.mybatis.spring.nativex.mapper.SampleMapper; import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RootBeanDefinition; /** @@ -36,20 +40,41 @@ void resolveMapperInterfaceType() { .rootBeanDefinition(MapperFactoryBean.class).addPropertyValue("mapperInterface", SampleMapper.class) .getBeanDefinition(); Assertions.assertThat(beanDefinition.getResolvableType().hasUnresolvableGenerics()).isTrue(); - postProcess(beanDefinition); + postProcess(MapperFactoryBean.class, beanDefinition); Assertions.assertThat(beanDefinition.getResolvableType().hasUnresolvableGenerics()).isFalse(); Assertions.assertThat(beanDefinition.getTargetType()).isEqualTo(MapperFactoryBean.class); Assertions.assertThat(beanDefinition.getResolvableType().getGenerics()).hasSize(1); Assertions.assertThat(beanDefinition.getResolvableType().getGenerics()[0].toClass()).isEqualTo(SampleMapper.class); } + @Test + void clearConstructorArgumentsWhenHasGenericConstructorArgument() { + RootBeanDefinition beanDefinition = (RootBeanDefinition) BeanDefinitionBuilder + .rootBeanDefinition(MapperFactoryBean.class).addConstructorArgValue(SampleMapper.class.getName()) + .addPropertyValue("mapperInterface", SampleMapper.class).getBeanDefinition(); + Assertions.assertThat(beanDefinition.getConstructorArgumentValues().getArgumentCount()).isEqualTo(1); + postProcess(MapperFactoryBean.class, beanDefinition); + Assertions.assertThat(beanDefinition.getConstructorArgumentValues().isEmpty()).isTrue(); + } + + @Test + void clearConstructorArgumentsWhenHasIndexedConstructorArgument() { + RootBeanDefinition beanDefinition = (RootBeanDefinition) BeanDefinitionBuilder + .rootBeanDefinition(MapperFactoryBean.class).addConstructorArgValue(SampleMapper.class.getName()) + .addPropertyValue("mapperInterface", SampleMapper.class).getBeanDefinition(); + beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(1, "sampleMapperClass"); + Assertions.assertThat(beanDefinition.getConstructorArgumentValues().getArgumentCount()).isEqualTo(2); + postProcess(MapperFactoryBean.class, beanDefinition); + Assertions.assertThat(beanDefinition.getConstructorArgumentValues().isEmpty()).isTrue(); + } + @Test void resolveMapperInterfaceTypeWhenMapperFactoryBeanSubclassWithOneGeneric() { RootBeanDefinition beanDefinition = (RootBeanDefinition) BeanDefinitionBuilder .rootBeanDefinition(MapperFactoryBean2.class).addPropertyValue("mapperInterface", SampleMapper.class) .getBeanDefinition(); Assertions.assertThat(beanDefinition.getResolvableType().hasUnresolvableGenerics()).isTrue(); - postProcess(beanDefinition); + postProcess(MapperFactoryBean2.class, beanDefinition); Assertions.assertThat(beanDefinition.getResolvableType().hasUnresolvableGenerics()).isFalse(); Assertions.assertThat(beanDefinition.getTargetType()).isEqualTo(MapperFactoryBean2.class); Assertions.assertThat(beanDefinition.getResolvableType().getGenerics()).hasSize(1); @@ -62,19 +87,21 @@ void resolveMapperInterfaceTypeWhenMapperFactoryBeanSubclassWithoutGeneric() { .rootBeanDefinition(SampleMapperFactoryBean.class).addPropertyValue("mapperInterface", SampleMapper.class) .getBeanDefinition(); Assertions.assertThat(beanDefinition.getResolvableType().hasUnresolvableGenerics()).isFalse(); - postProcess(beanDefinition); + postProcess(SampleMapperFactoryBean.class, beanDefinition); Assertions.assertThat(beanDefinition.getResolvableType().hasUnresolvableGenerics()).isFalse(); } - // TODO Now this case is limitation using MapperFactoryBean's subclass + // With BeanRegistrationAotProcessor, the processAheadOfTime method catches and ignores exceptions + // during type resolution (unlike the old BeanDefinitionPostProcessor which propagated them). @Test - void failResolveMapperInterfaceTypeWhenMapperFactoryBeanSubclassWithMultiGenerics() { + void skipResolveMapperInterfaceTypeWhenMapperFactoryBeanSubclassWithMultiGenerics() { RootBeanDefinition beanDefinition = (RootBeanDefinition) BeanDefinitionBuilder .rootBeanDefinition(MapperFactoryBean3.class).addPropertyValue("mapperInterface", SampleMapper.class) .getBeanDefinition(); Assertions.assertThat(beanDefinition.getResolvableType().hasUnresolvableGenerics()).isTrue(); - Assertions.assertThatIllegalArgumentException().isThrownBy(() -> postProcess(beanDefinition)).withMessage( - "Mismatched number of generics specified for private static class org.mybatis.spring.nativex.MyBatisMapperFactoryBeanPostProcessorTest$MapperFactoryBean3"); + postProcess(MapperFactoryBean3.class, beanDefinition); + // exception is caught and ignored, target type remains unset + Assertions.assertThat(beanDefinition.getTargetType()).isNull(); } @Test @@ -82,7 +109,7 @@ void skipResolveMapperInterfaceTypeWhenNotPresentMapperInterface() { RootBeanDefinition beanDefinition = (RootBeanDefinition) BeanDefinitionBuilder .rootBeanDefinition(MapperFactoryBean.class).getBeanDefinition(); Assertions.assertThat(beanDefinition.getResolvableType().hasUnresolvableGenerics()).isTrue(); - postProcess(beanDefinition); + postProcess(MapperFactoryBean.class, beanDefinition); Assertions.assertThat(beanDefinition.getResolvableType().hasUnresolvableGenerics()).isTrue(); Assertions.assertThat(beanDefinition.getTargetType()).isNull(); } @@ -93,32 +120,24 @@ void skipResolveMapperInterfaceTypeWhenFailGetMapperInterface() { .rootBeanDefinition(MapperFactoryBean.class).addPropertyValue("mapperInterface", "invalid value") .getBeanDefinition(); Assertions.assertThat(beanDefinition.getResolvableType().hasUnresolvableGenerics()).isTrue(); - postProcess(beanDefinition); + postProcess(MapperFactoryBean.class, beanDefinition); Assertions.assertThat(beanDefinition.getResolvableType().hasUnresolvableGenerics()).isTrue(); Assertions.assertThat(beanDefinition.getTargetType()).isNull(); } - @Test - void skipResolveMapperInterfaceTypeWhenNotPresentBeanClass() { - RootBeanDefinition beanDefinition = (RootBeanDefinition) BeanDefinitionBuilder.rootBeanDefinition((Class) null) - .getBeanDefinition(); - postProcess(beanDefinition); - Assertions.assertThat(beanDefinition.getTargetType()).isNull(); - } - @Test void skipResolveMapperInterfaceTypeWhenBeanClassNotMapperBeanFactory() { RootBeanDefinition beanDefinition = (RootBeanDefinition) BeanDefinitionBuilder.rootBeanDefinition(String.class) .getBeanDefinition(); - postProcess(beanDefinition); + postProcess(String.class, beanDefinition); Assertions.assertThat(beanDefinition.getTargetType()).isNull(); } - private void postProcess(RootBeanDefinition beanDefinition) { - DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); - MyBatisMapperFactoryBeanPostProcessor processor = new MyBatisMapperFactoryBeanPostProcessor(); - processor.setBeanFactory(beanFactory); - processor.postProcessBeanDefinition("testBean", beanDefinition); + private void postProcess(Class beanClass, RootBeanDefinition beanDefinition) { + RegisteredBean registeredBean = mock(RegisteredBean.class); + doReturn(beanClass).when(registeredBean).getBeanClass(); + when(registeredBean.getMergedBeanDefinition()).thenReturn(beanDefinition); + new MyBatisMapperFactoryBeanPostProcessor().processAheadOfTime(registeredBean); } private static class MapperFactoryBean2 extends MapperFactoryBean { diff --git a/core/src/test/java/org/mybatis/spring/nativex/MyBatisMapperNativeConfigurationProcessorTest.java b/core/src/test/java/org/mybatis/spring/nativex/MyBatisMapperNativeConfigurationProcessorTest.java index 414ea54..0f65385 100644 --- a/core/src/test/java/org/mybatis/spring/nativex/MyBatisMapperNativeConfigurationProcessorTest.java +++ b/core/src/test/java/org/mybatis/spring/nativex/MyBatisMapperNativeConfigurationProcessorTest.java @@ -15,40 +15,24 @@ */ package org.mybatis.spring.nativex; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_METHODS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_METHODS; -import static org.springframework.nativex.hint.TypeAccess.QUERY_DECLARED_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.QUERY_DECLARED_METHODS; -import static org.springframework.nativex.hint.TypeAccess.QUERY_PUBLIC_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.QUERY_PUBLIC_METHODS; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.mybatis.spring.mapper.MapperFactoryBean; import org.mybatis.spring.nativex.mapper.Sample2Mapper; import org.mybatis.spring.nativex.mapper.Sample3Mapper; import org.mybatis.spring.nativex.mapper.SampleMapper; -import org.springframework.aot.context.bootstrap.generator.infrastructure.nativex.DefaultNativeReflectionEntry; -import org.springframework.aot.context.bootstrap.generator.infrastructure.nativex.NativeConfigurationRegistry; -import org.springframework.aot.context.bootstrap.generator.infrastructure.nativex.NativeProxyEntry; +import org.springframework.aot.generate.GenerationContext; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; +import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution; +import org.springframework.beans.factory.aot.BeanFactoryInitializationCode; import org.springframework.beans.factory.config.RuntimeBeanNameReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.nativex.domain.proxies.JdkProxyDescriptor; -import org.springframework.nativex.domain.proxies.ProxiesDescriptor; -import org.springframework.nativex.hint.TypeAccess; /** * Test cases for {@link MyBatisMapperNativeConfigurationProcessor}. @@ -57,9 +41,10 @@ */ class MyBatisMapperNativeConfigurationProcessorTest { - private static final TypeAccess[] TYPE_ACCESSES = { PUBLIC_CONSTRUCTORS, PUBLIC_CLASSES, PUBLIC_FIELDS, - PUBLIC_METHODS, DECLARED_CLASSES, DECLARED_CONSTRUCTORS, DECLARED_FIELDS, DECLARED_METHODS, - QUERY_DECLARED_METHODS, QUERY_PUBLIC_METHODS, QUERY_DECLARED_CONSTRUCTORS, QUERY_PUBLIC_CONSTRUCTORS }; + private static final MemberCategory[] MEMBER_CATEGORIES = { MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS, + MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS, + MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES }; @Test @SuppressWarnings("java:S5961") @@ -70,62 +55,62 @@ void registerMapperInterfaceAndRelationships() { .addPropertyValue("mapperInterface", SampleMapper.class) .addPropertyValue("sqlSessionTemplate", new RuntimeBeanNameReference("sqlSessionTemplate")) .getBeanDefinition()); - NativeConfigurationRegistry registry = process(beanFactory); + RuntimeHints hints = process(beanFactory); // reflection hint { - Map, DefaultNativeReflectionEntry> entries = registry.reflection().reflectionEntries() - .collect(Collectors.toMap(DefaultNativeReflectionEntry::getType, x -> x)); - Assertions.assertThat(entries).hasSize(13); - // mapper interface - Assertions.assertThat(entries.get(SampleMapper.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); - // mapper method argument and return type - Assertions.assertThat(entries.get(SampleMapper.Sample.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); - Assertions.assertThat(entries.get(SampleMapper.SampleParam.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); - Assertions.assertThat(entries.get(SampleMapper.Sample2.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); - Assertions.assertThat(entries.get(SampleMapper.Sample2Param.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); - // sql provider - Assertions.assertThat(entries.get(SampleMapper.SelectProviderClass1.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); - Assertions.assertThat(entries.get(SampleMapper.SelectProviderClass2.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); - Assertions.assertThat(entries.get(SampleMapper.InsertProviderClass1.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); - Assertions.assertThat(entries.get(SampleMapper.InsertProviderClass2.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); - Assertions.assertThat(entries.get(SampleMapper.UpdateProviderClass1.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); - Assertions.assertThat(entries.get(SampleMapper.UpdateProviderClass2.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); - Assertions.assertThat(entries.get(SampleMapper.DeleteProviderClass1.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); - Assertions.assertThat(entries.get(SampleMapper.DeleteProviderClass2.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); + assertThat(hints.reflection().typeHints()).hasSize(13); + assertThat(RuntimeHintsPredicates.reflection().onType(SampleMapper.class).withMemberCategories(MEMBER_CATEGORIES)) + .accepts(hints); + assertThat( + RuntimeHintsPredicates.reflection().onType(SampleMapper.Sample.class).withMemberCategories(MEMBER_CATEGORIES)) + .accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(SampleMapper.SampleParam.class) + .withMemberCategories(MEMBER_CATEGORIES)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(SampleMapper.Sample2.class) + .withMemberCategories(MEMBER_CATEGORIES)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(SampleMapper.Sample2Param.class) + .withMemberCategories(MEMBER_CATEGORIES)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(SampleMapper.SelectProviderClass1.class) + .withMemberCategories(MEMBER_CATEGORIES)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(SampleMapper.SelectProviderClass2.class) + .withMemberCategories(MEMBER_CATEGORIES)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(SampleMapper.InsertProviderClass1.class) + .withMemberCategories(MEMBER_CATEGORIES)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(SampleMapper.InsertProviderClass2.class) + .withMemberCategories(MEMBER_CATEGORIES)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(SampleMapper.UpdateProviderClass1.class) + .withMemberCategories(MEMBER_CATEGORIES)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(SampleMapper.UpdateProviderClass2.class) + .withMemberCategories(MEMBER_CATEGORIES)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(SampleMapper.DeleteProviderClass1.class) + .withMemberCategories(MEMBER_CATEGORIES)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(SampleMapper.DeleteProviderClass2.class) + .withMemberCategories(MEMBER_CATEGORIES)).accepts(hints); } // proxy hint { - List entries = new ArrayList<>(registry.proxy().getEntries()); - Assertions.assertThat(entries).hasSize(1); - ProxiesDescriptor proxiesDescriptor = new ProxiesDescriptor(); - entries.forEach(x -> x.contribute(proxiesDescriptor)); - List jdkProxyDescriptors = new ArrayList<>(proxiesDescriptor.getProxyDescriptors()); - Assertions.assertThat(jdkProxyDescriptors).hasSize(1); - Assertions.assertThat(jdkProxyDescriptors.get(0)).satisfies(x -> { - Assertions.assertThat(x.isClassProxy()).isFalse(); - Assertions.assertThat(x.getTypes()).containsExactlyInAnyOrder("org.mybatis.spring.nativex.mapper.SampleMapper"); - }); + assertThat(hints.proxies().jdkProxyHints()).hasSize(1); + assertThat(RuntimeHintsPredicates.proxies().forInterfaces(SampleMapper.class)).accepts(hints); } // resource hint { - Set resources = registry.resources().toResourcesDescriptor().getPatterns(); - Assertions.assertThat(resources).containsExactlyInAnyOrder("org/mybatis/spring/nativex/mapper/SampleMapper.xml"); + assertThat(RuntimeHintsPredicates.resource().forResource("org/mybatis/spring/nativex/mapper/SampleMapper.xml")) + .accepts(hints); } } + @Test + void clearConstructorArgumentsForMapperFactoryBean() { + DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + beanFactory.registerBeanDefinition("sampleMapper", BeanDefinitionBuilder.rootBeanDefinition(MapperFactoryBean.class) + .addConstructorArgValue(SampleMapper.class.getName()).addPropertyValue("mapperInterface", SampleMapper.class) + .addPropertyValue("sqlSessionTemplate", new RuntimeBeanNameReference("sqlSessionTemplate")) + .getBeanDefinition()); + RuntimeHints hints = process(beanFactory); + assertThat(hints.reflection().typeHints()).isNotEmpty(); + assertThat(beanFactory.getBeanDefinition("sampleMapper").getConstructorArgumentValues().isEmpty()).isTrue(); + } + @Test void registerMultiMapperInterface() { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); @@ -139,42 +124,29 @@ void registerMultiMapperInterface() { .addPropertyValue("mapperInterface", Sample3Mapper.class) .addPropertyValue("sqlSessionTemplate", new RuntimeBeanNameReference("sqlSessionTemplate")) .getBeanDefinition()); - NativeConfigurationRegistry registry = process(beanFactory); + RuntimeHints hints = process(beanFactory); // reflection hint { - Map, DefaultNativeReflectionEntry> entries = registry.reflection().reflectionEntries() - .collect(Collectors.toMap(DefaultNativeReflectionEntry::getType, x -> x)); - Assertions.assertThat(entries).hasSize(2); - // mapper interface - Assertions.assertThat(entries.get(Sample2Mapper.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); - Assertions.assertThat(entries.get(Sample3Mapper.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); + assertThat(hints.reflection().typeHints()).hasSize(2); + assertThat( + RuntimeHintsPredicates.reflection().onType(Sample2Mapper.class).withMemberCategories(MEMBER_CATEGORIES)) + .accepts(hints); + assertThat( + RuntimeHintsPredicates.reflection().onType(Sample3Mapper.class).withMemberCategories(MEMBER_CATEGORIES)) + .accepts(hints); } // proxy hint { - List entries = new ArrayList<>(registry.proxy().getEntries()); - Assertions.assertThat(entries).hasSize(2); - ProxiesDescriptor proxiesDescriptor = new ProxiesDescriptor(); - entries.forEach(x -> x.contribute(proxiesDescriptor)); - List jdkProxyDescriptors = new ArrayList<>(proxiesDescriptor.getProxyDescriptors()); - Assertions.assertThat(jdkProxyDescriptors).hasSize(2); - Assertions.assertThat(jdkProxyDescriptors.get(0)).satisfies(x -> { - Assertions.assertThat(x.isClassProxy()).isFalse(); - Assertions.assertThat(x.getTypes()) - .containsExactlyInAnyOrder("org.mybatis.spring.nativex.mapper.Sample2Mapper"); - }); - Assertions.assertThat(jdkProxyDescriptors.get(1)).satisfies(x -> { - Assertions.assertThat(x.isClassProxy()).isFalse(); - Assertions.assertThat(x.getTypes()) - .containsExactlyInAnyOrder("org.mybatis.spring.nativex.mapper.Sample3Mapper"); - }); + assertThat(hints.proxies().jdkProxyHints()).hasSize(2); + assertThat(RuntimeHintsPredicates.proxies().forInterfaces(Sample2Mapper.class)).accepts(hints); + assertThat(RuntimeHintsPredicates.proxies().forInterfaces(Sample3Mapper.class)).accepts(hints); } // resource hint { - Set resources = registry.resources().toResourcesDescriptor().getPatterns(); - Assertions.assertThat(resources).containsExactlyInAnyOrder("org/mybatis/spring/nativex/mapper/Sample2Mapper.xml", - "org/mybatis/spring/nativex/mapper/Sample3Mapper.xml"); + assertThat(RuntimeHintsPredicates.resource().forResource("org/mybatis/spring/nativex/mapper/Sample2Mapper.xml")) + .accepts(hints); + assertThat(RuntimeHintsPredicates.resource().forResource("org/mybatis/spring/nativex/mapper/Sample3Mapper.xml")) + .accepts(hints); } } @@ -186,34 +158,23 @@ void registerMapperInterfaceWithMapperFactoryBeanSubclass() { .addPropertyValue("mapperInterface", Sample2Mapper.class) .addPropertyValue("sqlSessionTemplate", new RuntimeBeanNameReference("sqlSessionTemplate")) .getBeanDefinition()); - NativeConfigurationRegistry registry = process(beanFactory); + RuntimeHints hints = process(beanFactory); // reflection hint { - Map, DefaultNativeReflectionEntry> entries = registry.reflection().reflectionEntries() - .collect(Collectors.toMap(DefaultNativeReflectionEntry::getType, x -> x)); - Assertions.assertThat(entries).hasSize(1); - // mapper interface - Assertions.assertThat(entries.get(Sample2Mapper.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(TYPE_ACCESSES)); + assertThat(hints.reflection().typeHints()).hasSize(1); + assertThat( + RuntimeHintsPredicates.reflection().onType(Sample2Mapper.class).withMemberCategories(MEMBER_CATEGORIES)) + .accepts(hints); } // proxy hint { - List entries = new ArrayList<>(registry.proxy().getEntries()); - Assertions.assertThat(entries).hasSize(1); - ProxiesDescriptor proxiesDescriptor = new ProxiesDescriptor(); - entries.forEach(x -> x.contribute(proxiesDescriptor)); - List jdkProxyDescriptors = new ArrayList<>(proxiesDescriptor.getProxyDescriptors()); - Assertions.assertThat(jdkProxyDescriptors).hasSize(1); - Assertions.assertThat(jdkProxyDescriptors.get(0)).satisfies(x -> { - Assertions.assertThat(x.isClassProxy()).isFalse(); - Assertions.assertThat(x.getTypes()) - .containsExactlyInAnyOrder("org.mybatis.spring.nativex.mapper.Sample2Mapper"); - }); + assertThat(hints.proxies().jdkProxyHints()).hasSize(1); + assertThat(RuntimeHintsPredicates.proxies().forInterfaces(Sample2Mapper.class)).accepts(hints); } // resource hint { - Set resources = registry.resources().toResourcesDescriptor().getPatterns(); - Assertions.assertThat(resources).containsExactlyInAnyOrder("org/mybatis/spring/nativex/mapper/Sample2Mapper.xml"); + assertThat(RuntimeHintsPredicates.resource().forResource("org/mybatis/spring/nativex/mapper/Sample2Mapper.xml")) + .accepts(hints); } } @@ -224,19 +185,10 @@ void skipRegisterWhenMapperInterfaceNotPresent() { BeanDefinitionBuilder.rootBeanDefinition(MapperFactoryBean.class) .addPropertyValue("sqlSessionTemplate", new RuntimeBeanNameReference("sqlSessionTemplate")) .getBeanDefinition()); - NativeConfigurationRegistry registry = process(beanFactory); - // reflection hint - { - Assertions.assertThat(registry.reflection().reflectionEntries()).isEmpty(); - } - // proxy hint - { - Assertions.assertThat(registry.proxy().getEntries()).isEmpty(); - } - // resource hint - { - Assertions.assertThat(registry.resources().toResourcesDescriptor().getPatterns()).isEmpty(); - } + RuntimeHints hints = process(beanFactory); + assertThat(hints.reflection().typeHints()).isEmpty(); + assertThat(hints.proxies().jdkProxyHints()).isEmpty(); + assertThat(hints.resources().resourcePatternHints()).isEmpty(); } @Test @@ -246,25 +198,22 @@ void skipRegisterWhenMapperInterfaceIsNull() { BeanDefinitionBuilder.rootBeanDefinition(MapperFactoryBean.class).addPropertyValue("mapperInterface", null) .addPropertyValue("sqlSessionTemplate", new RuntimeBeanNameReference("sqlSessionTemplate")) .getBeanDefinition()); - NativeConfigurationRegistry registry = process(beanFactory); - // reflection hint - { - Assertions.assertThat(registry.reflection().reflectionEntries()).isEmpty(); - } - // proxy hint - { - Assertions.assertThat(registry.proxy().getEntries()).isEmpty(); - } - // resource hint - { - Assertions.assertThat(registry.resources().toResourcesDescriptor().getPatterns()).isEmpty(); - } + RuntimeHints hints = process(beanFactory); + assertThat(hints.reflection().typeHints()).isEmpty(); + assertThat(hints.proxies().jdkProxyHints()).isEmpty(); + assertThat(hints.resources().resourcePatternHints()).isEmpty(); } - private NativeConfigurationRegistry process(DefaultListableBeanFactory beanFactory) { - NativeConfigurationRegistry registry = new NativeConfigurationRegistry(); - new MyBatisMapperNativeConfigurationProcessor().process(beanFactory, registry); - return registry; + private RuntimeHints process(DefaultListableBeanFactory beanFactory) { + RuntimeHints hints = new RuntimeHints(); + GenerationContext generationContext = mock(GenerationContext.class); + when(generationContext.getRuntimeHints()).thenReturn(hints); + BeanFactoryInitializationAotContribution contribution = new MyBatisMapperNativeConfigurationProcessor() + .processAheadOfTime(beanFactory); + if (contribution != null) { + contribution.applyTo(generationContext, mock(BeanFactoryInitializationCode.class)); + } + return hints; } private static class MyMapperFactoryBean extends MapperFactoryBean { diff --git a/core/src/test/java/org/mybatis/spring/nativex/MyBatisResourcesScanTest.java b/core/src/test/java/org/mybatis/spring/nativex/MyBatisResourcesScanTest.java index 4f88932..bc48d0e 100644 --- a/core/src/test/java/org/mybatis/spring/nativex/MyBatisResourcesScanTest.java +++ b/core/src/test/java/org/mybatis/spring/nativex/MyBatisResourcesScanTest.java @@ -35,9 +35,9 @@ import org.mybatis.spring.nativex.entity.City; import org.mybatis.spring.nativex.entity.Country; import org.mybatis.spring.nativex.marker.StandardEntity; +import org.springframework.aot.hint.MemberCategory; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Configuration; -import org.springframework.nativex.hint.TypeAccess; import org.springframework.util.ClassUtils; class MyBatisResourcesScanTest { @@ -149,7 +149,8 @@ void scanReflectionType() { Assertions.assertThat(holder.getTypeHandlerClasses()).isEmpty(); Assertions.assertThat(holder.getReflectionClasses()).containsExactlyInAnyOrder(City.class, Country.class); Assertions.assertThat(holder.getResourceLocations()).isEmpty(); - Assertions.assertThat(holder.getReflectionTypeAccesses()).containsExactlyInAnyOrder(TypeAccess.DECLARED_CLASSES); + Assertions.assertThat(holder.getReflectionTypeAccesses()) + .containsExactlyInAnyOrder(MemberCategory.DECLARED_CLASSES); } @Test @@ -282,12 +283,12 @@ static class ConfigurationForScanMapperLocations { static class ConfigurationForScanMapperLocationsWithMultiPattern { } - @MyBatisResourcesScan(reflectionTypePackages = "org.mybatis.spring.nativex.entity", typeAccesses = TypeAccess.DECLARED_CLASSES) + @MyBatisResourcesScan(reflectionTypePackages = "org.mybatis.spring.nativex.entity", typeAccesses = MemberCategory.DECLARED_CLASSES) @Configuration static class ConfigurationForScanReflectionType { } - @MyBatisResourcesScan(reflectionTypePackages = "org.mybatis.spring.nativex.entity", reflectionTypeSupperType = StandardEntity.class, typeAccesses = TypeAccess.DECLARED_CLASSES) + @MyBatisResourcesScan(reflectionTypePackages = "org.mybatis.spring.nativex.entity", reflectionTypeSupperType = StandardEntity.class, typeAccesses = MemberCategory.DECLARED_CLASSES) @Configuration static class ConfigurationForScanReflectionTypeWithSuperType { } diff --git a/core/src/test/java/org/mybatis/spring/nativex/MyBatisScannedResourcesNativeConfigurationProcessorTest.java b/core/src/test/java/org/mybatis/spring/nativex/MyBatisScannedResourcesNativeConfigurationProcessorTest.java index 4182842..2222b2c 100644 --- a/core/src/test/java/org/mybatis/spring/nativex/MyBatisScannedResourcesNativeConfigurationProcessorTest.java +++ b/core/src/test/java/org/mybatis/spring/nativex/MyBatisScannedResourcesNativeConfigurationProcessorTest.java @@ -15,14 +15,10 @@ */ package org.mybatis.spring.nativex; -import static org.springframework.nativex.hint.TypeAccess.*; -import static org.springframework.nativex.hint.TypeAccess.QUERY_PUBLIC_CONSTRUCTORS; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.mybatis.spring.nativex.component.BarTypeHandler; import org.mybatis.spring.nativex.component.FooTypeHandler; @@ -30,35 +26,30 @@ import org.mybatis.spring.nativex.component2.AnyTypeHandler; import org.mybatis.spring.nativex.entity.City; import org.mybatis.spring.nativex.entity.Country; -import org.springframework.aot.context.bootstrap.generator.infrastructure.nativex.DefaultNativeReflectionEntry; -import org.springframework.aot.context.bootstrap.generator.infrastructure.nativex.NativeConfigurationRegistry; +import org.springframework.aot.generate.GenerationContext; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; +import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution; +import org.springframework.beans.factory.aot.BeanFactoryInitializationCode; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Configuration; -import org.springframework.nativex.hint.TypeAccess; class MyBatisScannedResourcesNativeConfigurationProcessorTest { - private static final TypeAccess[] DEFAULT_TYPE_ACCESSES = { PUBLIC_CONSTRUCTORS, PUBLIC_CLASSES, PUBLIC_FIELDS, - PUBLIC_METHODS, DECLARED_CLASSES, DECLARED_CONSTRUCTORS, DECLARED_FIELDS, DECLARED_METHODS, - QUERY_DECLARED_METHODS, QUERY_PUBLIC_METHODS, QUERY_DECLARED_CONSTRUCTORS, QUERY_PUBLIC_CONSTRUCTORS }; + private static final MemberCategory[] DEFAULT_MEMBER_CATEGORIES = { MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS, + MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS, + MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES }; @Test void empty() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.refresh(); - NativeConfigurationRegistry registry = process(context.getDefaultListableBeanFactory()); - // reflection hint - { - Map, DefaultNativeReflectionEntry> entries = registry.reflection().reflectionEntries() - .collect(Collectors.toMap(DefaultNativeReflectionEntry::getType, x -> x)); - Assertions.assertThat(entries).isEmpty(); - } - // resource hint - { - Set resources = registry.resources().toResourcesDescriptor().getPatterns(); - Assertions.assertThat(resources).isEmpty(); - } + RuntimeHints hints = process(context.getDefaultListableBeanFactory()); + assertThat(hints.reflection().typeHints()).isEmpty(); + assertThat(hints.resources().resourcePatternHints()).isEmpty(); } @Test @@ -66,22 +57,21 @@ void one() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.registerBean(ConfigurationForOne.class); context.refresh(); - NativeConfigurationRegistry registry = process(context.getDefaultListableBeanFactory()); + RuntimeHints hints = process(context.getDefaultListableBeanFactory()); // reflection hint { - Map, DefaultNativeReflectionEntry> entries = registry.reflection().reflectionEntries() - .collect(Collectors.toMap(DefaultNativeReflectionEntry::getType, x -> x)); - Assertions.assertThat(entries).hasSize(2); - Assertions.assertThat(entries.get(City.class)).satisfies(x -> Assertions.assertThat(x.getAccess().toArray()) - .isEqualTo(new TypeAccess[] { PUBLIC_CONSTRUCTORS, PUBLIC_METHODS })); - Assertions.assertThat(entries.get(Country.class)).satisfies(x -> Assertions.assertThat(x.getAccess().toArray()) - .isEqualTo(new TypeAccess[] { PUBLIC_CONSTRUCTORS, PUBLIC_METHODS })); + assertThat(hints.reflection().typeHints()).hasSize(2); + assertThat(RuntimeHintsPredicates.reflection().onType(City.class) + .withMemberCategories(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS)) + .accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(Country.class) + .withMemberCategories(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS)) + .accepts(hints); } // resource hint { - Set resources = registry.resources().toResourcesDescriptor().getPatterns(); - Assertions.assertThat(resources).containsExactlyInAnyOrder("mapper/sub1/BarMapper.xml", - "mapper/sub1/FooMapper.xml"); + assertThat(RuntimeHintsPredicates.resource().forResource("mapper/sub1/BarMapper.xml")).accepts(hints); + assertThat(RuntimeHintsPredicates.resource().forResource("mapper/sub1/FooMapper.xml")).accepts(hints); } } @@ -90,49 +80,54 @@ void multi() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.registerBean(ConfigurationForMulti.class); context.refresh(); - NativeConfigurationRegistry registry = process(context.getDefaultListableBeanFactory()); + RuntimeHints hints = process(context.getDefaultListableBeanFactory()); // reflection hint { - Map, DefaultNativeReflectionEntry> entries = registry.reflection().reflectionEntries() - .collect(Collectors.toMap(DefaultNativeReflectionEntry::getType, x -> x)); - Assertions.assertThat(entries).hasSize(6); - Assertions.assertThat(entries.get(City.class)).satisfies(x -> Assertions.assertThat(x.getAccess().toArray()) - .isEqualTo(new TypeAccess[] { PUBLIC_CONSTRUCTORS, PUBLIC_METHODS })); - Assertions.assertThat(entries.get(Country.class)).satisfies(x -> Assertions.assertThat(x.getAccess().toArray()) - .isEqualTo(new TypeAccess[] { PUBLIC_CONSTRUCTORS, PUBLIC_METHODS })); - Assertions.assertThat(entries.get(FooTypeHandler.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(DEFAULT_TYPE_ACCESSES)); - Assertions.assertThat(entries.get(BarTypeHandler.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(DEFAULT_TYPE_ACCESSES)); - Assertions.assertThat(entries.get(AnyTypeHandler.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(DEFAULT_TYPE_ACCESSES)); - Assertions.assertThat(entries.get(TypeHandlers.InnerTypeHandler.class)) - .satisfies(x -> Assertions.assertThat(x.getAccess().toArray()).isEqualTo(DEFAULT_TYPE_ACCESSES)); + assertThat(hints.reflection().typeHints()).hasSize(6); + assertThat(RuntimeHintsPredicates.reflection().onType(City.class) + .withMemberCategories(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS)) + .accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(Country.class) + .withMemberCategories(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS)) + .accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(FooTypeHandler.class) + .withMemberCategories(DEFAULT_MEMBER_CATEGORIES)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(BarTypeHandler.class) + .withMemberCategories(DEFAULT_MEMBER_CATEGORIES)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(AnyTypeHandler.class) + .withMemberCategories(DEFAULT_MEMBER_CATEGORIES)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(TypeHandlers.InnerTypeHandler.class) + .withMemberCategories(DEFAULT_MEMBER_CATEGORIES)).accepts(hints); } // resource hint { - Set resources = registry.resources().toResourcesDescriptor().getPatterns(); - Assertions.assertThat(resources).containsExactlyInAnyOrder("mapper/sub1/BarMapper.xml", - "mapper/sub1/FooMapper.xml", "mapper/sub2/AnyMapper.xml"); + assertThat(RuntimeHintsPredicates.resource().forResource("mapper/sub1/BarMapper.xml")).accepts(hints); + assertThat(RuntimeHintsPredicates.resource().forResource("mapper/sub1/FooMapper.xml")).accepts(hints); + assertThat(RuntimeHintsPredicates.resource().forResource("mapper/sub2/AnyMapper.xml")).accepts(hints); } - } - private NativeConfigurationRegistry process(DefaultListableBeanFactory beanFactory) { - NativeConfigurationRegistry registry = new NativeConfigurationRegistry(); - new MyBatisScannedResourcesNativeConfigurationProcessor().process(beanFactory, registry); - return registry; + private RuntimeHints process(DefaultListableBeanFactory beanFactory) { + RuntimeHints hints = new RuntimeHints(); + GenerationContext generationContext = mock(GenerationContext.class); + when(generationContext.getRuntimeHints()).thenReturn(hints); + BeanFactoryInitializationAotContribution contribution = new MyBatisScannedResourcesNativeConfigurationProcessor() + .processAheadOfTime(beanFactory); + if (contribution != null) { + contribution.applyTo(generationContext, mock(BeanFactoryInitializationCode.class)); + } + return hints; } @MyBatisResourcesScan(typeAliasesPackages = "org.mybatis.spring.nativex.entity", mapperLocationPatterns = "mapper/sub1/*.*", typeAccesses = { - TypeAccess.PUBLIC_CONSTRUCTORS, TypeAccess.PUBLIC_METHODS }) + MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS }) @Configuration static class ConfigurationForOne { } @MyBatisResourcesScan(typeAliasesPackages = "org.mybatis.spring.nativex.entity", typeAccesses = { - TypeAccess.PUBLIC_CONSTRUCTORS, TypeAccess.PUBLIC_METHODS }) + MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS }) @MyBatisResourcesScan(typeHandlerPackages = "org.mybatis.spring.nativex.component") @MyBatisResourcesScan(mapperLocationPatterns = "mapper/sub1/*.*") @MyBatisResourcesScan(reflectionTypePackages = "org.mybatis.spring.nativex.component2") diff --git a/core/src/test/java/org/mybatis/spring/nativex/autoconfigure/MyBatisSpringNativeAutoConfigurationTest.java b/core/src/test/java/org/mybatis/spring/nativex/autoconfigure/MyBatisSpringNativeAutoConfigurationTest.java index 99a6a39..c899c04 100644 --- a/core/src/test/java/org/mybatis/spring/nativex/autoconfigure/MyBatisSpringNativeAutoConfigurationTest.java +++ b/core/src/test/java/org/mybatis/spring/nativex/autoconfigure/MyBatisSpringNativeAutoConfigurationTest.java @@ -22,6 +22,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mybatis.spring.mapper.MapperFactoryBean; import org.mybatis.spring.nativex.MyBatisResourcesScan; import org.mybatis.spring.nativex.component.AbstractTypeHandler; import org.mybatis.spring.nativex.component.BarService; @@ -31,6 +32,9 @@ import org.mybatis.spring.nativex.component2.AnyTypeHandler; import org.mybatis.spring.nativex.entity.City; import org.mybatis.spring.nativex.entity.Country; +import org.mybatis.spring.nativex.mapper.SampleMapper; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Configuration; @@ -133,6 +137,21 @@ void multi() { } } + @Test + void clearMapperFactoryBeanConstructorArguments() { + DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + beanFactory.registerBeanDefinition("sampleMapper", + BeanDefinitionBuilder.rootBeanDefinition(MapperFactoryBean.class) + .addConstructorArgValue(SampleMapper.class.getName()) + .addPropertyValue("mapperInterface", SampleMapper.class).getBeanDefinition()); + Assertions.assertThat(beanFactory.getBeanDefinition("sampleMapper").getConstructorArgumentValues().isEmpty()) + .isFalse(); + new MyBatisSpringNativeAutoConfiguration().mybatisMapperFactoryBeanDefinitionPostProcessor() + .postProcessBeanFactory(beanFactory); + Assertions.assertThat(beanFactory.getBeanDefinition("sampleMapper").getConstructorArgumentValues().isEmpty()) + .isTrue(); + } + @EnableAutoConfiguration @Configuration static class EmptyConfiguration { diff --git a/core/src/test/java/org/mybatis/spring/nativex/mapper/Sample2Mapper.java b/core/src/test/java/org/mybatis/spring/nativex/mapper/Sample2Mapper.java index 3f2e1ed..7989785 100644 --- a/core/src/test/java/org/mybatis/spring/nativex/mapper/Sample2Mapper.java +++ b/core/src/test/java/org/mybatis/spring/nativex/mapper/Sample2Mapper.java @@ -15,5 +15,5 @@ */ package org.mybatis.spring.nativex.mapper; -public class Sample2Mapper { +public interface Sample2Mapper { } diff --git a/core/src/test/java/org/mybatis/spring/nativex/mapper/Sample3Mapper.java b/core/src/test/java/org/mybatis/spring/nativex/mapper/Sample3Mapper.java index b5c3fb9..ec200ae 100644 --- a/core/src/test/java/org/mybatis/spring/nativex/mapper/Sample3Mapper.java +++ b/core/src/test/java/org/mybatis/spring/nativex/mapper/Sample3Mapper.java @@ -15,5 +15,5 @@ */ package org.mybatis.spring.nativex.mapper; -public class Sample3Mapper { +public interface Sample3Mapper { } diff --git a/extensions/pom.xml b/extensions/pom.xml index a94470c..10be0b9 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -58,20 +58,15 @@ true - org.mybatis.dynamic-sql - mybatis-dynamic-sql + org.springframework + spring-context provided - true - org.springframework.experimental - spring-native - provided - - - org.springframework.experimental - spring-aot + org.mybatis.dynamic-sql + mybatis-dynamic-sql provided + true diff --git a/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisDynamicSqlNativeConfiguration.java b/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisDynamicSqlNativeConfiguration.java index abe66ce..bb91e30 100644 --- a/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisDynamicSqlNativeConfiguration.java +++ b/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisDynamicSqlNativeConfiguration.java @@ -15,15 +15,6 @@ */ package org.mybatis.spring.nativex; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_METHODS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_METHODS; - import org.mybatis.dynamic.sql.delete.render.DefaultDeleteStatementProvider; import org.mybatis.dynamic.sql.insert.render.DefaultGeneralInsertStatementProvider; import org.mybatis.dynamic.sql.insert.render.DefaultInsertStatementProvider; @@ -32,41 +23,34 @@ import org.mybatis.dynamic.sql.update.render.DefaultUpdateStatementProvider; import org.mybatis.dynamic.sql.util.SqlProviderAdapter; import org.mybatis.dynamic.sql.util.springbatch.SpringBatchProviderAdapter; -import org.springframework.nativex.hint.NativeHint; -import org.springframework.nativex.hint.TypeHint; -import org.springframework.nativex.type.NativeConfiguration; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.util.ClassUtils; /** * Registers hints to make a MyBatis Dynamic SQL component work in a Spring Native context. * * @author Kazuki Shimizu */ -// @formatter:off -@NativeHint( - trigger = SqlProviderAdapter.class -) -@TypeHint( - types = { - SqlProviderAdapter.class, - SpringBatchProviderAdapter.class, - DefaultDeleteStatementProvider.class, - DefaultGeneralInsertStatementProvider.class, - DefaultInsertStatementProvider.class, - DefaultMultiRowInsertStatementProvider.class, - DefaultSelectStatementProvider.class, - DefaultUpdateStatementProvider.class - }, - access = { - PUBLIC_CONSTRUCTORS, - PUBLIC_CLASSES, - PUBLIC_FIELDS, - PUBLIC_METHODS, - DECLARED_CLASSES, - DECLARED_CONSTRUCTORS, - DECLARED_FIELDS, - DECLARED_METHODS +public class MyBatisDynamicSqlNativeConfiguration implements RuntimeHintsRegistrar { + + private static final MemberCategory[] MEMBER_CATEGORIES = { MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS, + MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS, + MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES }; + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + if (!ClassUtils.isPresent("org.mybatis.dynamic.sql.util.SqlProviderAdapter", classLoader)) { + return; } -) -// @formatter:on -public class MyBatisDynamicSqlNativeConfiguration implements NativeConfiguration { + for (Class type : new Class[] { SqlProviderAdapter.class, SpringBatchProviderAdapter.class, + DefaultDeleteStatementProvider.class, DefaultGeneralInsertStatementProvider.class, + DefaultInsertStatementProvider.class, DefaultMultiRowInsertStatementProvider.class, + DefaultSelectStatementProvider.class, DefaultUpdateStatementProvider.class }) { + hints.reflection().registerType(type, MEMBER_CATEGORIES); + } + } + } diff --git a/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisFreeMarkerNativeConfiguration.java b/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisFreeMarkerNativeConfiguration.java index 20c04ed..a9c5d76 100644 --- a/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisFreeMarkerNativeConfiguration.java +++ b/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisFreeMarkerNativeConfiguration.java @@ -15,56 +15,38 @@ */ package org.mybatis.spring.nativex; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_METHODS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_METHODS; - import org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver; import org.mybatis.scripting.freemarker.FreeMarkerLanguageDriverConfig; import org.mybatis.scripting.freemarker.support.TemplateFilePathProvider; -import org.springframework.nativex.hint.NativeHint; -import org.springframework.nativex.hint.ResourceHint; -import org.springframework.nativex.hint.TypeHint; -import org.springframework.nativex.type.NativeConfiguration; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.util.ClassUtils; /** * Registers hints to make a MyBatis FreeMarker component work in a Spring Native context. * * @author Kazuki Shimizu */ -// @formatter:off -@NativeHint( - trigger = FreeMarkerLanguageDriver.class, - resources = @ResourceHint( - patterns = { - "mybatis-freemarker.properties", - "freemarker/version.properties", - "freemarker/ext/beans/DefaultMemberAccessPolicy-rules" - } - ) -) -@TypeHint( - types = { - FreeMarkerLanguageDriver.class, - FreeMarkerLanguageDriverConfig.class, - TemplateFilePathProvider.class - }, - access = { - PUBLIC_CONSTRUCTORS, - PUBLIC_CLASSES, - PUBLIC_FIELDS, - PUBLIC_METHODS, - DECLARED_CLASSES, - DECLARED_CONSTRUCTORS, - DECLARED_FIELDS, - DECLARED_METHODS +public class MyBatisFreeMarkerNativeConfiguration implements RuntimeHintsRegistrar { + + private static final MemberCategory[] MEMBER_CATEGORIES = { MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS, + MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS, + MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES }; + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + if (!ClassUtils.isPresent("org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver", classLoader)) { + return; } -) -// @formatter:on -public class MyBatisFreeMarkerNativeConfiguration implements NativeConfiguration { + for (Class type : new Class[] { FreeMarkerLanguageDriver.class, FreeMarkerLanguageDriverConfig.class, + TemplateFilePathProvider.class }) { + hints.reflection().registerType(type, MEMBER_CATEGORIES); + } + hints.resources().registerPattern("mybatis-freemarker.properties"); + hints.resources().registerPattern("freemarker/version.properties"); + hints.resources().registerPattern("freemarker/ext/beans/DefaultMemberAccessPolicy-rules"); + } + } diff --git a/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisThymeleafNativeConfiguration.java b/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisThymeleafNativeConfiguration.java index 4b3e773..1879080 100644 --- a/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisThymeleafNativeConfiguration.java +++ b/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisThymeleafNativeConfiguration.java @@ -15,25 +15,16 @@ */ package org.mybatis.spring.nativex; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_METHODS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_METHODS; - import org.mybatis.scripting.thymeleaf.SqlGeneratorConfig; import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriver; import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriverConfig; import org.mybatis.scripting.thymeleaf.expression.Likes; import org.mybatis.scripting.thymeleaf.support.TemplateFilePathProvider; import org.mybatis.scripting.thymeleaf.support.spring.SpringNamedParameterBindVariableRender; -import org.springframework.nativex.hint.NativeHint; -import org.springframework.nativex.hint.ResourceHint; -import org.springframework.nativex.hint.TypeHint; -import org.springframework.nativex.type.NativeConfiguration; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.util.ClassUtils; import org.thymeleaf.expression.Aggregates; import org.thymeleaf.expression.Arrays; import org.thymeleaf.expression.Bools; @@ -55,48 +46,26 @@ * * @author Kazuki Shimizu */ -// @formatter:off -@NativeHint( - trigger = ThymeleafLanguageDriver.class, - resources = @ResourceHint( - patterns = "mybatis-thymeleaf.properties" - ) -) -@TypeHint( - types = { - ThymeleafLanguageDriver.class, - SqlGeneratorConfig.class, - ThymeleafLanguageDriverConfig.class, - TemplateFilePathProvider.class, - SpringNamedParameterBindVariableRender.class, - Likes.class, - Uris.class, - Calendars.class, - Dates.class, - Bools.class, - Numbers.class, - Objects.class, - Strings.class, - Arrays.class, - Lists.class, - Sets.class, - Maps.class, - Aggregates.class, - Messages.class, - Ids.class, - ExecutionInfo.class - }, - access = { - PUBLIC_CONSTRUCTORS, - PUBLIC_CLASSES, - PUBLIC_FIELDS, - PUBLIC_METHODS, - DECLARED_CLASSES, - DECLARED_CONSTRUCTORS, - DECLARED_FIELDS, - DECLARED_METHODS +public class MyBatisThymeleafNativeConfiguration implements RuntimeHintsRegistrar { + + private static final MemberCategory[] MEMBER_CATEGORIES = { MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS, + MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS, + MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES }; + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + if (!ClassUtils.isPresent("org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriver", classLoader)) { + return; } -) -// @formatter:on -public class MyBatisThymeleafNativeConfiguration implements NativeConfiguration { + for (Class type : new Class[] { ThymeleafLanguageDriver.class, SqlGeneratorConfig.class, + ThymeleafLanguageDriverConfig.class, TemplateFilePathProvider.class, + SpringNamedParameterBindVariableRender.class, Likes.class, Uris.class, Calendars.class, Dates.class, + Bools.class, Numbers.class, Objects.class, Strings.class, Arrays.class, Lists.class, Sets.class, Maps.class, + Aggregates.class, Messages.class, Ids.class, ExecutionInfo.class }) { + hints.reflection().registerType(type, MEMBER_CATEGORIES); + } + hints.resources().registerPattern("mybatis-thymeleaf.properties"); + } + } diff --git a/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisVelocityNativeConfiguration.java b/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisVelocityNativeConfiguration.java index f8dd89a..2caf096 100644 --- a/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisVelocityNativeConfiguration.java +++ b/extensions/src/main/java/org/mybatis/spring/nativex/MyBatisVelocityNativeConfiguration.java @@ -15,15 +15,6 @@ */ package org.mybatis.spring.nativex; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.DECLARED_METHODS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CLASSES; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_CONSTRUCTORS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_FIELDS; -import static org.springframework.nativex.hint.TypeAccess.PUBLIC_METHODS; - import org.apache.velocity.runtime.ParserPoolImpl; import org.apache.velocity.runtime.directive.Break; import org.apache.velocity.runtime.directive.Define; @@ -47,63 +38,38 @@ import org.mybatis.scripting.velocity.VelocityLanguageDriver; import org.mybatis.scripting.velocity.VelocityLanguageDriverConfig; import org.mybatis.scripting.velocity.WhereDirective; -import org.springframework.nativex.hint.NativeHint; -import org.springframework.nativex.hint.ResourceHint; -import org.springframework.nativex.hint.TypeHint; -import org.springframework.nativex.type.NativeConfiguration; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.util.ClassUtils; /** * Registers hints to make a MyBatis Velocity component work in a Spring Native context. * * @author Kazuki Shimizu */ -// @formatter:off -@NativeHint( - trigger = VelocityLanguageDriver.class, - resources = @ResourceHint( - patterns = { - "mybatis-velocity.properties", - "org/apache/velocity/runtime/defaults/.*.properties" - } - ) -) -@TypeHint( - types = { - VelocityLanguageDriver.class, - VelocityLanguageDriverConfig.class, - ParameterMappingCollector.class, - TrimDirective.class, - WhereDirective.class, - SetDirective.class, - InDirective.class, - RepeatDirective.class, - ResourceManagerImpl.class, - ClasspathResourceLoader.class, - ResourceCacheImpl.class, - ParserPoolImpl.class, - UberspectImpl.class, - TypeConversionHandlerImpl.class, - StandardParser.class, - Foreach.class, - Include.class, - Parse.class, - Macro.class, - Evaluate.class, - Break.class, - Define.class, - Stop.class - }, - access = { - PUBLIC_CONSTRUCTORS, - PUBLIC_CLASSES, - PUBLIC_FIELDS, - PUBLIC_METHODS, - DECLARED_CLASSES, - DECLARED_CONSTRUCTORS, - DECLARED_FIELDS, - DECLARED_METHODS +public class MyBatisVelocityNativeConfiguration implements RuntimeHintsRegistrar { + + private static final MemberCategory[] MEMBER_CATEGORIES = { MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS, + MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS, + MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES }; + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + if (!ClassUtils.isPresent("org.mybatis.scripting.velocity.VelocityLanguageDriver", classLoader)) { + return; } -) -// @formatter:on -public class MyBatisVelocityNativeConfiguration implements NativeConfiguration { + for (Class type : new Class[] { VelocityLanguageDriver.class, VelocityLanguageDriverConfig.class, + ParameterMappingCollector.class, TrimDirective.class, WhereDirective.class, SetDirective.class, + InDirective.class, RepeatDirective.class, ResourceManagerImpl.class, ClasspathResourceLoader.class, + ResourceCacheImpl.class, ParserPoolImpl.class, UberspectImpl.class, TypeConversionHandlerImpl.class, + StandardParser.class, Foreach.class, Include.class, Parse.class, Macro.class, Evaluate.class, Break.class, + Define.class, Stop.class }) { + hints.reflection().registerType(type, MEMBER_CATEGORIES); + } + hints.resources().registerPattern("mybatis-velocity.properties"); + hints.resources().registerPattern("org/apache/velocity/runtime/defaults/*.properties"); + } + } diff --git a/extensions/src/main/resources/META-INF/spring.factories b/extensions/src/main/resources/META-INF/spring.factories index d2a044d..1ec9f4e 100644 --- a/extensions/src/main/resources/META-INF/spring.factories +++ b/extensions/src/main/resources/META-INF/spring.factories @@ -13,9 +13,3 @@ # See the License for the specific language governing permissions and # limitations under the License. # - -org.springframework.nativex.type.NativeConfiguration=\ - org.mybatis.spring.nativex.MyBatisThymeleafNativeConfiguration,\ - org.mybatis.spring.nativex.MyBatisVelocityNativeConfiguration,\ - org.mybatis.spring.nativex.MyBatisFreeMarkerNativeConfiguration,\ - org.mybatis.spring.nativex.MyBatisDynamicSqlNativeConfiguration diff --git a/extensions/src/main/resources/META-INF/spring/org.springframework.aot.hint.RuntimeHintsRegistrar b/extensions/src/main/resources/META-INF/spring/org.springframework.aot.hint.RuntimeHintsRegistrar new file mode 100644 index 0000000..c1f3ea8 --- /dev/null +++ b/extensions/src/main/resources/META-INF/spring/org.springframework.aot.hint.RuntimeHintsRegistrar @@ -0,0 +1,4 @@ +org.mybatis.spring.nativex.MyBatisDynamicSqlNativeConfiguration +org.mybatis.spring.nativex.MyBatisFreeMarkerNativeConfiguration +org.mybatis.spring.nativex.MyBatisThymeleafNativeConfiguration +org.mybatis.spring.nativex.MyBatisVelocityNativeConfiguration diff --git a/pom.xml b/pom.xml index b26845a..9819fa0 100644 --- a/pom.xml +++ b/pom.xml @@ -74,19 +74,18 @@ - 11 - 11 + 17 + 17 3.5.19 - 2.1.2 - 2.3.2 + 3.0.4 + 3.0.4 1.1.1 2.3.1 1.3.1 2.0.0 - 2.7.18 - 0.12.2 + 3.4.3 1757561022 @@ -134,16 +133,6 @@ mybatis-spring-boot-autoconfigure ${mybatis-spring-boot.version} - - org.springframework.experimental - spring-native - ${spring-native.version} - - - org.springframework.experimental - spring-aot - ${spring-native.version} - org.springframework.boot spring-boot-starter-parent @@ -155,63 +144,15 @@ - - sonatype-oss-snapshots - Sonatype OSS Snapshots Repository - https://oss.sonatype.org/content/repositories/snapshots - - - - false - - spring-releases - Spring Releases - https://repo.spring.io/release - - - - false - - spring-milestone - Spring Milestone - https://repo.spring.io/milestone - true - spring-snapshot - Spring Snapshot - https://repo.spring.io/snapshot + sonatype-oss-snapshots + Sonatype OSS Snapshots Repository + https://oss.sonatype.org/content/repositories/snapshots - - - - false - - spring-releases - Spring Releases - https://repo.spring.io/release - - - - false - - spring-milestone - Spring Milestone - https://repo.spring.io/milestone - - - - true - - spring-snapshot - Spring Snapshot - https://repo.spring.io/snapshot - - - diff --git a/samples/cache/pom.xml b/samples/cache/pom.xml index 7d807e3..f532ac9 100644 --- a/samples/cache/pom.xml +++ b/samples/cache/pom.xml @@ -41,14 +41,7 @@ org.mybatis.spring.boot mybatis-spring-boot-starter - - org.springframework.experimental - spring-native - - - org.springframework.experimental - spring-aot - + com.h2database h2 @@ -65,12 +58,6 @@ ${repackage.classifier} true - - paketobuildpacks/builder:tiny - - true - - @@ -81,25 +68,7 @@ - - org.springframework.experimental - spring-aot-maven-plugin - ${spring-native.version} - - - test-generate - - test-generate - - - - generate - - generate - - - - + @@ -118,9 +87,22 @@ + + org.springframework.boot + spring-boot-maven-plugin + + + process-aot + + process-aot + + + + org.graalvm.buildtools native-maven-plugin + ${native-buildtools.version} true @@ -129,16 +111,15 @@ - test-native + add-reachability-metadata - test + add-reachability-metadata - test build-native - build + compile-no-fork package diff --git a/samples/cache/src/main/java/org/mybatis/spring/nativex/sample/cache/MybatisSpringNativeSampleApplication.java b/samples/cache/src/main/java/org/mybatis/spring/nativex/sample/cache/MybatisSpringNativeSampleApplication.java index b1ac045..6a0df31 100644 --- a/samples/cache/src/main/java/org/mybatis/spring/nativex/sample/cache/MybatisSpringNativeSampleApplication.java +++ b/samples/cache/src/main/java/org/mybatis/spring/nativex/sample/cache/MybatisSpringNativeSampleApplication.java @@ -19,18 +19,29 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; -import org.springframework.nativex.hint.NativeHint; -import org.springframework.nativex.hint.SerializationHint; +import org.springframework.context.annotation.ImportRuntimeHints; -@NativeHint(serializables = @SerializationHint(types = { ArrayList.class, City.class, String.class, Integer.class, - Number.class })) +@ImportRuntimeHints(MybatisSpringNativeSampleApplication.CacheRuntimeHints.class) @SpringBootApplication public class MybatisSpringNativeSampleApplication { + static class CacheRuntimeHints implements RuntimeHintsRegistrar { + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + hints.serialization().registerType(ArrayList.class); + hints.serialization().registerType(City.class); + hints.serialization().registerType(String.class); + hints.serialization().registerType(Integer.class); + hints.serialization().registerType(Number.class); + } + } + private static final Logger log = LoggerFactory.getLogger("ApLog"); public static void main(String[] args) { diff --git a/samples/configuration/pom.xml b/samples/configuration/pom.xml index 5d3223d..2fc8faa 100644 --- a/samples/configuration/pom.xml +++ b/samples/configuration/pom.xml @@ -41,14 +41,7 @@ org.mybatis.spring.boot mybatis-spring-boot-starter - - org.springframework.experimental - spring-native - - - org.springframework.experimental - spring-aot - + com.h2database h2 @@ -65,12 +58,6 @@ ${repackage.classifier} true - - paketobuildpacks/builder:tiny - - true - - @@ -81,25 +68,7 @@ - - org.springframework.experimental - spring-aot-maven-plugin - ${spring-native.version} - - - test-generate - - test-generate - - - - generate - - generate - - - - + @@ -118,22 +87,34 @@ + + org.springframework.boot + spring-boot-maven-plugin + + + process-aot + + process-aot + + + + org.graalvm.buildtools native-maven-plugin + ${native-buildtools.version} true - test-native + add-reachability-metadata - test + add-reachability-metadata - test build-native - build + compile-no-fork package diff --git a/samples/dao/pom.xml b/samples/dao/pom.xml index 8c604a7..b5f2497 100644 --- a/samples/dao/pom.xml +++ b/samples/dao/pom.xml @@ -41,14 +41,7 @@ org.mybatis.spring.boot mybatis-spring-boot-starter - - org.springframework.experimental - spring-native - - - org.springframework.experimental - spring-aot - + com.h2database h2 @@ -65,12 +58,6 @@ ${repackage.classifier} true - - paketobuildpacks/builder:tiny - - true - - @@ -81,25 +68,7 @@ - - org.springframework.experimental - spring-aot-maven-plugin - ${spring-native.version} - - - test-generate - - test-generate - - - - generate - - generate - - - - + @@ -118,22 +87,34 @@ + + org.springframework.boot + spring-boot-maven-plugin + + + process-aot + + process-aot + + + + org.graalvm.buildtools native-maven-plugin + ${native-buildtools.version} true - test-native + add-reachability-metadata - test + add-reachability-metadata - test build-native - build + compile-no-fork package diff --git a/samples/dynamic-sql/pom.xml b/samples/dynamic-sql/pom.xml index 3dff393..14771e6 100644 --- a/samples/dynamic-sql/pom.xml +++ b/samples/dynamic-sql/pom.xml @@ -45,14 +45,7 @@ org.mybatis.dynamic-sql mybatis-dynamic-sql - - org.springframework.experimental - spring-native - - - org.springframework.experimental - spring-aot - + com.h2database h2 @@ -69,12 +62,6 @@ ${repackage.classifier} true - - paketobuildpacks/builder:tiny - - true - - @@ -85,25 +72,7 @@ - - org.springframework.experimental - spring-aot-maven-plugin - ${spring-native.version} - - - test-generate - - test-generate - - - - generate - - generate - - - - + @@ -122,22 +91,34 @@ + + org.springframework.boot + spring-boot-maven-plugin + + + process-aot + + process-aot + + + + org.graalvm.buildtools native-maven-plugin + ${native-buildtools.version} true - test-native + add-reachability-metadata - test + add-reachability-metadata - test build-native - build + compile-no-fork package diff --git a/samples/freemarker/pom.xml b/samples/freemarker/pom.xml index c5bdb1b..c29fde2 100644 --- a/samples/freemarker/pom.xml +++ b/samples/freemarker/pom.xml @@ -45,14 +45,7 @@ org.mybatis.scripting mybatis-freemarker - - org.springframework.experimental - spring-native - - - org.springframework.experimental - spring-aot - + com.h2database h2 @@ -69,12 +62,6 @@ ${repackage.classifier} true - - paketobuildpacks/builder:tiny - - true - - @@ -85,25 +72,7 @@ - - org.springframework.experimental - spring-aot-maven-plugin - ${spring-native.version} - - - test-generate - - test-generate - - - - generate - - generate - - - - + @@ -122,22 +91,34 @@ + + org.springframework.boot + spring-boot-maven-plugin + + + process-aot + + process-aot + + + + org.graalvm.buildtools native-maven-plugin + ${native-buildtools.version} true - test-native + add-reachability-metadata - test + add-reachability-metadata - test build-native - build + compile-no-fork package diff --git a/samples/pom.xml b/samples/pom.xml index 338ba41..fbec9f1 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -78,6 +78,11 @@ native-maven-plugin ${native-buildtools.version} true + + + --initialize-at-run-time=org.apache.ibatis.logging.LogFactory + + diff --git a/samples/scan/pom.xml b/samples/scan/pom.xml index dc94cfd..ef3d26d 100644 --- a/samples/scan/pom.xml +++ b/samples/scan/pom.xml @@ -41,14 +41,7 @@ org.mybatis.spring.boot mybatis-spring-boot-starter - - org.springframework.experimental - spring-native - - - org.springframework.experimental - spring-aot - + com.h2database h2 @@ -65,12 +58,6 @@ ${repackage.classifier} true - - paketobuildpacks/builder:tiny - - true - - @@ -81,25 +68,7 @@ - - org.springframework.experimental - spring-aot-maven-plugin - ${spring-native.version} - - - test-generate - - test-generate - - - - generate - - generate - - - - + @@ -118,22 +87,34 @@ + + org.springframework.boot + spring-boot-maven-plugin + + + process-aot + + process-aot + + + + org.graalvm.buildtools native-maven-plugin + ${native-buildtools.version} true - test-native + add-reachability-metadata - test + add-reachability-metadata - test build-native - build + compile-no-fork package diff --git a/samples/simple/pom.xml b/samples/simple/pom.xml index 3563e07..1e3dcd5 100644 --- a/samples/simple/pom.xml +++ b/samples/simple/pom.xml @@ -41,14 +41,7 @@ org.mybatis.spring.boot mybatis-spring-boot-starter - - org.springframework.experimental - spring-native - - - org.springframework.experimental - spring-aot - + com.h2database h2 @@ -65,12 +58,6 @@ ${repackage.classifier} true - - paketobuildpacks/builder:tiny - - true - - @@ -81,25 +68,7 @@ - - org.springframework.experimental - spring-aot-maven-plugin - ${spring-native.version} - - - test-generate - - test-generate - - - - generate - - generate - - - - + @@ -118,22 +87,34 @@ + + org.springframework.boot + spring-boot-maven-plugin + + + process-aot + + process-aot + + + + org.graalvm.buildtools native-maven-plugin + ${native-buildtools.version} true - test-native + add-reachability-metadata - test + add-reachability-metadata - test build-native - build + compile-no-fork package diff --git a/samples/sqlprovider/pom.xml b/samples/sqlprovider/pom.xml index e20e23d..58aa916 100644 --- a/samples/sqlprovider/pom.xml +++ b/samples/sqlprovider/pom.xml @@ -41,14 +41,7 @@ org.mybatis.spring.boot mybatis-spring-boot-starter - - org.springframework.experimental - spring-native - - - org.springframework.experimental - spring-aot - + com.h2database h2 @@ -65,12 +58,6 @@ ${repackage.classifier} true - - paketobuildpacks/builder:tiny - - true - - @@ -81,25 +68,7 @@ - - org.springframework.experimental - spring-aot-maven-plugin - ${spring-native.version} - - - test-generate - - test-generate - - - - generate - - generate - - - - + @@ -118,22 +87,34 @@ + + org.springframework.boot + spring-boot-maven-plugin + + + process-aot + + process-aot + + + + org.graalvm.buildtools native-maven-plugin + ${native-buildtools.version} true - test-native + add-reachability-metadata - test + add-reachability-metadata - test build-native - build + compile-no-fork package diff --git a/samples/thymeleaf-sqlgenerator/pom.xml b/samples/thymeleaf-sqlgenerator/pom.xml index caf5c4a..b44f0a7 100644 --- a/samples/thymeleaf-sqlgenerator/pom.xml +++ b/samples/thymeleaf-sqlgenerator/pom.xml @@ -45,14 +45,7 @@ org.mybatis.scripting mybatis-thymeleaf - - org.springframework.experimental - spring-native - - - org.springframework.experimental - spring-aot - + com.h2database h2 @@ -69,12 +62,6 @@ ${repackage.classifier} true - - paketobuildpacks/builder:tiny - - true - - @@ -85,25 +72,7 @@ - - org.springframework.experimental - spring-aot-maven-plugin - ${spring-native.version} - - - test-generate - - test-generate - - - - generate - - generate - - - - + @@ -122,22 +91,34 @@ + + org.springframework.boot + spring-boot-maven-plugin + + + process-aot + + process-aot + + + + org.graalvm.buildtools native-maven-plugin + ${native-buildtools.version} true - test-native + add-reachability-metadata - test + add-reachability-metadata - test build-native - build + compile-no-fork package diff --git a/samples/thymeleaf/pom.xml b/samples/thymeleaf/pom.xml index 1509de6..49d0fb1 100644 --- a/samples/thymeleaf/pom.xml +++ b/samples/thymeleaf/pom.xml @@ -45,14 +45,7 @@ org.mybatis.scripting mybatis-thymeleaf - - org.springframework.experimental - spring-native - - - org.springframework.experimental - spring-aot - + com.h2database h2 @@ -69,12 +62,6 @@ ${repackage.classifier} true - - paketobuildpacks/builder:tiny - - true - - @@ -85,25 +72,7 @@ - - org.springframework.experimental - spring-aot-maven-plugin - ${spring-native.version} - - - test-generate - - test-generate - - - - generate - - generate - - - - + @@ -122,22 +91,34 @@ + + org.springframework.boot + spring-boot-maven-plugin + + + process-aot + + process-aot + + + + org.graalvm.buildtools native-maven-plugin + ${native-buildtools.version} true - test-native + add-reachability-metadata - test + add-reachability-metadata - test build-native - build + compile-no-fork package diff --git a/samples/velocity/pom.xml b/samples/velocity/pom.xml index e6dcd7c..2696e5e 100644 --- a/samples/velocity/pom.xml +++ b/samples/velocity/pom.xml @@ -45,14 +45,7 @@ org.mybatis.scripting mybatis-velocity - - org.springframework.experimental - spring-native - - - org.springframework.experimental - spring-aot - + com.h2database h2 @@ -69,12 +62,6 @@ ${repackage.classifier} true - - paketobuildpacks/builder:tiny - - true - - @@ -85,25 +72,7 @@ - - org.springframework.experimental - spring-aot-maven-plugin - ${spring-native.version} - - - test-generate - - test-generate - - - - generate - - generate - - - - + @@ -122,22 +91,34 @@ + + org.springframework.boot + spring-boot-maven-plugin + + + process-aot + + process-aot + + + + org.graalvm.buildtools native-maven-plugin + ${native-buildtools.version} true - test-native + add-reachability-metadata - test + add-reachability-metadata - test build-native - build + compile-no-fork package diff --git a/samples/xml/pom.xml b/samples/xml/pom.xml index 25bda7c..ac52999 100644 --- a/samples/xml/pom.xml +++ b/samples/xml/pom.xml @@ -41,14 +41,7 @@ org.mybatis.spring.boot mybatis-spring-boot-starter - - org.springframework.experimental - spring-native - - - org.springframework.experimental - spring-aot - + com.h2database h2 @@ -65,12 +58,6 @@ ${repackage.classifier} true - - paketobuildpacks/builder:tiny - - true - - @@ -81,25 +68,7 @@ - - org.springframework.experimental - spring-aot-maven-plugin - ${spring-native.version} - - - test-generate - - test-generate - - - - generate - - generate - - - - + @@ -118,22 +87,34 @@ + + org.springframework.boot + spring-boot-maven-plugin + + + process-aot + + process-aot + + + + org.graalvm.buildtools native-maven-plugin + ${native-buildtools.version} true - test-native + add-reachability-metadata - test + add-reachability-metadata - test build-native - build + compile-no-fork package