Introduce @RegisterReflectionForBinding
This annotation and the related processor allows to register reflection hints for data binding purpose (class, fields, properties, record components for the whole type hierarchy) Closes gh-28979
This commit is contained in:
		
							parent
							
								
									aaffb8b27e
								
							
						
					
					
						commit
						044f3728a3
					
				| 
						 | 
				
			
			@ -0,0 +1,60 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.aot.hint.annotation;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.Documented;
 | 
			
		||||
import java.lang.annotation.ElementType;
 | 
			
		||||
import java.lang.annotation.Retention;
 | 
			
		||||
import java.lang.annotation.RetentionPolicy;
 | 
			
		||||
import java.lang.annotation.Target;
 | 
			
		||||
 | 
			
		||||
import org.springframework.core.annotation.AliasFor;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Indicates that one or more {@link Class} reflection hints should be registered for
 | 
			
		||||
 * data binding purpose (class, fields, properties, record components for the whole
 | 
			
		||||
 * type hierarchy).
 | 
			
		||||
 *
 | 
			
		||||
 * <p>Typically used to annotate the bean class or bean method where the reflection hint
 | 
			
		||||
 * is needed.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sebastien Deleuze
 | 
			
		||||
 * @since 6.0
 | 
			
		||||
 */
 | 
			
		||||
@Target({ ElementType.TYPE, ElementType.METHOD })
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Documented
 | 
			
		||||
@Reflective(RegisterReflectionForBindingProcessor.class)
 | 
			
		||||
public @interface RegisterReflectionForBinding {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Classes for which reflection hints should be registered to enable data binding
 | 
			
		||||
	 * (class, fields, properties, record components for the whole type hierarchy).
 | 
			
		||||
	 * @see #classes()
 | 
			
		||||
	 */
 | 
			
		||||
	@AliasFor("classes")
 | 
			
		||||
	Class<?>[] value() default {};
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Classes for which reflection hints should be registered to enable data binding
 | 
			
		||||
	 * (class, fields, properties, record components for the whole type hierarchy).
 | 
			
		||||
	 * @see #value()
 | 
			
		||||
	 */
 | 
			
		||||
	@AliasFor("value")
 | 
			
		||||
	Class<?>[] classes() default {};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.aot.hint.annotation;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.AnnotatedElement;
 | 
			
		||||
 | 
			
		||||
import org.springframework.aot.hint.ReflectionHints;
 | 
			
		||||
import org.springframework.core.annotation.AnnotationUtils;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A {@link ReflectiveProcessor} implementation that registers reflection hints
 | 
			
		||||
 * for data binding purpose (class, constructors, fields, properties, record
 | 
			
		||||
 * components for the whole type hierarchy).
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sebastien Deleuze
 | 
			
		||||
 * @since 6.0
 | 
			
		||||
 */
 | 
			
		||||
public class RegisterReflectionForBindingProcessor implements ReflectiveProcessor {
 | 
			
		||||
 | 
			
		||||
	private final BindingReflectionHintsRegistrar bindingRegistrar = new BindingReflectionHintsRegistrar();
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void registerReflectionHints(ReflectionHints hints, AnnotatedElement element) {
 | 
			
		||||
		RegisterReflectionForBinding registerReflection = AnnotationUtils.getAnnotation(element, RegisterReflectionForBinding.class);
 | 
			
		||||
		if (registerReflection != null) {
 | 
			
		||||
			for (Class<?> type : registerReflection.classes()) {
 | 
			
		||||
				this.bindingRegistrar.registerReflectionHints(hints, type);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,75 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.aot.hint.annotation;
 | 
			
		||||
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
 | 
			
		||||
import org.springframework.aot.hint.RuntimeHints;
 | 
			
		||||
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests for {@link RegisterReflectionForBindingProcessor}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sebastien Deleuze
 | 
			
		||||
 */
 | 
			
		||||
public class RegisterReflectionForBindingProcessorTests {
 | 
			
		||||
 | 
			
		||||
	private final RegisterReflectionForBindingProcessor processor = new RegisterReflectionForBindingProcessor();
 | 
			
		||||
 | 
			
		||||
	private final RuntimeHints hints = new RuntimeHints();
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	void registerReflectionForBindingOnClass() {
 | 
			
		||||
		processor.registerReflectionHints(hints.reflection(), ClassLevelAnnotatedBean.class);
 | 
			
		||||
		assertThat(RuntimeHintsPredicates.reflection().onType(SampleClassWithGetter.class)).accepts(hints);
 | 
			
		||||
		assertThat(RuntimeHintsPredicates.reflection().onType(String.class)).accepts(hints);
 | 
			
		||||
		assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleClassWithGetter.class, "getName")).accepts(hints);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	void registerReflectionForBindingOnMethod() throws NoSuchMethodException {
 | 
			
		||||
		processor.registerReflectionHints(hints.reflection(), MethodLevelAnnotatedBean.class.getMethod("method"));
 | 
			
		||||
		assertThat(RuntimeHintsPredicates.reflection().onType(SampleClassWithGetter.class)).accepts(hints);
 | 
			
		||||
		assertThat(RuntimeHintsPredicates.reflection().onType(String.class)).accepts(hints);
 | 
			
		||||
		assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleClassWithGetter.class, "getName")).accepts(hints);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@RegisterReflectionForBinding(SampleClassWithGetter.class)
 | 
			
		||||
	static class ClassLevelAnnotatedBean {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static class MethodLevelAnnotatedBean {
 | 
			
		||||
 | 
			
		||||
		@RegisterReflectionForBinding(SampleClassWithGetter.class)
 | 
			
		||||
		public void method() {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static class SampleClassWithGetter {
 | 
			
		||||
 | 
			
		||||
		public String getName() {
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public BindingReflectionHintsRegistrarTests.SampleEmptyClass unmanaged() {
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue