Add Spring Framework AOT support.

This commit is contained in:
Gerrit Meier
2022-07-11 15:22:13 +02:00
parent f7b07ed963
commit 2b06d45209
7 changed files with 227 additions and 9 deletions

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2011-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.aot;
import org.springframework.data.neo4j.core.convert.Neo4jSimpleTypes;
import java.util.function.Predicate;
/**
* @author Gerrit Meier
* @since 7.0.0
*/
public class Neo4jAotPredicates {
static final Predicate<Class<?>> IS_SIMPLE_TYPE = Neo4jSimpleTypes.HOLDER::isSimpleType;
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2011-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.aot;
import org.springframework.data.domain.ManagedTypes;
import java.util.Arrays;
import java.util.function.Consumer;
/**
* @author Gerrit Meier
* @since 7.0.0
*/
public final class Neo4jManagedTypes implements ManagedTypes {
private final ManagedTypes delegate;
private Neo4jManagedTypes(ManagedTypes types) {
this.delegate = types;
}
/**
* Wraps an existing {@link ManagedTypes} object with {@link Neo4jManagedTypes}.
*/
public static Neo4jManagedTypes from(ManagedTypes managedTypes) {
return new Neo4jManagedTypes(managedTypes);
}
/**
* Factory method used to construct {@link Neo4jManagedTypes} from the given array of {@link Class types}.
*
* @param types array of {@link Class types} used to initialize the {@link ManagedTypes}; must not be {@literal null}.
* @return new instance of {@link Neo4jManagedTypes} initialized from {@link Class types}.
*/
public static Neo4jManagedTypes from(Class<?>... types) {
return fromIterable(Arrays.asList(types));
}
/**
* Factory method used to construct {@link Neo4jManagedTypes} from the given, required {@link Iterable} of
* {@link Class types}.
*
* @param types {@link Iterable} of {@link Class types} used to initialize the {@link ManagedTypes}; must not be
* {@literal null}.
* @return new instance of {@link Neo4jManagedTypes} initialized the given, required {@link Iterable} of {@link Class
* types}.
*/
public static Neo4jManagedTypes fromIterable(Iterable<? extends Class<?>> types) {
return from(ManagedTypes.fromIterable(types));
}
/**
* Factory method to return an empty {@link Neo4jManagedTypes} object.
*
* @return an empty {@link Neo4jManagedTypes} object.
*/
public static Neo4jManagedTypes empty() {
return from(ManagedTypes.empty());
}
@Override
public void forEach(Consumer<Class<?>> action) {
delegate.forEach(action);
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2011-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.aot;
import org.springframework.aot.generate.GenerationContext;
import org.springframework.core.ResolvableType;
import org.springframework.data.aot.ManagedTypesBeanRegistrationAotProcessor;
import org.springframework.data.domain.ManagedTypes;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
* @author Gerrit Meier
* @since 7.0.0
*/
public class Neo4jManagedTypesBeanRegistrationAotProcessor extends ManagedTypesBeanRegistrationAotProcessor {
public Neo4jManagedTypesBeanRegistrationAotProcessor() {
setModuleIdentifier("neo4j");
}
@Override
protected boolean isMatch(@Nullable Class<?> beanType, @Nullable String beanName) {
return isNeo4jManagedTypes(beanType) || super.isMatch(beanType, beanName);
}
protected boolean isNeo4jManagedTypes(@Nullable Class<?> beanType) {
return beanType != null && ClassUtils.isAssignable(ManagedTypes.class, beanType);
}
@Override
protected void contributeType(ResolvableType type, GenerationContext generationContext) {
if (Neo4jAotPredicates.IS_SIMPLE_TYPE.test(type.toClass())) {
return;
}
super.contributeType(type, generationContext);
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2011-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.aot;
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.data.neo4j.core.mapping.callback.AfterConvertCallback;
import org.springframework.data.neo4j.core.mapping.callback.BeforeBindCallback;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.support.UUIDStringGenerator;
import org.springframework.data.neo4j.repository.query.SimpleQueryByExampleExecutor;
import org.springframework.data.neo4j.repository.support.SimpleNeo4jRepository;
import org.springframework.lang.Nullable;
import java.util.Arrays;
/**
* @author Gerrit Meier
* @since 7.0.0
*/
public class Neo4jRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
hints.reflection().registerTypes(
Arrays.asList(
TypeReference.of(SimpleNeo4jRepository.class),
TypeReference.of(SimpleQueryByExampleExecutor.class),
TypeReference.of(BeforeBindCallback.class),
TypeReference.of(AfterConvertCallback.class),
// todo "temporary" fix, should get resolved when defined in @GeneratedValue
TypeReference.of(UUIDStringGenerator.class),
TypeReference.of(GeneratedValue.InternalIdGenerator.class),
TypeReference.of(GeneratedValue.UUIDGenerator.class)
),
builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_PUBLIC_METHODS));
}
}

View File

@@ -15,8 +15,6 @@
*/ */
package org.springframework.data.neo4j.config; package org.springframework.data.neo4j.config;
import java.lang.annotation.Annotation;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@@ -24,10 +22,11 @@ import org.springframework.data.auditing.IsNewAwareAuditingHandler;
import org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport; import org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport;
import org.springframework.data.auditing.config.AuditingConfiguration; import org.springframework.data.auditing.config.AuditingConfiguration;
import org.springframework.data.config.ParsingUtils; import org.springframework.data.config.ParsingUtils;
import org.springframework.data.mapping.context.PersistentEntities;
import org.springframework.data.neo4j.core.mapping.callback.AuditingBeforeBindCallback; import org.springframework.data.neo4j.core.mapping.callback.AuditingBeforeBindCallback;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import java.lang.annotation.Annotation;
/** /**
* @author Michael J. Simons * @author Michael J. Simons
* @soundtrack Iron Maiden - Killers * @soundtrack Iron Maiden - Killers
@@ -62,7 +61,7 @@ final class Neo4jAuditingRegistrar extends AuditingBeanDefinitionRegistrarSuppor
*/ */
@Override @Override
protected void registerAuditListenerBeanDefinition(BeanDefinition auditingHandlerDefinition, protected void registerAuditListenerBeanDefinition(BeanDefinition auditingHandlerDefinition,
BeanDefinitionRegistry registry) { BeanDefinitionRegistry registry) {
Assert.notNull(auditingHandlerDefinition, "BeanDefinition must not be null"); Assert.notNull(auditingHandlerDefinition, "BeanDefinition must not be null");
Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
@@ -86,11 +85,11 @@ final class Neo4jAuditingRegistrar extends AuditingBeanDefinitionRegistrarSuppor
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(IsNewAwareAuditingHandler.class); BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(IsNewAwareAuditingHandler.class);
BeanDefinitionBuilder persistentEntities = BeanDefinitionBuilder.genericBeanDefinition(PersistentEntities.class)
.setFactoryMethod("of");
persistentEntities.addConstructorArgReference(MAPPING_CONTEXT_BEAN_NAME);
builder.addConstructorArgValue(persistentEntities.getBeanDefinition());
return configureDefaultAuditHandlerAttributes(configuration, builder); return configureDefaultAuditHandlerAttributes(configuration, builder);
} }
@Override
public void postProcess(BeanDefinitionBuilder builder, AuditingConfiguration configuration, BeanDefinitionRegistry registry) {
builder.setFactoryMethod("from").addConstructorArgReference("neo4jMappingContext");
}
} }

View File

@@ -135,4 +135,5 @@ public final class Neo4jRepositoryConfigurationExtension extends RepositoryConfi
builder.addPropertyReference("neo4jMappingContext", builder.addPropertyReference("neo4jMappingContext",
source.getAttribute("neo4jMappingContextRef").orElse(DEFAULT_MAPPING_CONTEXT_BEAN_NAME)); source.getAttribute("neo4jMappingContextRef").orElse(DEFAULT_MAPPING_CONTEXT_BEAN_NAME));
} }
} }

View File

@@ -0,0 +1,4 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.springframework.data.neo4j.aot.Neo4jRuntimeHints
org.springframework.beans.factory.aot.BeanRegistrationAotProcessor=\
org.springframework.data.neo4j.aot.Neo4jManagedTypesBeanRegistrationAotProcessor