|
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