Browse Source
This commit allows `@Reflective` to be used on arbitrary types, not only Spring beans. This makes the feature much more powerful as components can be tagged directly. Scanning happens during AOT processing (typically at build-time) when `@ReflectiveScan` is used. Types do not need to have a particular annotation, and types that can't be loaded are ignored. This commit also exposes the infrastructure that does the scanning so that custom code can do the scanning in an AOT contribution if they don't want to rely on the annotation. Closes gh-33132pull/33165/head
25 changed files with 887 additions and 39 deletions
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.docs.core.aot.hints.reflective; |
||||
|
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.annotation.ReflectiveScan; |
||||
|
||||
@Configuration |
||||
@ReflectiveScan("com.example.app") |
||||
public class MyConfiguration { |
||||
} |
||||
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.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.aot.hint.annotation.Reflective; |
||||
import org.springframework.aot.hint.annotation.RegisterReflection; |
||||
import org.springframework.core.annotation.AliasFor; |
||||
|
||||
/** |
||||
* Scan arbitrary types for use of {@link Reflective}. Typically used on |
||||
* {@link Configuration @Configuration} classes but can be added to any bean. |
||||
* Scanning happens during AOT processing, typically at build-time. |
||||
* |
||||
* <p>In the example below, {@code com.example.app} and its subpackages are |
||||
* scanned: <pre><code class="java"> |
||||
* @Configuration |
||||
* @ReflectiveScan("com.example.app") |
||||
* class MyConfiguration { |
||||
* // ...
|
||||
* }</code></pre> |
||||
* |
||||
* <p>Either {@link #basePackageClasses} or {@link #basePackages} (or its alias |
||||
* {@link #value}) may be specified to define specific packages to scan. If specific |
||||
* packages are not defined, scanning will occur recursively beginning with the |
||||
* package of the class that declares this annotation. |
||||
* |
||||
* <p>A type does not need to be annotated at class level to be candidate, and |
||||
* this performs a "deep scan" by loading every class in the target packages and |
||||
* search for {@link Reflective} on types, constructors, methods, and fields. |
||||
* Enclosed classes are candidates as well. Classes that fail to load are |
||||
* ignored. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @see Reflective @Reflective |
||||
* @see RegisterReflection @RegisterReflection |
||||
* @since 6.2 |
||||
*/ |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Target(ElementType.TYPE) |
||||
@Documented |
||||
public @interface ReflectiveScan { |
||||
|
||||
/** |
||||
* Alias for {@link #basePackages}. |
||||
* <p>Allows for more concise annotation declarations if no other attributes |
||||
* are needed — for example, {@code @ReflectiveScan("org.my.pkg")} |
||||
* instead of {@code @ReflectiveScan(basePackages = "org.my.pkg")}. |
||||
*/ |
||||
@AliasFor("basePackages") |
||||
String[] value() default {}; |
||||
|
||||
/** |
||||
* Base packages to scan for reflective usage. |
||||
* <p>{@link #value} is an alias for (and mutually exclusive with) this |
||||
* attribute. |
||||
* <p>Use {@link #basePackageClasses} for a type-safe alternative to |
||||
* String-based package names. |
||||
*/ |
||||
@AliasFor("value") |
||||
String[] basePackages() default {}; |
||||
|
||||
/** |
||||
* Type-safe alternative to {@link #basePackages} for specifying the packages |
||||
* to scan for reflection usage. The package of each class specified will be scanned. |
||||
* <p>Consider creating a special no-op marker class or interface in each package
|
||||
* that serves no purpose other than being referenced by this attribute. |
||||
*/ |
||||
Class<?>[] basePackageClasses() default {}; |
||||
|
||||
} |
||||
@ -0,0 +1,160 @@
@@ -0,0 +1,160 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.aot; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.HashSet; |
||||
import java.util.LinkedHashSet; |
||||
import java.util.Set; |
||||
import java.util.stream.StreamSupport; |
||||
|
||||
import org.springframework.aot.generate.GenerationContext; |
||||
import org.springframework.aot.hint.RuntimeHints; |
||||
import org.springframework.aot.hint.annotation.Reflective; |
||||
import org.springframework.aot.hint.annotation.ReflectiveProcessor; |
||||
import org.springframework.aot.hint.annotation.ReflectiveRuntimeHintsRegistrar; |
||||
import org.springframework.aot.hint.annotation.RegisterReflection; |
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; |
||||
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution; |
||||
import org.springframework.beans.factory.aot.BeanFactoryInitializationCode; |
||||
import org.springframework.beans.factory.config.BeanDefinition; |
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; |
||||
import org.springframework.lang.Nullable; |
||||
import org.springframework.util.ClassUtils; |
||||
|
||||
/** |
||||
* Builder for an {@linkplain BeanFactoryInitializationAotContribution AOT |
||||
* contribution} that detects the presence of {@link Reflective @Reflective} on |
||||
* annotated elements and invoke the underlying {@link ReflectiveProcessor} |
||||
* implementations. |
||||
* |
||||
* <p>Candidates can be provided explicitly or by scanning the classpath. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 6.2 |
||||
* @see Reflective |
||||
* @see RegisterReflection |
||||
*/ |
||||
public class ReflectiveProcessorAotContributionBuilder { |
||||
|
||||
private static final ReflectiveRuntimeHintsRegistrar registrar = new ReflectiveRuntimeHintsRegistrar(); |
||||
|
||||
private final Set<Class<?>> classes = new LinkedHashSet<>(); |
||||
|
||||
|
||||
/** |
||||
* Process the given classes by checking the ones that use {@link Reflective}. |
||||
* <p>A class is candidate if it uses {@link Reflective} directly or via a |
||||
* meta-annotation. Type, fields, constructors, methods and enclosed types |
||||
* are inspected. |
||||
* @param classes the classes to inspect |
||||
*/ |
||||
public ReflectiveProcessorAotContributionBuilder withClasses(Iterable<Class<?>> classes) { |
||||
this.classes.addAll(StreamSupport.stream(classes.spliterator(), false) |
||||
.filter(registrar::isCandidate).toList()); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Process the given classes by checking the ones that use {@link Reflective}. |
||||
* <p>A class is candidate if it uses {@link Reflective} directly or via a |
||||
* meta-annotation. Type, fields, constructors, methods and enclosed types |
||||
* are inspected. |
||||
* @param classes the classes to inspect |
||||
*/ |
||||
public ReflectiveProcessorAotContributionBuilder withClasses(Class<?>[] classes) { |
||||
return withClasses(Arrays.asList(classes)); |
||||
} |
||||
|
||||
/** |
||||
* Scan the given {@code packageNames} and their sub-packages for classes |
||||
* that uses {@link Reflective}. |
||||
* <p>This performs a "deep scan" by loading every class in the specified |
||||
* packages and search for {@link Reflective} on types, constructors, methods, |
||||
* and fields. Enclosed classes are candidates as well. Classes that fail to |
||||
* load are ignored. |
||||
* @param classLoader the classloader to use |
||||
* @param packageNames the package names to scan |
||||
*/ |
||||
public ReflectiveProcessorAotContributionBuilder scan(@Nullable ClassLoader classLoader, String... packageNames) { |
||||
ReflectiveClassPathScanner scanner = new ReflectiveClassPathScanner(classLoader); |
||||
return withClasses(scanner.scan(packageNames)); |
||||
} |
||||
|
||||
@Nullable |
||||
public BeanFactoryInitializationAotContribution build() { |
||||
return (!this.classes.isEmpty() ? new AotContribution(this.classes) : null); |
||||
} |
||||
|
||||
private static class AotContribution implements BeanFactoryInitializationAotContribution { |
||||
|
||||
private final Class<?>[] classes; |
||||
|
||||
public AotContribution(Set<Class<?>> classes) { |
||||
this.classes = classes.toArray(Class<?>[]::new); |
||||
} |
||||
|
||||
@Override |
||||
public void applyTo(GenerationContext generationContext, BeanFactoryInitializationCode beanFactoryInitializationCode) { |
||||
RuntimeHints runtimeHints = generationContext.getRuntimeHints(); |
||||
registrar.registerRuntimeHints(runtimeHints, this.classes); |
||||
} |
||||
|
||||
} |
||||
|
||||
private static class ReflectiveClassPathScanner extends ClassPathScanningCandidateComponentProvider { |
||||
|
||||
@Nullable |
||||
private final ClassLoader classLoader; |
||||
|
||||
ReflectiveClassPathScanner(@Nullable ClassLoader classLoader) { |
||||
super(false); |
||||
this.classLoader = classLoader; |
||||
addIncludeFilter((metadataReader, metadataReaderFactory) -> true); |
||||
} |
||||
|
||||
Class<?>[] scan(String... packageNames) { |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug("Scanning all types for reflective usage from " + Arrays.toString(packageNames)); |
||||
} |
||||
Set<BeanDefinition> candidates = new HashSet<>(); |
||||
for (String packageName : packageNames) { |
||||
candidates.addAll(findCandidateComponents(packageName)); |
||||
} |
||||
return candidates.stream().map(c -> (Class<?>) c.getAttribute("type")).toArray(Class<?>[]::new); |
||||
} |
||||
|
||||
@Override |
||||
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { |
||||
String className = beanDefinition.getBeanClassName(); |
||||
if (className != null) { |
||||
try { |
||||
Class<?> type = ClassUtils.forName(className, this.classLoader); |
||||
beanDefinition.setAttribute("type", type); |
||||
return registrar.isCandidate(type); |
||||
} |
||||
catch (Exception ex) { |
||||
if (logger.isTraceEnabled()) { |
||||
logger.trace("Ignoring '%s' for reflective usage: %s".formatted(className, ex.getMessage())); |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,114 @@
@@ -0,0 +1,114 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.aot; |
||||
|
||||
import java.util.List; |
||||
|
||||
import org.assertj.core.api.InstanceOfAssertFactories; |
||||
import org.assertj.core.api.ObjectArrayAssert; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution; |
||||
import org.springframework.context.testfixture.context.aot.scan.noreflective.ReflectiveNotUsed; |
||||
import org.springframework.context.testfixture.context.aot.scan.reflective.ReflectiveOnConstructor; |
||||
import org.springframework.context.testfixture.context.aot.scan.reflective.ReflectiveOnField; |
||||
import org.springframework.context.testfixture.context.aot.scan.reflective.ReflectiveOnInnerField; |
||||
import org.springframework.context.testfixture.context.aot.scan.reflective.ReflectiveOnInterface; |
||||
import org.springframework.context.testfixture.context.aot.scan.reflective.ReflectiveOnMethod; |
||||
import org.springframework.context.testfixture.context.aot.scan.reflective.ReflectiveOnNestedType; |
||||
import org.springframework.context.testfixture.context.aot.scan.reflective.ReflectiveOnRecord; |
||||
import org.springframework.context.testfixture.context.aot.scan.reflective.ReflectiveOnType; |
||||
import org.springframework.context.testfixture.context.aot.scan.reflective2.Reflective2OnType; |
||||
import org.springframework.context.testfixture.context.aot.scan.reflective2.reflective21.Reflective21OnType; |
||||
import org.springframework.context.testfixture.context.aot.scan.reflective2.reflective22.Reflective22OnType; |
||||
import org.springframework.lang.Nullable; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* Tests for {@link ReflectiveProcessorAotContributionBuilder}. |
||||
* |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
class ReflectiveProcessorAotContributionBuilderTests { |
||||
|
||||
@Test |
||||
void classesWithMatchingCandidates() { |
||||
BeanFactoryInitializationAotContribution contribution = new ReflectiveProcessorAotContributionBuilder() |
||||
.withClasses(List.of(String.class, ReflectiveOnInterface.class, Integer.class)).build(); |
||||
assertDetectedClasses(contribution).containsOnly(ReflectiveOnInterface.class).hasSize(1); |
||||
} |
||||
|
||||
@Test |
||||
void classesWithMatchingCandidatesFiltersDuplicates() { |
||||
BeanFactoryInitializationAotContribution contribution = new ReflectiveProcessorAotContributionBuilder() |
||||
.withClasses(List.of(ReflectiveOnField.class, ReflectiveOnInterface.class, Integer.class)) |
||||
.withClasses(new Class<?>[] { ReflectiveOnInterface.class, ReflectiveOnMethod.class, String.class }) |
||||
.build(); |
||||
assertDetectedClasses(contribution) |
||||
.containsOnly(ReflectiveOnInterface.class, ReflectiveOnField.class, ReflectiveOnMethod.class) |
||||
.hasSize(3); |
||||
} |
||||
|
||||
@Test |
||||
void scanWithMatchingCandidates() { |
||||
String packageName = ReflectiveOnType.class.getPackageName(); |
||||
BeanFactoryInitializationAotContribution contribution = new ReflectiveProcessorAotContributionBuilder() |
||||
.scan(getClass().getClassLoader(), packageName).build(); |
||||
assertDetectedClasses(contribution).containsOnly(ReflectiveOnType.class, ReflectiveOnInterface.class, |
||||
ReflectiveOnRecord.class, ReflectiveOnField.class, ReflectiveOnConstructor.class, |
||||
ReflectiveOnMethod.class, ReflectiveOnNestedType.Nested.class, ReflectiveOnInnerField.Inner.class); |
||||
} |
||||
|
||||
@Test |
||||
void scanWithMatchingCandidatesInSubPackages() { |
||||
String packageName = Reflective2OnType.class.getPackageName(); |
||||
BeanFactoryInitializationAotContribution contribution = new ReflectiveProcessorAotContributionBuilder() |
||||
.scan(getClass().getClassLoader(), packageName).build(); |
||||
assertDetectedClasses(contribution).containsOnly(Reflective2OnType.class, |
||||
Reflective21OnType.class, Reflective22OnType.class); |
||||
} |
||||
|
||||
@Test |
||||
void scanWithNoCandidate() { |
||||
String packageName = ReflectiveNotUsed.class.getPackageName(); |
||||
BeanFactoryInitializationAotContribution contribution = new ReflectiveProcessorAotContributionBuilder() |
||||
.scan(getClass().getClassLoader(), packageName).build(); |
||||
assertThat(contribution).isNull(); |
||||
} |
||||
|
||||
@Test |
||||
void classesAndScanWithDuplicatesFiltersThem() { |
||||
BeanFactoryInitializationAotContribution contribution = new ReflectiveProcessorAotContributionBuilder() |
||||
.withClasses(List.of(ReflectiveOnField.class, ReflectiveOnInterface.class, Integer.class)) |
||||
.withClasses(new Class<?>[] { ReflectiveOnInterface.class, ReflectiveOnMethod.class, String.class }) |
||||
.scan(null, ReflectiveOnType.class.getPackageName()) |
||||
.build(); |
||||
assertDetectedClasses(contribution) |
||||
.containsOnly(ReflectiveOnType.class, ReflectiveOnInterface.class, ReflectiveOnRecord.class, |
||||
ReflectiveOnField.class, ReflectiveOnConstructor.class, ReflectiveOnMethod.class, |
||||
ReflectiveOnNestedType.Nested.class, ReflectiveOnInnerField.Inner.class) |
||||
.hasSize(8); |
||||
} |
||||
|
||||
@SuppressWarnings("rawtypes") |
||||
private ObjectArrayAssert<Class> assertDetectedClasses(@Nullable BeanFactoryInitializationAotContribution contribution) { |
||||
assertThat(contribution).isNotNull(); |
||||
return assertThat(contribution).extracting("classes", InstanceOfAssertFactories.array(Class[].class)); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.testfixture.context.aot.scan.noreflective; |
||||
|
||||
@SuppressWarnings("unused") |
||||
public class ReflectiveNotUsed { |
||||
} |
||||
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.testfixture.context.aot.scan.reflective; |
||||
|
||||
@SuppressWarnings("unused") |
||||
public class Dummy { |
||||
} |
||||
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.testfixture.context.aot.scan.reflective; |
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective; |
||||
|
||||
@SuppressWarnings("unused") |
||||
public class ReflectiveOnConstructor { |
||||
|
||||
private final String name; |
||||
|
||||
public ReflectiveOnConstructor(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
@Reflective |
||||
public ReflectiveOnConstructor(String firstName, String lastName) { |
||||
this("%s %s".formatted(firstName, lastName)); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.testfixture.context.aot.scan.reflective; |
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective; |
||||
|
||||
@SuppressWarnings("unused") |
||||
public class ReflectiveOnField { |
||||
|
||||
private String name; |
||||
|
||||
@Reflective |
||||
private String description; |
||||
|
||||
} |
||||
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.testfixture.context.aot.scan.reflective; |
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective; |
||||
|
||||
@SuppressWarnings("unused") |
||||
public class ReflectiveOnInnerField { |
||||
|
||||
public class Inner { |
||||
|
||||
@Reflective |
||||
private String description; |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.testfixture.context.aot.scan.reflective; |
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective; |
||||
|
||||
@Reflective |
||||
@SuppressWarnings("unused") |
||||
public interface ReflectiveOnInterface { |
||||
} |
||||
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.testfixture.context.aot.scan.reflective; |
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective; |
||||
|
||||
@SuppressWarnings("unused") |
||||
public class ReflectiveOnMethod { |
||||
|
||||
@Reflective |
||||
void doReflection() { } |
||||
} |
||||
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.testfixture.context.aot.scan.reflective; |
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective; |
||||
|
||||
@SuppressWarnings("unused") |
||||
public class ReflectiveOnNestedType { |
||||
|
||||
@Reflective |
||||
public static class Nested {} |
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.testfixture.context.aot.scan.reflective; |
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective; |
||||
|
||||
@Reflective |
||||
@SuppressWarnings("unused") |
||||
public record ReflectiveOnRecord() { |
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.testfixture.context.aot.scan.reflective; |
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective; |
||||
|
||||
@Reflective |
||||
@SuppressWarnings("unused") |
||||
public class ReflectiveOnType { |
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.testfixture.context.aot.scan.reflective2; |
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective; |
||||
|
||||
@Reflective |
||||
@SuppressWarnings("unused") |
||||
public class Reflective2OnType { |
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.testfixture.context.aot.scan.reflective2.reflective21; |
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective; |
||||
|
||||
@Reflective |
||||
@SuppressWarnings("unused") |
||||
public class Reflective21OnType { |
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright 2002-2024 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.context.testfixture.context.aot.scan.reflective2.reflective22; |
||||
|
||||
import org.springframework.aot.hint.annotation.Reflective; |
||||
|
||||
@Reflective |
||||
@SuppressWarnings("unused") |
||||
public class Reflective22OnType { |
||||
} |
||||
Loading…
Reference in new issue