|
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; |
| 19 | +import java.util.Collection; |
22 | 20 |
|
23 | 21 | import org.springframework.beans.BeansException; |
| 22 | +import org.springframework.beans.factory.NoSuchBeanDefinitionException; |
24 | 23 | import org.springframework.beans.factory.config.BeanDefinition; |
25 | 24 | import org.springframework.beans.factory.config.BeanFactoryPostProcessor; |
26 | 25 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; |
27 | 26 | import org.springframework.beans.factory.support.AbstractBeanDefinition; |
28 | 27 | import org.springframework.core.Ordered; |
29 | 28 |
|
30 | 29 | /** |
31 | | - * {@link BeanFactoryPostProcessor} to set the lazy attribute on bean definition. |
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. |
| 30 | + * {@link BeanFactoryPostProcessor} to set lazy-init on bean definitions that not |
| 31 | + * {@link LazyInitializationExcludeFilter excluded} and have not already had a value |
| 32 | + * explicitly set. |
49 | 33 | * |
50 | 34 | * @author Andy Wilkinson |
51 | 35 | * @author Madhura Bhave |
52 | 36 | * @author Tyler Van Gorder |
| 37 | + * @author Phillip Webb |
53 | 38 | * @since 2.2.0 |
| 39 | + * @see LazyInitializationExcludeFilter |
54 | 40 | */ |
55 | 41 | public final class LazyInitializationBeanFactoryPostProcessor implements BeanFactoryPostProcessor, Ordered { |
56 | 42 |
|
57 | 43 | @Override |
58 | 44 | public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { |
59 | | - |
60 | | - List<EagerLoadingBeanDefinitionPredicate> eagerPredicateList = getEagerLoadingPredicatesFromContext( |
61 | | - beanFactory); |
62 | | - |
| 45 | + // Take care not to force the eager init of factory beans when getting filters |
| 46 | + Collection<LazyInitializationExcludeFilter> filters = beanFactory |
| 47 | + .getBeansOfType(LazyInitializationExcludeFilter.class, false, false).values(); |
63 | 48 | for (String beanName : beanFactory.getBeanDefinitionNames()) { |
64 | 49 | BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); |
65 | | - if (eagerPredicateList.stream() |
66 | | - .anyMatch((predicate) -> predicate.test(beanFactory.getType(beanName, false)))) { |
67 | | - continue; |
68 | | - } |
69 | 50 | if (beanDefinition instanceof AbstractBeanDefinition) { |
70 | | - Boolean lazyInit = ((AbstractBeanDefinition) beanDefinition).getLazyInit(); |
71 | | - if (lazyInit != null && !lazyInit) { |
72 | | - continue; |
73 | | - } |
| 51 | + postProcess(beanFactory, filters, beanName, (AbstractBeanDefinition) beanDefinition); |
74 | 52 | } |
75 | | - beanDefinition.setLazyInit(true); |
76 | 53 | } |
77 | 54 | } |
78 | 55 |
|
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); |
| 56 | + private void postProcess(ConfigurableListableBeanFactory beanFactory, |
| 57 | + Collection<LazyInitializationExcludeFilter> filters, String beanName, |
| 58 | + AbstractBeanDefinition beanDefinition) { |
| 59 | + Boolean lazyInit = beanDefinition.getLazyInit(); |
| 60 | + Class<?> beanType = getBeanType(beanFactory, beanName); |
| 61 | + if (lazyInit == null && !isExcluded(filters, beanName, beanDefinition, beanType)) { |
| 62 | + beanDefinition.setLazyInit(true); |
| 63 | + } |
| 64 | + } |
93 | 65 |
|
94 | | - return new ArrayList<>(eagerPredicates.values()); |
| 66 | + private Class<?> getBeanType(ConfigurableListableBeanFactory beanFactory, String beanName) { |
| 67 | + try { |
| 68 | + return beanFactory.getType(beanName, false); |
| 69 | + } |
| 70 | + catch (NoSuchBeanDefinitionException ex) { |
| 71 | + return null; |
| 72 | + } |
| 73 | + } |
95 | 74 |
|
| 75 | + private boolean isExcluded(Collection<LazyInitializationExcludeFilter> filters, String beanName, |
| 76 | + AbstractBeanDefinition beanDefinition, Class<?> beanType) { |
| 77 | + if (beanType != null) { |
| 78 | + for (LazyInitializationExcludeFilter filter : filters) { |
| 79 | + if (filter.isExcluded(beanName, beanDefinition, beanType)) { |
| 80 | + return true; |
| 81 | + } |
| 82 | + } |
| 83 | + } |
| 84 | + return false; |
96 | 85 | } |
97 | 86 |
|
98 | 87 | @Override |
|
0 commit comments