Merge branch '6.2.x'
# Conflicts: # framework-platform/framework-platform.gradle # spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessor.java # spring-orm/src/test/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessorTests.java
This commit is contained in:
commit
585b4e08e8
|
|
@ -26,7 +26,7 @@ dependencies {
|
|||
constraints {
|
||||
api("com.fasterxml:aalto-xml:1.3.4")
|
||||
api("com.fasterxml.woodstox:woodstox-core:6.7.0")
|
||||
api("com.github.ben-manes.caffeine:caffeine:3.2.2")
|
||||
api("com.github.ben-manes.caffeine:caffeine:3.2.3")
|
||||
api("com.github.librepdf:openpdf:1.3.43")
|
||||
api("com.google.code.findbugs:findbugs:3.0.1")
|
||||
api("com.google.code.findbugs:jsr305:3.0.2")
|
||||
|
|
@ -124,7 +124,7 @@ dependencies {
|
|||
api("org.hibernate.orm:hibernate-core:7.2.0.CR1")
|
||||
api("org.hibernate.validator:hibernate-validator:9.1.0.CR1")
|
||||
api("org.hsqldb:hsqldb:2.7.4")
|
||||
api("org.htmlunit:htmlunit:4.17.0")
|
||||
api("org.htmlunit:htmlunit:4.18.0")
|
||||
api("org.javamoney:moneta:1.4.4")
|
||||
api("org.jboss.logging:jboss-logging:3.6.1.Final")
|
||||
api("org.jruby:jruby:10.0.2.0")
|
||||
|
|
@ -135,8 +135,8 @@ dependencies {
|
|||
api("org.python:jython-standalone:2.7.4")
|
||||
api("org.quartz-scheduler:quartz:2.3.2")
|
||||
api("org.reactivestreams:reactive-streams:1.0.4")
|
||||
api("org.seleniumhq.selenium:htmlunit3-driver:4.36.1")
|
||||
api("org.seleniumhq.selenium:selenium-java:4.36.0")
|
||||
api("org.seleniumhq.selenium:htmlunit3-driver:4.38.0")
|
||||
api("org.seleniumhq.selenium:selenium-java:4.38.0")
|
||||
api("org.skyscreamer:jsonassert:1.5.3")
|
||||
api("org.testng:testng:7.11.0")
|
||||
api("org.webjars:underscorejs:1.8.3")
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@ import org.springframework.cache.interceptor.CacheResolver;
|
|||
import org.springframework.cache.interceptor.KeyGenerator;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by @{@link org.springframework.context.annotation.Configuration
|
||||
* Configuration} classes annotated with @{@link EnableCaching} that wish or need to specify
|
||||
* explicitly how caches are resolved and how keys are generated for annotation-driven
|
||||
* cache management.
|
||||
* Interface to be implemented for explicitly specifying how caches are resolved
|
||||
* and how keys are generated for annotation-driven cache management.
|
||||
*
|
||||
* <p>See @{@link EnableCaching} for general examples and context; see
|
||||
* {@link #cacheManager()}, {@link #cacheResolver()}, {@link #keyGenerator()}, and
|
||||
* {@link #errorHandler()} for detailed instructions.
|
||||
* <p>Typically implemented by @{@link org.springframework.context.annotation.Configuration
|
||||
* Configuration} classes annotated with @{@link EnableCaching}.
|
||||
* See @{@link EnableCaching} for general examples and context; see
|
||||
* {@link #cacheManager()}, {@link #cacheResolver()}, {@link #keyGenerator()},
|
||||
* and {@link #errorHandler()} for detailed instructions.
|
||||
*
|
||||
* <p><b>NOTE: A {@code CachingConfigurer} will get initialized early.</b>
|
||||
* Do not inject common dependencies into autowired fields directly; instead, consider
|
||||
|
|
|
|||
|
|
@ -23,13 +23,18 @@ import org.jspecify.annotations.Nullable;
|
|||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by @{@link org.springframework.context.annotation.Configuration
|
||||
* Configuration} classes annotated with @{@link EnableAsync} that wish to customize the
|
||||
* {@link Executor} instance used when processing async method invocations or the
|
||||
* {@link AsyncUncaughtExceptionHandler} instance used to process exception thrown from
|
||||
* async method with {@code void} return type.
|
||||
* Interface to be implemented for customizing the {@link Executor} instance used when
|
||||
* processing async method invocations or the {@link AsyncUncaughtExceptionHandler}
|
||||
* instance used to process exceptions thrown from async methods with a {@code void}
|
||||
* return type.
|
||||
*
|
||||
* <p>See @{@link EnableAsync} for usage examples.
|
||||
* <p>Typically implemented by @{@link org.springframework.context.annotation.Configuration
|
||||
* Configuration} classes annotated with @{@link EnableAsync}.
|
||||
* See the @{@link EnableAsync} javadoc for usage examples.
|
||||
*
|
||||
* <p><b>NOTE: An {@code AsyncConfigurer} will get initialized early.</b>
|
||||
* Do not inject common dependencies into autowired fields directly; instead, consider
|
||||
* declaring a lazy {@link org.springframework.beans.factory.ObjectProvider} for those.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Stephane Nicoll
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ import org.springframework.util.ReflectionUtils;
|
|||
* @author Sebastien Deleuze
|
||||
* @since 6.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {
|
||||
|
||||
private static final boolean JPA_PRESENT = ClassUtils.isPresent("jakarta.persistence.Entity",
|
||||
|
|
@ -82,12 +81,12 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static final class JpaManagedTypesBeanRegistrationCodeFragments extends BeanRegistrationCodeFragmentsDecorator {
|
||||
|
||||
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);
|
||||
|
||||
|
||||
private static final ParameterizedTypeName LIST_OF_STRINGS_TYPE = ParameterizedTypeName.get(List.class, String.class);
|
||||
|
||||
private final RegisteredBean registeredBean;
|
||||
|
|
@ -102,8 +101,8 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
|
|||
|
||||
@Override
|
||||
public CodeBlock generateInstanceSupplierCode(GenerationContext generationContext,
|
||||
BeanRegistrationCode beanRegistrationCode,
|
||||
boolean allowDirectSupplierShortcut) {
|
||||
BeanRegistrationCode beanRegistrationCode, boolean allowDirectSupplierShortcut) {
|
||||
|
||||
PersistenceManagedTypes persistenceManagedTypes = this.registeredBean.getBeanFactory()
|
||||
.getBean(this.registeredBean.getBeanName(), PersistenceManagedTypes.class);
|
||||
contributeHints(generationContext.getRuntimeHints(),
|
||||
|
|
@ -140,7 +139,7 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
|
|||
contributeHibernateHints(hints, classLoader, managedClass);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new IllegalArgumentException("Failed to instantiate the managed class: " + managedClassName, ex);
|
||||
throw new IllegalArgumentException("Failed to instantiate JPA managed class: " + managedClassName, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -149,7 +148,8 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
|
|||
EntityListeners entityListeners = AnnotationUtils.findAnnotation(managedClass, EntityListeners.class);
|
||||
if (entityListeners != null) {
|
||||
for (Class<?> entityListener : entityListeners.value()) {
|
||||
hints.reflection().registerType(entityListener, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS);
|
||||
hints.reflection().registerType(entityListener,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -169,12 +169,14 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
|
|||
}
|
||||
Convert convertClassAnnotation = AnnotationUtils.findAnnotation(managedClass, Convert.class);
|
||||
if (convertClassAnnotation != null) {
|
||||
reflectionHints.registerType(convertClassAnnotation.converter(), MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
||||
reflectionHints.registerType(convertClassAnnotation.converter(),
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
||||
}
|
||||
ReflectionUtils.doWithFields(managedClass, field -> {
|
||||
Convert convertFieldAnnotation = AnnotationUtils.findAnnotation(field, Convert.class);
|
||||
if (convertFieldAnnotation != null && convertFieldAnnotation.converter() != AttributeConverter.class) {
|
||||
reflectionHints.registerType(convertFieldAnnotation.converter(), MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
||||
reflectionHints.registerType(convertFieldAnnotation.converter(),
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -186,11 +188,11 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
|
|||
method -> CALLBACK_TYPES.stream().anyMatch(method::isAnnotationPresent));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void contributeHibernateHints(RuntimeHints hints, @Nullable ClassLoader classLoader, Class<?> managedClass) {
|
||||
ReflectionHints reflection = hints.reflection();
|
||||
|
||||
Class<? extends Annotation> embeddableInstantiatorClass = loadClass("org.hibernate.annotations.EmbeddableInstantiator", classLoader);
|
||||
Class<? extends Annotation> embeddableInstantiatorClass =
|
||||
loadClass("org.hibernate.annotations.EmbeddableInstantiator", classLoader);
|
||||
if (embeddableInstantiatorClass != null) {
|
||||
registerForReflection(reflection,
|
||||
AnnotationUtils.findAnnotation(managedClass, embeddableInstantiatorClass), "value");
|
||||
|
|
@ -204,7 +206,8 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
|
|||
AnnotationUtils.findAnnotation(method, embeddableInstantiatorClass), "value"));
|
||||
}
|
||||
|
||||
Class<? extends Annotation> valueGenerationTypeClass = loadClass("org.hibernate.annotations.ValueGenerationType", classLoader);
|
||||
Class<? extends Annotation> valueGenerationTypeClass =
|
||||
loadClass("org.hibernate.annotations.ValueGenerationType", classLoader);
|
||||
if (valueGenerationTypeClass != null) {
|
||||
ReflectionUtils.doWithFields(managedClass, field -> registerForReflection(reflection,
|
||||
AnnotationUtils.findAnnotation(field, valueGenerationTypeClass), "generatedBy"));
|
||||
|
|
@ -212,7 +215,8 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
|
|||
AnnotationUtils.findAnnotation(method, valueGenerationTypeClass), "generatedBy"));
|
||||
}
|
||||
|
||||
Class<? extends Annotation> idGeneratorTypeClass = loadClass("org.hibernate.annotations.IdGeneratorType", classLoader);
|
||||
Class<? extends Annotation> idGeneratorTypeClass =
|
||||
loadClass("org.hibernate.annotations.IdGeneratorType", classLoader);
|
||||
if (idGeneratorTypeClass != null) {
|
||||
ReflectionUtils.doWithFields(managedClass, field -> registerForReflection(reflection,
|
||||
AnnotationUtils.findAnnotation(field, idGeneratorTypeClass), "value"));
|
||||
|
|
@ -220,7 +224,8 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
|
|||
AnnotationUtils.findAnnotation(method, idGeneratorTypeClass), "value"));
|
||||
}
|
||||
|
||||
Class<? extends Annotation> attributeBinderTypeClass = loadClass("org.hibernate.annotations.AttributeBinderType", classLoader);
|
||||
Class<? extends Annotation> attributeBinderTypeClass =
|
||||
loadClass("org.hibernate.annotations.AttributeBinderType", classLoader);
|
||||
if (attributeBinderTypeClass != null) {
|
||||
ReflectionUtils.doWithFields(managedClass, field -> registerForReflection(reflection,
|
||||
AnnotationUtils.findAnnotation(field, attributeBinderTypeClass), "binder"));
|
||||
|
|
@ -229,6 +234,7 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static @Nullable Class<? extends Annotation> loadClass(String className, @Nullable ClassLoader classLoader) {
|
||||
try {
|
||||
return (Class<? extends Annotation>) ClassUtils.forName(className, classLoader);
|
||||
|
|
@ -238,7 +244,7 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("NullAway") // Not null assertion performed in ReflectionHints.registerType
|
||||
@SuppressWarnings("NullAway") // Not-null assertion performed in ReflectionHints.registerType
|
||||
private void registerForReflection(ReflectionHints reflection, @Nullable Annotation annotation, String attribute) {
|
||||
if (annotation == null) {
|
||||
return;
|
||||
|
|
@ -247,4 +253,5 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
|
|||
reflection.registerType(type, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,8 +66,7 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
|
|||
GenericApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.registerBean(JpaDomainConfiguration.class);
|
||||
compile(context, (initializer, compiled) -> {
|
||||
GenericApplicationContext freshApplicationContext = toFreshApplicationContext(
|
||||
initializer);
|
||||
GenericApplicationContext freshApplicationContext = toFreshApplicationContext(initializer);
|
||||
PersistenceManagedTypes persistenceManagedTypes = freshApplicationContext.getBean(
|
||||
"persistenceManagedTypes", PersistenceManagedTypes.class);
|
||||
assertThat(persistenceManagedTypes.getManagedClassNames()).containsExactlyInAnyOrder(
|
||||
|
|
@ -121,6 +120,7 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
|
|||
@SuppressWarnings("unchecked")
|
||||
private void compile(GenericApplicationContext applicationContext,
|
||||
BiConsumer<ApplicationContextInitializer<GenericApplicationContext>, Compiled> result) {
|
||||
|
||||
ApplicationContextAotGenerator generator = new ApplicationContextAotGenerator();
|
||||
TestGenerationContext generationContext = new TestGenerationContext();
|
||||
generator.processAheadOfTime(applicationContext, generationContext);
|
||||
|
|
@ -131,6 +131,7 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
|
|||
|
||||
private GenericApplicationContext toFreshApplicationContext(
|
||||
ApplicationContextInitializer<GenericApplicationContext> initializer) {
|
||||
|
||||
GenericApplicationContext freshApplicationContext = new GenericApplicationContext();
|
||||
initializer.initialize(freshApplicationContext);
|
||||
freshApplicationContext.refresh();
|
||||
|
|
@ -145,24 +146,6 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
|
|||
}
|
||||
|
||||
|
||||
public static class JpaDomainConfiguration extends AbstractEntityManagerWithPackagesToScanConfiguration {
|
||||
|
||||
@Override
|
||||
protected String packageToScan() {
|
||||
return "org.springframework.orm.jpa.domain";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class HibernateDomainConfiguration extends AbstractEntityManagerWithPackagesToScanConfiguration {
|
||||
|
||||
@Override
|
||||
protected String packageToScan() {
|
||||
return "org.springframework.orm.jpa.hibernate.domain";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public abstract static class AbstractEntityManagerWithPackagesToScanConfiguration {
|
||||
|
||||
protected boolean scanningInvoked;
|
||||
|
|
@ -182,13 +165,13 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
|
|||
@Bean
|
||||
public PersistenceManagedTypes persistenceManagedTypes(ResourceLoader resourceLoader) {
|
||||
this.scanningInvoked = true;
|
||||
return new PersistenceManagedTypesScanner(resourceLoader)
|
||||
.scan(packageToScan());
|
||||
return new PersistenceManagedTypesScanner(resourceLoader).scan(packageToScan());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
|
||||
JpaVendorAdapter jpaVendorAdapter, PersistenceManagedTypes persistenceManagedTypes) {
|
||||
|
||||
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
|
||||
entityManagerFactoryBean.setDataSource(dataSource);
|
||||
entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
|
||||
|
|
@ -199,4 +182,22 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
|
|||
protected abstract String packageToScan();
|
||||
}
|
||||
|
||||
|
||||
public static class JpaDomainConfiguration extends AbstractEntityManagerWithPackagesToScanConfiguration {
|
||||
|
||||
@Override
|
||||
protected String packageToScan() {
|
||||
return "org.springframework.orm.jpa.domain";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class HibernateDomainConfiguration extends AbstractEntityManagerWithPackagesToScanConfiguration {
|
||||
|
||||
@Override
|
||||
protected String packageToScan() {
|
||||
return "org.springframework.orm.jpa.hibernate.domain";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,15 +19,17 @@ package org.springframework.transaction.annotation;
|
|||
import org.springframework.transaction.TransactionManager;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by @{@link org.springframework.context.annotation.Configuration
|
||||
* Configuration} classes annotated with @{@link EnableTransactionManagement} that wish to
|
||||
* (or need to) explicitly specify the default {@code PlatformTransactionManager} bean
|
||||
* (or {@code ReactiveTransactionManager} bean) to be used for annotation-driven
|
||||
* transaction management, as opposed to the default approach of a by-type lookup.
|
||||
* One reason this might be necessary is if there are two {@code PlatformTransactionManager}
|
||||
* beans (or two {@code ReactiveTransactionManager} beans) present in the container.
|
||||
* Interface to be implemented for explicitly specifying the default
|
||||
* {@link org.springframework.transaction.PlatformTransactionManager} bean
|
||||
* (or {@link org.springframework.transaction.ReactiveTransactionManager} bean)
|
||||
* to be used for annotation-driven transaction management, as opposed to the
|
||||
* default approach of a by-type lookup. One reason this might be necessary is
|
||||
* if there are two {@code PlatformTransactionManager} beans (or two
|
||||
* {@code ReactiveTransactionManager} beans) present in the container.
|
||||
*
|
||||
* <p>See @{@link EnableTransactionManagement} for general examples and context;
|
||||
* <p>Typically implemented by @{@link org.springframework.context.annotation.Configuration
|
||||
* Configuration} classes annotated with @{@link EnableTransactionManagement}.
|
||||
* See @{@link EnableTransactionManagement} for general examples and context;
|
||||
* see {@link #annotationDrivenTransactionManager()} for detailed instructions.
|
||||
*
|
||||
* <p><b>NOTE: A {@code TransactionManagementConfigurer} will get initialized early.</b>
|
||||
|
|
|
|||
Loading…
Reference in New Issue