|
28 | 28 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
29 | 29 | import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
30 | 30 | import org.springframework.beans.factory.support.RootBeanDefinition;
|
| 31 | +import org.springframework.lang.NonNull; |
31 | 32 | import org.springframework.lang.Nullable;
|
32 | 33 | import org.springframework.util.Assert;
|
33 | 34 | import org.springframework.util.ClassUtils;
|
34 | 35 | import org.springframework.util.ObjectUtils;
|
35 | 36 |
|
36 | 37 | /**
|
37 |
| - * The context in which the AOT processing happens. Grants access to the {@link ConfigurableListableBeanFactory |
38 |
| - * beanFactory} and {@link ClassLoader}. Holds a few convenience methods to check if a type |
39 |
| - * {@link #isTypePresent(String) is present} and allows resolution of them. <strong>WARNING:</strong> Unstable internal |
40 |
| - * API! |
| 38 | + * The context in which the AOT processing happens. |
| 39 | + * |
| 40 | + * Grants access to the {@link ConfigurableListableBeanFactory beanFactory} and {@link ClassLoader}. Holds a few |
| 41 | + * convenience methods to check if a type {@link #isTypePresent(String) is present} and allows resolution of them. |
| 42 | + * |
| 43 | + * <strong>WARNING:</strong> Unstable internal API! |
41 | 44 | *
|
42 | 45 | * @author Christoph Strobl
|
| 46 | + * @author John Blum |
| 47 | + * @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory |
| 48 | + * @since 3.0 |
43 | 49 | */
|
44 | 50 | public interface AotContext {
|
45 | 51 |
|
46 | 52 | /**
|
47 | 53 | * Create an {@link AotContext} backed by the given {@link BeanFactory}.
|
48 | 54 | *
|
49 |
| - * @param beanFactory must not be {@literal null}. |
50 |
| - * @return new instance of {@link AotContext}. |
| 55 | + * @param beanFactory reference to the {@link BeanFactory}; must not be {@literal null}. |
| 56 | + * @return a new instance of {@link AotContext}. |
| 57 | + * @see BeanFactory |
51 | 58 | */
|
52 |
| - static AotContext context(BeanFactory beanFactory) { |
| 59 | + static AotContext from(@NonNull BeanFactory beanFactory) { |
53 | 60 |
|
54 |
| - Assert.notNull(beanFactory, "BeanFactory must not be null!"); |
| 61 | + Assert.notNull(beanFactory, "BeanFactory must not be null"); |
55 | 62 |
|
56 | 63 | return new AotContext() {
|
57 | 64 |
|
58 | 65 | private final ConfigurableListableBeanFactory bf = beanFactory instanceof ConfigurableListableBeanFactory
|
59 | 66 | ? (ConfigurableListableBeanFactory) beanFactory
|
60 | 67 | : new DefaultListableBeanFactory(beanFactory);
|
61 | 68 |
|
| 69 | + @NonNull |
62 | 70 | @Override
|
63 | 71 | public ConfigurableListableBeanFactory getBeanFactory() {
|
64 | 72 | return bf;
|
65 | 73 | }
|
66 | 74 | };
|
67 | 75 | }
|
68 | 76 |
|
| 77 | + /** |
| 78 | + * Returns a reference to the {@link ConfigurableListableBeanFactory} backing this {@link AotContext}. |
| 79 | + * |
| 80 | + * @return a reference to the {@link ConfigurableListableBeanFactory} backing this {@link AotContext}. |
| 81 | + * @see ConfigurableListableBeanFactory |
| 82 | + */ |
69 | 83 | ConfigurableListableBeanFactory getBeanFactory();
|
70 | 84 |
|
| 85 | + /** |
| 86 | + * Returns the {@link ClassLoader} used by this {@link AotContext} to resolve {@link Class types}. |
| 87 | + * |
| 88 | + * By default, this is the same {@link ClassLoader} used by the {@link BeanFactory} to resolve {@link Class types} |
| 89 | + * declared in bean definitions. |
| 90 | + * |
| 91 | + * @return the {@link ClassLoader} used by this {@link AotContext} to resolve {@link Class types}. |
| 92 | + * @see ConfigurableListableBeanFactory#getBeanClassLoader() |
| 93 | + */ |
| 94 | + @Nullable |
71 | 95 | default ClassLoader getClassLoader() {
|
72 | 96 | return getBeanFactory().getBeanClassLoader();
|
73 | 97 | }
|
74 | 98 |
|
75 |
| - default boolean isTypePresent(String typeName) { |
76 |
| - return ClassUtils.isPresent(typeName, getBeanFactory().getBeanClassLoader()); |
| 99 | + /** |
| 100 | + * Determines whether the given {@link String named} {@link Class type} is present on the application classpath. |
| 101 | + * |
| 102 | + * @param typeName {@link String name} of the {@link Class type} to evaluate; must not be {@literal null}. |
| 103 | + * @return {@literal true} if the given {@link String named} {@link Class type} is present |
| 104 | + * on the application classpath. |
| 105 | + * @see #getClassLoader() |
| 106 | + */ |
| 107 | + default boolean isTypePresent(@NonNull String typeName) { |
| 108 | + return ClassUtils.isPresent(typeName, getClassLoader()); |
77 | 109 | }
|
78 | 110 |
|
| 111 | + /** |
| 112 | + * Returns a new {@link TypeScanner} used to scan for {@link Class types} that will be contributed to the AOT |
| 113 | + * processing infrastructure. |
| 114 | + * |
| 115 | + * @return a {@link TypeScanner} used to scan for {@link Class types} that will be contributed to the AOT |
| 116 | + * processing infrastructure. |
| 117 | + * @see TypeScanner |
| 118 | + */ |
| 119 | + @NonNull |
79 | 120 | default TypeScanner getTypeScanner() {
|
80 | 121 | return new TypeScanner(getClassLoader());
|
81 | 122 | }
|
82 | 123 |
|
83 |
| - default Set<Class<?>> scanPackageForTypes(Collection<Class<? extends Annotation>> identifyingAnnotations, |
| 124 | + /** |
| 125 | + * Scans for {@link Class types} in the given {@link String named packages} annotated with the store-specific |
| 126 | + * {@link Annotation identifying annotations}. |
| 127 | + * |
| 128 | + * @param identifyingAnnotations {@link Collection} of {@link Annotation Annotations} identifying store-specific |
| 129 | + * model {@link Class types}; must not be {@literal null}. |
| 130 | + * @param packageNames {@link Collection} of {@link String package names} to scan. |
| 131 | + * @return a {@link Set} of {@link Class types} found during the scan. |
| 132 | + * @see TypeScanner#scanForTypesAnnotatedWith(Class[]) |
| 133 | + * @see TypeScanner.Scanner#inPackages(Collection) |
| 134 | + * @see #getTypeScanner() |
| 135 | + */ |
| 136 | + default Set<Class<?>> scanPackageForTypes(@NonNull Collection<Class<? extends Annotation>> identifyingAnnotations, |
84 | 137 | Collection<String> packageNames) {
|
| 138 | + |
85 | 139 | return getTypeScanner().scanForTypesAnnotatedWith(identifyingAnnotations).inPackages(packageNames);
|
86 | 140 | }
|
87 | 141 |
|
88 |
| - default Optional<Class<?>> resolveType(String typeName) { |
89 |
| - |
90 |
| - if (!isTypePresent(typeName)) { |
91 |
| - return Optional.empty(); |
92 |
| - } |
93 |
| - return Optional.of(resolveRequiredType(typeName)); |
94 |
| - } |
| 142 | + /** |
| 143 | + * Resolves the required {@link String named} {@link Class type}. |
| 144 | + * |
| 145 | + * @param typeName {@link String} containing the {@literal fully-qualified class name} of the {@link Class type} |
| 146 | + * to resolve; must not be {@literal null}. |
| 147 | + * @return a resolved {@link Class type} for the given, required {@link String name}. |
| 148 | + * @throws TypeNotPresentException if the {@link String named} {@link Class type} cannot be found. |
| 149 | + */ |
| 150 | + @NonNull |
| 151 | + default Class<?> resolveRequiredType(@NonNull String typeName) throws TypeNotPresentException { |
95 | 152 |
|
96 |
| - default Class<?> resolveRequiredType(String typeName) throws TypeNotPresentException { |
97 | 153 | try {
|
98 | 154 | return ClassUtils.forName(typeName, getClassLoader());
|
99 |
| - } catch (ClassNotFoundException e) { |
100 |
| - throw new TypeNotPresentException(typeName, e); |
| 155 | + } catch (ClassNotFoundException cause) { |
| 156 | + throw new TypeNotPresentException(typeName, cause); |
101 | 157 | }
|
102 | 158 | }
|
103 | 159 |
|
| 160 | + /** |
| 161 | + * Resolves the given {@link String named} {@link Class type} if present. |
| 162 | + * |
| 163 | + * @param typeName {@link String} containing the {@literal fully-qualified class name} of the {@link Class type} |
| 164 | + * to resolve; must not be {@literal null}. |
| 165 | + * @return an {@link Optional} value containing the {@link Class type} |
| 166 | + * if the {@link String fully-qualified class name} is present on the application classpath. |
| 167 | + * @see #isTypePresent(String) |
| 168 | + * @see #resolveRequiredType(String) |
| 169 | + * @see java.util.Optional |
| 170 | + */ |
| 171 | + default Optional<Class<?>> resolveType(@NonNull String typeName) { |
| 172 | + |
| 173 | + return isTypePresent(typeName) |
| 174 | + ? Optional.of(resolveRequiredType(typeName)) |
| 175 | + : Optional.empty(); |
| 176 | + } |
| 177 | + |
| 178 | + /** |
| 179 | + * Resolves the {@link BeanDefinition bean's} defined {@link Class type}. |
| 180 | + * |
| 181 | + * @param beanReference {@link BeanReference} to the managed bean. |
| 182 | + * @return the {@link Class type} of the {@link BeanReference referenced bean} if defined; may be {@literal null}. |
| 183 | + * @see BeanReference |
| 184 | + */ |
104 | 185 | @Nullable
|
105 |
| - default Class<?> resolveType(BeanReference beanReference) { |
| 186 | + default Class<?> resolveType(@NonNull BeanReference beanReference) { |
106 | 187 | return getBeanFactory().getType(beanReference.getBeanName(), false);
|
107 | 188 | }
|
108 | 189 |
|
109 |
| - default BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { |
| 190 | + /** |
| 191 | + * Gets the {@link BeanDefinition} for the given, required {@link String named bean}. |
| 192 | + * |
| 193 | + * @param beanName {@link String} containing the {@literal name} of the bean; must not be {@literal null}. |
| 194 | + * @return the {@link BeanDefinition} for the given, required {@link String named bean}. |
| 195 | + * @throws NoSuchBeanDefinitionException if a {@link BeanDefinition} cannot be found for |
| 196 | + * the {@link String named bean}. |
| 197 | + * @see BeanDefinition |
| 198 | + */ |
| 199 | + @NonNull |
| 200 | + default BeanDefinition getBeanDefinition(@NonNull String beanName) throws NoSuchBeanDefinitionException { |
110 | 201 | return getBeanFactory().getBeanDefinition(beanName);
|
111 | 202 | }
|
112 | 203 |
|
113 |
| - default RootBeanDefinition getRootBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { |
| 204 | + /** |
| 205 | + * Gets the {@link RootBeanDefinition} for the given, required {@link String bean name}. |
| 206 | + * |
| 207 | + * @param beanName {@link String} containing the {@literal name} of the bean. |
| 208 | + * @return the {@link RootBeanDefinition} for the given, required {@link String bean name}. |
| 209 | + * @throws NoSuchBeanDefinitionException if a {@link BeanDefinition} cannot be found for |
| 210 | + * the {@link String named bean}. |
| 211 | + * @throws IllegalStateException if the bean is not a {@link RootBeanDefinition root bean}. |
| 212 | + * @see RootBeanDefinition |
| 213 | + */ |
| 214 | + @NonNull |
| 215 | + default RootBeanDefinition getRootBeanDefinition(@NonNull String beanName) throws NoSuchBeanDefinitionException { |
| 216 | + |
| 217 | + BeanDefinition beanDefinition = getBeanDefinition(beanName); |
114 | 218 |
|
115 |
| - BeanDefinition val = getBeanFactory().getBeanDefinition(beanName); |
116 |
| - if (!(val instanceof RootBeanDefinition)) { |
117 |
| - throw new IllegalStateException(String.format("%s is not a root bean", beanName)); |
| 219 | + if (beanDefinition instanceof RootBeanDefinition rootBeanDefinition) { |
| 220 | + return rootBeanDefinition; |
118 | 221 | }
|
119 |
| - return RootBeanDefinition.class.cast(val); |
| 222 | + |
| 223 | + throw new IllegalStateException(String.format("%s is not a root bean", beanName)); |
120 | 224 | }
|
121 | 225 |
|
122 |
| - default boolean isFactoryBean(String beanName) { |
| 226 | + /** |
| 227 | + * Determines whether a bean identified by the given, required {@link String name} is a |
| 228 | + * {@link org.springframework.beans.factory.FactoryBean}. |
| 229 | + * |
| 230 | + * @param beanName {@link String} containing the {@literal name} of the bean to evaluate; |
| 231 | + * must not be {@literal null}. |
| 232 | + * @return {@literal true} if the bean identified by the given, required {@link String name} is a |
| 233 | + * {@link org.springframework.beans.factory.FactoryBean}. |
| 234 | + */ |
| 235 | + default boolean isFactoryBean(@NonNull String beanName) { |
123 | 236 | return getBeanFactory().isFactoryBean(beanName);
|
124 | 237 | }
|
125 | 238 |
|
| 239 | + /** |
| 240 | + * Determines whether a Spring {@link org.springframework.transaction.TransactionManager} is present. |
| 241 | + * |
| 242 | + * @return {@literal true} if a Spring {@link org.springframework.transaction.TransactionManager} is present. |
| 243 | + */ |
126 | 244 | default boolean isTransactionManagerPresent() {
|
127 | 245 |
|
128 |
| - return resolveType("org.springframework.transaction.TransactionManager") // |
129 |
| - .map(it -> !ObjectUtils.isEmpty(getBeanFactory().getBeanNamesForType(it))) // |
130 |
| - .orElse(false); |
| 246 | + return resolveType("org.springframework.transaction.TransactionManager") |
| 247 | + .filter(it -> !ObjectUtils.isEmpty(getBeanFactory().getBeanNamesForType(it))) |
| 248 | + .isPresent(); |
131 | 249 | }
|
132 | 250 |
|
133 |
| - default void ifTypePresent(String typeName, Consumer<Class<?>> action) { |
| 251 | + /** |
| 252 | + * Determines whether the given, required {@link String type name} is declared on the application classpath |
| 253 | + * and performs the given, required {@link Consumer action} if present. |
| 254 | + * |
| 255 | + * @param typeName {@link String name} of the {@link Class type} to process; must not be {@literal null}. |
| 256 | + * @param action {@link Consumer} defining the action to perform on the resolved {@link Class type}; |
| 257 | + * must not be {@literal null}. |
| 258 | + * @see java.util.function.Consumer |
| 259 | + * @see #resolveType(String) |
| 260 | + */ |
| 261 | + default void ifTypePresent(@NonNull String typeName, @NonNull Consumer<Class<?>> action) { |
134 | 262 | resolveType(typeName).ifPresent(action);
|
135 | 263 | }
|
136 | 264 |
|
137 |
| - default void ifTransactionManagerPresent(Consumer<String[]> beanNamesConsumer) { |
| 265 | + /** |
| 266 | + * Runs the given {@link Consumer action} on any {@link org.springframework.transaction.TransactionManager} beans |
| 267 | + * defined in the application context. |
| 268 | + * |
| 269 | + * @param beanNamesConsumer {@link Consumer} defining the action to perform on |
| 270 | + * the {@link org.springframework.transaction.TransactionManager} beans if present; must not be {@literal null}. |
| 271 | + * @see java.util.function.Consumer |
| 272 | + */ |
| 273 | + default void ifTransactionManagerPresent(@NonNull Consumer<String[]> beanNamesConsumer) { |
138 | 274 |
|
139 | 275 | ifTypePresent("org.springframework.transaction.TransactionManager", txMgrType -> {
|
140 | 276 | String[] txMgrBeanNames = getBeanFactory().getBeanNamesForType(txMgrType);
|
|
0 commit comments