Skip to content

Commit 21ff2a7

Browse files
Introduce infrastructure for AOT processing of repository declarations
This commit introduces initial support for framework 6 bases ahead of time processing of data components and adds extension points for module implementations. See: #2593 Original Pull Request: #2624
1 parent 8b560f9 commit 21ff2a7

File tree

72 files changed

+4664
-147
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+4664
-147
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2022. the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data;
17+
18+
import java.util.ArrayList;
19+
import java.util.List;
20+
import java.util.function.Consumer;
21+
import java.util.function.Supplier;
22+
import java.util.stream.Stream;
23+
24+
import org.springframework.data.util.Lazy;
25+
26+
/**
27+
* Types managed by a Spring Data implementation. Used to predefine a set of know entities that might need processing
28+
* during container/repository initialization phase.
29+
*
30+
* @author Christoph Strobl
31+
* @since 3.0
32+
*/
33+
public interface ManagedTypes {
34+
35+
void forEach(Consumer<Class<?>> action);
36+
37+
default List<Class<?>> toList() {
38+
39+
List<Class<?>> tmp = new ArrayList<>(100);
40+
forEach(tmp::add);
41+
return tmp;
42+
}
43+
44+
static ManagedTypes of(Iterable<? extends Class<?>> types) {
45+
return types::forEach;
46+
}
47+
48+
static ManagedTypes of(Stream<? extends Class<?>> types) {
49+
return types::forEach;
50+
}
51+
52+
static ManagedTypes o(Supplier<Iterable<? extends Class<?>>> dataProvider) {
53+
54+
return new ManagedTypes() {
55+
56+
Lazy<Iterable<? extends Class<?>>> lazyProvider = Lazy.of(dataProvider);
57+
58+
@Override
59+
public void forEach(Consumer<Class<?>> action) {
60+
lazyProvider.get().forEach(action);
61+
}
62+
};
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/*
2+
* Copyright 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.aot;
17+
18+
import java.lang.annotation.Annotation;
19+
import java.util.Collection;
20+
import java.util.Optional;
21+
import java.util.Set;
22+
import java.util.function.Consumer;
23+
24+
import org.springframework.beans.factory.BeanFactory;
25+
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
26+
import org.springframework.beans.factory.config.BeanDefinition;
27+
import org.springframework.beans.factory.config.BeanReference;
28+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
29+
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
30+
import org.springframework.beans.factory.support.RootBeanDefinition;
31+
import org.springframework.lang.Nullable;
32+
import org.springframework.util.Assert;
33+
import org.springframework.util.ClassUtils;
34+
import org.springframework.util.ObjectUtils;
35+
36+
/**
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!
41+
*
42+
* @author Christoph Strobl
43+
*/
44+
public interface AotContext {
45+
46+
/**
47+
* Create an {@link AotContext} backed by the given {@link BeanFactory}.
48+
*
49+
* @param beanFactory must not be {@literal null}.
50+
* @return new instance of {@link AotContext}.
51+
*/
52+
static AotContext context(BeanFactory beanFactory) {
53+
54+
Assert.notNull(beanFactory, "BeanFactory must not be null!");
55+
56+
return new AotContext() {
57+
58+
private final ConfigurableListableBeanFactory bf = beanFactory instanceof ConfigurableListableBeanFactory
59+
? (ConfigurableListableBeanFactory) beanFactory
60+
: new DefaultListableBeanFactory(beanFactory);
61+
62+
@Override
63+
public ConfigurableListableBeanFactory getBeanFactory() {
64+
return bf;
65+
}
66+
};
67+
}
68+
69+
ConfigurableListableBeanFactory getBeanFactory();
70+
71+
default ClassLoader getClassLoader() {
72+
return getBeanFactory().getBeanClassLoader();
73+
}
74+
75+
default boolean isTypePresent(String typeName) {
76+
return ClassUtils.isPresent(typeName, getBeanFactory().getBeanClassLoader());
77+
}
78+
79+
default TypeScanner getTypeScanner() {
80+
return new TypeScanner(getClassLoader());
81+
}
82+
83+
default Set<Class<?>> scanPackageForTypes(Collection<Class<? extends Annotation>> identifyingAnnotations,
84+
Collection<String> packageNames) {
85+
return getTypeScanner().scanForTypesAnnotatedWith(identifyingAnnotations).inPackages(packageNames);
86+
}
87+
88+
default Optional<Class<?>> resolveType(String typeName) {
89+
90+
if (!isTypePresent(typeName)) {
91+
return Optional.empty();
92+
}
93+
return Optional.of(resolveRequiredType(typeName));
94+
}
95+
96+
default Class<?> resolveRequiredType(String typeName) throws TypeNotPresentException {
97+
try {
98+
return ClassUtils.forName(typeName, getClassLoader());
99+
} catch (ClassNotFoundException e) {
100+
throw new TypeNotPresentException(typeName, e);
101+
}
102+
}
103+
104+
@Nullable
105+
default Class<?> resolveType(BeanReference beanReference) {
106+
return getBeanFactory().getType(beanReference.getBeanName(), false);
107+
}
108+
109+
default BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
110+
return getBeanFactory().getBeanDefinition(beanName);
111+
}
112+
113+
default RootBeanDefinition getRootBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
114+
115+
BeanDefinition val = getBeanFactory().getBeanDefinition(beanName);
116+
if (!(val instanceof RootBeanDefinition)) {
117+
throw new IllegalStateException(String.format("%s is not a root bean", beanName));
118+
}
119+
return RootBeanDefinition.class.cast(val);
120+
}
121+
122+
default boolean isFactoryBean(String beanName) {
123+
return getBeanFactory().isFactoryBean(beanName);
124+
}
125+
126+
default boolean isTransactionManagerPresent() {
127+
128+
return resolveType("org.springframework.transaction.TransactionManager") //
129+
.map(it -> !ObjectUtils.isEmpty(getBeanFactory().getBeanNamesForType(it))) //
130+
.orElse(false);
131+
}
132+
133+
default void ifTypePresent(String typeName, Consumer<Class<?>> action) {
134+
resolveType(typeName).ifPresent(action);
135+
}
136+
137+
default void ifTransactionManagerPresent(Consumer<String[]> beanNamesConsumer) {
138+
139+
ifTypePresent("org.springframework.transaction.TransactionManager", txMgrType -> {
140+
String[] txMgrBeanNames = getBeanFactory().getBeanNamesForType(txMgrType);
141+
if (!ObjectUtils.isEmpty(txMgrBeanNames)) {
142+
beanNamesConsumer.accept(txMgrBeanNames);
143+
}
144+
});
145+
}
146+
}

0 commit comments

Comments
 (0)