diff --git a/spring-context/src/main/java/org/springframework/cache/annotation/CachingBeanRegistrationAotProcessor.java b/spring-context/src/main/java/org/springframework/cache/annotation/CachingBeanRegistrationAotProcessor.java deleted file mode 100644 index ba0028f879..0000000000 --- a/spring-context/src/main/java/org/springframework/cache/annotation/CachingBeanRegistrationAotProcessor.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2002-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.cache.annotation; - -import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedElement; -import java.util.LinkedHashSet; -import java.util.Set; - -import org.springframework.aop.config.AopConfigUtils; -import org.springframework.aop.framework.AopProxyUtils; -import org.springframework.aot.hint.RuntimeHints; -import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; -import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.RegisteredBean; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.core.annotation.MergedAnnotations; -import org.springframework.util.ClassUtils; -import org.springframework.util.ReflectionUtils; - -/** - * {@link BeanRegistrationAotProcessor} to register runtime hints for beans that use caching annotations to - * enable JDK proxy creation when needed. - * - * @author Sebastien Deleuze - * @since 6.0 - */ -public class CachingBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor { - - private static final Set> CACHE_OPERATION_ANNOTATIONS = new LinkedHashSet<>(8); - - static { - CACHE_OPERATION_ANNOTATIONS.add(Cacheable.class); - CACHE_OPERATION_ANNOTATIONS.add(CacheEvict.class); - CACHE_OPERATION_ANNOTATIONS.add(CachePut.class); - CACHE_OPERATION_ANNOTATIONS.add(Caching.class); - } - - @Override - public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { - if (isCaching(registeredBean.getBeanClass()) && !isClassProxyingForced(registeredBean.getBeanFactory())) { - return (generationContext, beanRegistrationCode) -> registerSpringProxy(registeredBean.getBeanClass(), - generationContext.getRuntimeHints()); - } - return null; - } - - private static boolean isClassProxyingForced(ConfigurableListableBeanFactory beanFactory) { - return beanFactory.containsBean(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME) && - Boolean.TRUE.equals(beanFactory.getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME) - .getPropertyValues().get("proxyTargetClass")); - } - - private boolean isCaching(Class beanClass) { - if (!AnnotationUtils.isCandidateClass(beanClass, CACHE_OPERATION_ANNOTATIONS)) { - return false; - } - Set elements = new LinkedHashSet<>(); - elements.add(beanClass); - ReflectionUtils.doWithMethods(beanClass, elements::add); - for (Class interfaceClass : ClassUtils.getAllInterfacesForClass(beanClass)) { - elements.add(interfaceClass); - ReflectionUtils.doWithMethods(interfaceClass, elements::add); - } - return elements.stream().anyMatch(element -> { - MergedAnnotations mergedAnnotations = MergedAnnotations.from(element, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY); - return CACHE_OPERATION_ANNOTATIONS.stream().anyMatch(mergedAnnotations::isPresent); - }); - } - - private static void registerSpringProxy(Class type, RuntimeHints runtimeHints) { - Class[] proxyInterfaces = ClassUtils.getAllInterfacesForClass(type); - if (proxyInterfaces.length == 0) { - return; - } - runtimeHints.proxies().registerJdkProxy(AopProxyUtils.completeJdkProxyInterfaces(proxyInterfaces)); - } -} diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationPostProcessor.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationPostProcessor.java index 43bff733d9..e24c9a0228 100644 --- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationPostProcessor.java @@ -23,19 +23,14 @@ import jakarta.validation.ValidatorFactory; import org.aopalliance.aop.Advice; import org.springframework.aop.Pointcut; -import org.springframework.aop.framework.AopProxyUtils; import org.springframework.aop.framework.autoproxy.AbstractBeanFactoryAwareAdvisingPostProcessor; import org.springframework.aop.support.DefaultPointcutAdvisor; import org.springframework.aop.support.annotation.AnnotationMatchingPointcut; -import org.springframework.aot.hint.RuntimeHints; -import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.context.annotation.ImportRuntimeHints; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.validation.annotation.Validated; -import org.springframework.validation.beanvalidation.MethodValidationPostProcessor.MethodValidationRuntimeHints; /** * A convenient {@link BeanPostProcessor} implementation that delegates to a @@ -62,7 +57,6 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess * @see jakarta.validation.executable.ExecutableValidator */ @SuppressWarnings("serial") -@ImportRuntimeHints(MethodValidationRuntimeHints.class) public class MethodValidationPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor implements InitializingBean { @@ -131,14 +125,4 @@ public class MethodValidationPostProcessor extends AbstractBeanFactoryAwareAdvis return (validator != null ? new MethodValidationInterceptor(validator) : new MethodValidationInterceptor()); } - - static class MethodValidationRuntimeHints implements RuntimeHintsRegistrar { - - @Override - public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) { - hints.proxies().registerJdkProxy(AopProxyUtils.completeJdkProxyInterfaces(Validator.class)); - } - - } - } diff --git a/spring-context/src/main/resources/META-INF/spring/aot.factories b/spring-context/src/main/resources/META-INF/spring/aot.factories index e6f0e9cb77..7ead6d3fb1 100644 --- a/spring-context/src/main/resources/META-INF/spring/aot.factories +++ b/spring-context/src/main/resources/META-INF/spring/aot.factories @@ -1,5 +1,3 @@ org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor= \ org.springframework.context.aot.ReflectiveProcessorBeanFactoryInitializationAotProcessor -org.springframework.beans.factory.aot.BeanRegistrationAotProcessor= \ -org.springframework.cache.annotation.CachingBeanRegistrationAotProcessor diff --git a/spring-context/src/test/java/org/springframework/cache/annotation/CachingBeanRegistrationAotProcessorTests.java b/spring-context/src/test/java/org/springframework/cache/annotation/CachingBeanRegistrationAotProcessorTests.java deleted file mode 100644 index b72adad5f1..0000000000 --- a/spring-context/src/test/java/org/springframework/cache/annotation/CachingBeanRegistrationAotProcessorTests.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2002-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.cache.annotation; - -import org.junit.jupiter.api.Test; - -import org.springframework.aop.config.AopConfigUtils; -import org.springframework.aop.framework.AopProxyUtils; -import org.springframework.aot.generate.GenerationContext; -import org.springframework.aot.hint.RuntimeHints; -import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; -import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; -import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor; -import org.springframework.beans.factory.aot.BeanRegistrationCode; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.beans.factory.support.RegisteredBean; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.core.testfixture.aot.generate.TestGenerationContext; -import org.springframework.lang.Nullable; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link CachingBeanRegistrationAotProcessor}. - * - * @author Sebastien Deleuze - */ -public class CachingBeanRegistrationAotProcessorTests { - - BeanRegistrationAotProcessor processor = new CachingBeanRegistrationAotProcessor(); - - GenerationContext generationContext = new TestGenerationContext(); - - - @Test - void ignoresNonCachingBean() { - assertThat(createContribution(NonCaching.class, false)).isNull(); - } - - @Test - void contributesProxyForCacheableInterface() { - process(CacheableServiceImpl.class, false); - RuntimeHints runtimeHints = this.generationContext.getRuntimeHints(); - assertThat(RuntimeHintsPredicates.proxies().forInterfaces(AopProxyUtils.completeJdkProxyInterfaces(CacheableServiceInterface.class))).accepts(runtimeHints); - } - - @Test - void ignoresProxyForCacheableInterfaceWithClassProxying() { - assertThat(createContribution(CacheableServiceImpl.class, true)).isNull(); - } - - @Test - void ignoresProxyForCacheableClass() { - assertThat(createContribution(CacheableService.class, true)).isNull(); - } - - @Nullable - private BeanRegistrationAotContribution createContribution(Class beanClass, boolean forceClassProxying) { - DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); - if (forceClassProxying) { - AopConfigUtils.registerAutoProxyCreatorIfNecessary(beanFactory); - AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(beanFactory); - } - beanFactory.registerBeanDefinition(beanClass.getName(), new RootBeanDefinition(beanClass)); - return this.processor.processAheadOfTime(RegisteredBean.of(beanFactory, beanClass.getName())); - } - - private void process(Class beanClass, boolean forceClassProxying) { - BeanRegistrationAotContribution contribution = createContribution(beanClass, forceClassProxying); - assertThat(contribution).isNotNull(); - contribution.applyTo(this.generationContext, mock(BeanRegistrationCode.class)); - } - - static class NonCaching { - } - - interface CacheableServiceInterface { - - @Cacheable - void invoke(); - } - - class CacheableServiceImpl implements CacheableServiceInterface { - - @Override - public void invoke() { - } - } - - class CacheableService { - - @Cacheable - public void invoke() { - } - } -} diff --git a/spring-tx/src/main/java/org/springframework/transaction/annotation/TransactionBeanRegistrationAotProcessor.java b/spring-tx/src/main/java/org/springframework/transaction/annotation/TransactionBeanRegistrationAotProcessor.java index 4eba81592e..4a8cc28114 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/annotation/TransactionBeanRegistrationAotProcessor.java +++ b/spring-tx/src/main/java/org/springframework/transaction/annotation/TransactionBeanRegistrationAotProcessor.java @@ -20,7 +20,6 @@ import java.lang.reflect.AnnotatedElement; import java.util.LinkedHashSet; import java.util.Set; -import org.springframework.aop.framework.AopProxyUtils; import org.springframework.aot.generate.GenerationContext; import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.RuntimeHints; @@ -35,7 +34,7 @@ import org.springframework.util.ReflectionUtils; /** * AOT {@code BeanRegistrationAotProcessor} that detects the presence of * {@link Transactional @Transactional} on annotated elements and creates - * the required proxy and reflection hints. + * the required reflection hints. * * @author Sebastien Deleuze * @since 6.0 @@ -89,7 +88,6 @@ class TransactionBeanRegistrationAotProcessor implements BeanRegistrationAotProc runtimeHints.reflection().registerType(proxyInterface, builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_METHODS)); } - runtimeHints.proxies().registerJdkProxy(AopProxyUtils.completeJdkProxyInterfaces(proxyInterfaces)); } } diff --git a/spring-tx/src/test/java/org/springframework/transaction/annotation/TransactionBeanRegistrationAotProcessorTests.java b/spring-tx/src/test/java/org/springframework/transaction/annotation/TransactionBeanRegistrationAotProcessorTests.java index 81bcdaaa91..94ca524f6b 100644 --- a/spring-tx/src/test/java/org/springframework/transaction/annotation/TransactionBeanRegistrationAotProcessorTests.java +++ b/spring-tx/src/test/java/org/springframework/transaction/annotation/TransactionBeanRegistrationAotProcessorTests.java @@ -18,8 +18,6 @@ package org.springframework.transaction.annotation; import org.junit.jupiter.api.Test; -import org.springframework.aop.SpringProxy; -import org.springframework.aop.framework.Advised; import org.springframework.aot.generate.GenerationContext; import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; @@ -28,7 +26,6 @@ import org.springframework.beans.factory.aot.BeanRegistrationCode; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.core.DecoratingProxy; import org.springframework.core.testfixture.aot.generate.TestGenerationContext; import org.springframework.lang.Nullable; @@ -50,14 +47,12 @@ public class TransactionBeanRegistrationAotProcessorTests { void shouldSkipNonAnnotatedType() { process(NonAnnotatedBean.class); assertThat(this.generationContext.getRuntimeHints().reflection().typeHints()).isEmpty(); - assertThat(this.generationContext.getRuntimeHints().proxies().jdkProxies()).isEmpty(); } @Test void shouldSkipAnnotatedTypeWithNoInterface() { process(NoInterfaceBean.class); assertThat(this.generationContext.getRuntimeHints().reflection().typeHints()).isEmpty(); - assertThat(this.generationContext.getRuntimeHints().proxies().jdkProxies()).isEmpty(); } @Test @@ -65,7 +60,6 @@ public class TransactionBeanRegistrationAotProcessorTests { process(TransactionalOnTypeBean.class); assertThat(RuntimeHintsPredicates.reflection().onType(NonAnnotatedTransactionalInterface.class) .withMemberCategory(MemberCategory.INVOKE_DECLARED_METHODS)).accepts(this.generationContext.getRuntimeHints()); - assertThat(RuntimeHintsPredicates.proxies().forInterfaces(NonAnnotatedTransactionalInterface.class, SpringProxy.class, Advised.class, DecoratingProxy.class)).accepts(this.generationContext.getRuntimeHints()); } @Test @@ -73,7 +67,6 @@ public class TransactionBeanRegistrationAotProcessorTests { process(JakartaTransactionalOnTypeBean.class); assertThat(RuntimeHintsPredicates.reflection().onType(NonAnnotatedTransactionalInterface.class) .withMemberCategory(MemberCategory.INVOKE_DECLARED_METHODS)).accepts(this.generationContext.getRuntimeHints()); - assertThat(RuntimeHintsPredicates.proxies().forInterfaces(NonAnnotatedTransactionalInterface.class, SpringProxy.class, Advised.class, DecoratingProxy.class)).accepts(this.generationContext.getRuntimeHints()); } @Test @@ -81,7 +74,6 @@ public class TransactionBeanRegistrationAotProcessorTests { process(TransactionalOnTypeInterface.class); assertThat(RuntimeHintsPredicates.reflection().onType(TransactionalOnTypeInterface.class) .withMemberCategory(MemberCategory.INVOKE_DECLARED_METHODS)).accepts(this.generationContext.getRuntimeHints()); - assertThat(RuntimeHintsPredicates.proxies().forInterfaces(TransactionalOnTypeInterface.class, SpringProxy.class, Advised.class, DecoratingProxy.class)).accepts(this.generationContext.getRuntimeHints()); } @Test @@ -89,7 +81,6 @@ public class TransactionBeanRegistrationAotProcessorTests { process(TransactionalOnClassMethodBean.class); assertThat(RuntimeHintsPredicates.reflection().onType(NonAnnotatedTransactionalInterface.class) .withMemberCategory(MemberCategory.INVOKE_DECLARED_METHODS)).accepts(this.generationContext.getRuntimeHints()); - assertThat(RuntimeHintsPredicates.proxies().forInterfaces(NonAnnotatedTransactionalInterface.class, SpringProxy.class, Advised.class, DecoratingProxy.class)).accepts(this.generationContext.getRuntimeHints()); } @Test @@ -97,7 +88,6 @@ public class TransactionBeanRegistrationAotProcessorTests { process(TransactionalOnInterfaceMethodBean.class); assertThat(RuntimeHintsPredicates.reflection().onType(TransactionalOnMethodInterface.class) .withMemberCategory(MemberCategory.INVOKE_DECLARED_METHODS)).accepts(this.generationContext.getRuntimeHints()); - assertThat(RuntimeHintsPredicates.proxies().forInterfaces(TransactionalOnMethodInterface.class, SpringProxy.class, Advised.class, DecoratingProxy.class)).accepts(this.generationContext.getRuntimeHints()); } private void process(Class beanClass) {