16
16
17
17
package org .springframework .boot ;
18
18
19
+ import java .util .ArrayList ;
20
+ import java .util .List ;
21
+ import java .util .Map ;
22
+
19
23
import org .springframework .beans .BeansException ;
20
24
import org .springframework .beans .factory .config .BeanDefinition ;
21
25
import org .springframework .beans .factory .config .BeanFactoryPostProcessor ;
26
30
/**
27
31
* {@link BeanFactoryPostProcessor} to set the lazy attribute on bean definition.
28
32
*
33
+ * <P>
34
+ * This processor will not touch a bean definition that has already had its "lazy" flag
35
+ * explicitly set to "false".
36
+ *
37
+ * <P>
38
+ * There are edge cases in which it is not easy to explicitly set the "lazy" flag to
39
+ * "false" (such as in DSLs that dynamically create additional beans) and therefore this
40
+ * class uses a customizer strategy that allows downstream projects to contribute
41
+ * predicates which impact if a class is considered for lazy-loading.
42
+ *
43
+ * <P>
44
+ * Because this is a BeanFactoryPostProcessor, this class does not use dependency
45
+ * injection to collect the customizers. The post processor actually makes two passes
46
+ * through the bean definitions; the first is used to find and instantiate any
47
+ * {@link org.springframework.boot.EagerLoadingBeanDefinitionPredicate} and the second
48
+ * pass is where bean definitions are marked as lazy.
49
+ *
29
50
* @author Andy Wilkinson
30
51
* @author Madhura Bhave
52
+ * @author Tyler Van Gorder
31
53
* @since 2.2.0
32
54
*/
33
55
public final class LazyInitializationBeanFactoryPostProcessor implements BeanFactoryPostProcessor , Ordered {
34
56
35
57
@ Override
36
58
public void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory ) throws BeansException {
37
- for (String name : beanFactory .getBeanDefinitionNames ()) {
38
- BeanDefinition beanDefinition = beanFactory .getBeanDefinition (name );
59
+
60
+ List <EagerLoadingBeanDefinitionPredicate > eagerPredicateList = getEagerLoadingPredicatesFromContext (
61
+ beanFactory );
62
+
63
+ for (String beanName : beanFactory .getBeanDefinitionNames ()) {
64
+ BeanDefinition beanDefinition = beanFactory .getBeanDefinition (beanName );
65
+ if (eagerPredicateList .stream ()
66
+ .anyMatch ((predicate ) -> predicate .test (beanFactory .getType (beanName , false )))) {
67
+ continue ;
68
+ }
39
69
if (beanDefinition instanceof AbstractBeanDefinition ) {
40
70
Boolean lazyInit = ((AbstractBeanDefinition ) beanDefinition ).getLazyInit ();
41
71
if (lazyInit != null && !lazyInit ) {
@@ -46,6 +76,25 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
46
76
}
47
77
}
48
78
79
+ /**
80
+ * This method extracts the list of
81
+ * {@link org.springframework.boot.EagerLoadingBeanDefinitionPredicate} beans from the
82
+ * bean factory. Because this method is called early in the factory life cycle, we
83
+ * take care not to force the eager initialization of factory beans.
84
+ * @param beanFactory bean factory passed into the post-processor.
85
+ * @return a list of {@link EagerLoadingBeanDefinitionPredicate} that can be used to
86
+ * customize the behavior of this processor.
87
+ */
88
+ private List <EagerLoadingBeanDefinitionPredicate > getEagerLoadingPredicatesFromContext (
89
+ ConfigurableListableBeanFactory beanFactory ) {
90
+
91
+ Map <String , EagerLoadingBeanDefinitionPredicate > eagerPredicates = beanFactory
92
+ .getBeansOfType (EagerLoadingBeanDefinitionPredicate .class , false , false );
93
+
94
+ return new ArrayList <>(eagerPredicates .values ());
95
+
96
+ }
97
+
49
98
@ Override
50
99
public int getOrder () {
51
100
return Ordered .HIGHEST_PRECEDENCE ;
0 commit comments