Register Hibernate @EmbeddableInstantiator reflection hints
This commit updates PersistenceManagedTypesBeanRegistrationAotProcessor to register reflection hints for `@EmbeddableInstantiator` annotations available as of Hibernate 6.0 when needed. Related tests will be added in https://github.com/spring-projects/spring-aot-smoke-tests. Closes gh-31534
This commit is contained in:
@@ -23,6 +23,7 @@ import javax.lang.model.element.Modifier;
|
||||
|
||||
import jakarta.persistence.Convert;
|
||||
import jakarta.persistence.Converter;
|
||||
import jakarta.persistence.Embedded;
|
||||
import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.IdClass;
|
||||
import jakarta.persistence.PostLoad;
|
||||
@@ -64,11 +65,26 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @author Sebastien Deleuze
|
||||
* @since 6.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {
|
||||
|
||||
private static final List<Class<? extends Annotation>> CALLBACK_TYPES = List.of(PreUpdate.class,
|
||||
PostUpdate.class, PrePersist.class, PostPersist.class, PreRemove.class, PostRemove.class, PostLoad.class);
|
||||
|
||||
@Nullable
|
||||
private static Class<? extends Annotation> embeddableInstantiatorClass;
|
||||
|
||||
static {
|
||||
try {
|
||||
embeddableInstantiatorClass = (Class<? extends Annotation>) ClassUtils.forName("org.hibernate.annotations.EmbeddableInstantiator",
|
||||
PersistenceManagedTypesBeanRegistrationAotProcessor.class.getClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
embeddableInstantiatorClass = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
|
||||
@@ -129,6 +145,7 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
|
||||
contributeIdClassHints(hints, managedClass);
|
||||
contributeConverterHints(hints, managedClass);
|
||||
contributeCallbackHints(hints, managedClass);
|
||||
contributeHibernateHints(hints, managedClass);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new IllegalArgumentException("Failed to instantiate the managed class: " + managedClassName, ex);
|
||||
@@ -176,5 +193,23 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
|
||||
reflection.registerMethod(method, ExecutableMode.INVOKE),
|
||||
method -> CALLBACK_TYPES.stream().anyMatch(method::isAnnotationPresent));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void contributeHibernateHints(RuntimeHints hints, Class<?> managedClass) {
|
||||
if (embeddableInstantiatorClass == null) {
|
||||
return;
|
||||
}
|
||||
ReflectionHints reflection = hints.reflection();
|
||||
ReflectionUtils.doWithFields(managedClass, field -> {
|
||||
Embedded embeddedAnnotation = AnnotationUtils.findAnnotation(field, Embedded.class);
|
||||
if (embeddedAnnotation != null && field.getAnnotatedType().getType() instanceof Class<?> embeddedClass) {
|
||||
Annotation embeddableInstantiatorAnnotation = AnnotationUtils.findAnnotation(embeddedClass, embeddableInstantiatorClass);
|
||||
if (embeddableInstantiatorAnnotation != null) {
|
||||
Class<?> embeddableInstantiatorClass = (Class<?>) AnnotationUtils.getAnnotationAttributes(embeddableInstantiatorAnnotation).get("value");
|
||||
reflection.registerType(embeddableInstantiatorClass, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user