Browse Source
This commit adds reflection hints on fields for classes compiled by AspectJ. Closes gh-31575pull/27229/merge
Sébastien Deleuze
1 year ago
4 changed files with 145 additions and 2 deletions
@ -0,0 +1,58 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2023 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.aop.aspectj.annotation; |
||||||
|
|
||||||
|
import org.springframework.aot.generate.GenerationContext; |
||||||
|
import org.springframework.aot.hint.MemberCategory; |
||||||
|
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.RegisteredBean; |
||||||
|
|
||||||
|
/** |
||||||
|
* An AOT {@link BeanRegistrationAotProcessor} that detects the presence of |
||||||
|
* classes compiled with AspectJ and adds the related required field hints. |
||||||
|
* |
||||||
|
* @author Sebastien Deleuze |
||||||
|
* @since 6.1 |
||||||
|
*/ |
||||||
|
public class AspectJAdvisorBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor { |
||||||
|
|
||||||
|
@Override |
||||||
|
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { |
||||||
|
Class<?> beanClass = registeredBean.getBeanClass(); |
||||||
|
if (AbstractAspectJAdvisorFactory.compiledByAjc(beanClass)) { |
||||||
|
return new AspectJAdvisorContribution(beanClass); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
private static class AspectJAdvisorContribution implements BeanRegistrationAotContribution { |
||||||
|
|
||||||
|
private final Class<?> beanClass; |
||||||
|
|
||||||
|
public AspectJAdvisorContribution(Class<?> beanClass) { |
||||||
|
this.beanClass = beanClass; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) { |
||||||
|
generationContext.getRuntimeHints().reflection().registerType(this.beanClass, MemberCategory.DECLARED_FIELDS); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,5 +1,6 @@ |
|||||||
org.springframework.beans.factory.aot.BeanRegistrationAotProcessor=\ |
org.springframework.beans.factory.aot.BeanRegistrationAotProcessor=\ |
||||||
org.springframework.aop.scope.ScopedProxyBeanRegistrationAotProcessor |
org.springframework.aop.scope.ScopedProxyBeanRegistrationAotProcessor,\ |
||||||
|
org.springframework.aop.aspectj.annotation.AspectJAdvisorBeanRegistrationAotProcessor |
||||||
|
|
||||||
org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor= \ |
org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor= \ |
||||||
org.springframework.aop.aspectj.annotation.AspectJBeanFactoryInitializationAotProcessor |
org.springframework.aop.aspectj.annotation.AspectJBeanFactoryInitializationAotProcessor |
||||||
|
@ -0,0 +1,84 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2023 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.aop.aspectj; |
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
|
||||||
|
import org.springframework.aop.aspectj.annotation.AspectJAdvisorBeanRegistrationAotProcessor; |
||||||
|
import org.springframework.aot.generate.GenerationContext; |
||||||
|
import org.springframework.aot.hint.MemberCategory; |
||||||
|
import org.springframework.aot.hint.RuntimeHints; |
||||||
|
import org.springframework.aot.test.generate.TestGenerationContext; |
||||||
|
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; |
||||||
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory; |
||||||
|
import org.springframework.beans.factory.support.RegisteredBean; |
||||||
|
import org.springframework.beans.factory.support.RootBeanDefinition; |
||||||
|
import org.springframework.lang.Nullable; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
import static org.mockito.Mockito.mock; |
||||||
|
import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.reflection; |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests for {@link AspectJAdvisorBeanRegistrationAotProcessor}. |
||||||
|
* |
||||||
|
* @author Sebastien Deleuze |
||||||
|
*/ |
||||||
|
public class AspectJAdvisorBeanRegistrationAotProcessorTests { |
||||||
|
|
||||||
|
private final GenerationContext generationContext = new TestGenerationContext(); |
||||||
|
|
||||||
|
private final RuntimeHints runtimeHints = this.generationContext.getRuntimeHints(); |
||||||
|
|
||||||
|
@Test |
||||||
|
void shouldProcessesAspectJClass() { |
||||||
|
process(AspectJClass.class); |
||||||
|
assertThat(reflection().onType(AspectJClass.class).withMemberCategory(MemberCategory.DECLARED_FIELDS)) |
||||||
|
.accepts(this.runtimeHints); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void shouldSkipRegularClass() { |
||||||
|
process(RegularClass.class); |
||||||
|
assertThat(this.runtimeHints.reflection().typeHints()).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
void process(Class<?> beanClass) { |
||||||
|
BeanRegistrationAotContribution contribution = createContribution(beanClass); |
||||||
|
if (contribution != null) { |
||||||
|
contribution.applyTo(this.generationContext, mock()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Nullable |
||||||
|
private static BeanRegistrationAotContribution createContribution(Class<?> beanClass) { |
||||||
|
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); |
||||||
|
beanFactory.registerBeanDefinition(beanClass.getName(), new RootBeanDefinition(beanClass)); |
||||||
|
return new AspectJAdvisorBeanRegistrationAotProcessor() |
||||||
|
.processAheadOfTime(RegisteredBean.of(beanFactory, beanClass.getName())); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
static class AspectJClass { |
||||||
|
private static java.lang.Throwable ajc$initFailureCause; |
||||||
|
} |
||||||
|
|
||||||
|
static class RegularClass { |
||||||
|
private static java.lang.Throwable initFailureCause; |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue