|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2020 the original author or authors. |
| 2 | + * Copyright 2002-2021 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
16 | 16 |
|
17 | 17 | package org.springframework.cache.annotation;
|
18 | 18 |
|
19 |
| -import java.util.Collection; |
| 19 | +import java.util.List; |
| 20 | +import java.util.function.Function; |
20 | 21 | import java.util.function.Supplier;
|
| 22 | +import java.util.stream.Collectors; |
21 | 23 |
|
| 24 | +import org.springframework.beans.factory.ObjectProvider; |
22 | 25 | import org.springframework.beans.factory.annotation.Autowired;
|
23 | 26 | import org.springframework.cache.CacheManager;
|
24 | 27 | import org.springframework.cache.interceptor.CacheErrorHandler;
|
|
30 | 33 | import org.springframework.core.type.AnnotationMetadata;
|
31 | 34 | import org.springframework.lang.Nullable;
|
32 | 35 | import org.springframework.util.CollectionUtils;
|
| 36 | +import org.springframework.util.function.SingletonSupplier; |
33 | 37 |
|
34 | 38 | /**
|
35 | 39 | * Abstract base {@code @Configuration} class providing common structure
|
@@ -70,29 +74,60 @@ public void setImportMetadata(AnnotationMetadata importMetadata) {
|
70 | 74 | }
|
71 | 75 | }
|
72 | 76 |
|
73 |
| - @Autowired(required = false) |
74 |
| - void setConfigurers(Collection<CachingConfigurer> configurers) { |
75 |
| - if (CollectionUtils.isEmpty(configurers)) { |
76 |
| - return; |
77 |
| - } |
78 |
| - if (configurers.size() > 1) { |
79 |
| - throw new IllegalStateException(configurers.size() + " implementations of " + |
80 |
| - "CachingConfigurer were found when only 1 was expected. " + |
81 |
| - "Refactor the configuration such that CachingConfigurer is " + |
82 |
| - "implemented only once or not at all."); |
83 |
| - } |
84 |
| - CachingConfigurer configurer = configurers.iterator().next(); |
85 |
| - useCachingConfigurer(configurer); |
| 77 | + @Autowired |
| 78 | + void setConfigurers(ObjectProvider<CachingConfigurer> configurers) { |
| 79 | + Supplier<CachingConfigurer> cachingConfigurer = () -> { |
| 80 | + List<CachingConfigurer> candidates = configurers.stream().collect(Collectors.toList()); |
| 81 | + if (CollectionUtils.isEmpty(candidates)) { |
| 82 | + return null; |
| 83 | + } |
| 84 | + if (candidates.size() > 1) { |
| 85 | + throw new IllegalStateException(candidates.size() + " implementations of " + |
| 86 | + "CachingConfigurer were found when only 1 was expected. " + |
| 87 | + "Refactor the configuration such that CachingConfigurer is " + |
| 88 | + "implemented only once or not at all."); |
| 89 | + } |
| 90 | + return candidates.get(0); |
| 91 | + }; |
| 92 | + useCachingConfigurer(new CachingConfigurerSupplier(cachingConfigurer)); |
86 | 93 | }
|
87 | 94 |
|
88 | 95 | /**
|
89 | 96 | * Extract the configuration from the nominated {@link CachingConfigurer}.
|
90 | 97 | */
|
91 |
| - protected void useCachingConfigurer(CachingConfigurer config) { |
92 |
| - this.cacheManager = config::cacheManager; |
93 |
| - this.cacheResolver = config::cacheResolver; |
94 |
| - this.keyGenerator = config::keyGenerator; |
95 |
| - this.errorHandler = config::errorHandler; |
| 98 | + protected void useCachingConfigurer(CachingConfigurerSupplier cachingConfigurerSupplier) { |
| 99 | + this.cacheManager = cachingConfigurerSupplier.adapt(CachingConfigurer::cacheManager); |
| 100 | + this.cacheResolver = cachingConfigurerSupplier.adapt(CachingConfigurer::cacheResolver); |
| 101 | + this.keyGenerator = cachingConfigurerSupplier.adapt(CachingConfigurer::keyGenerator); |
| 102 | + this.errorHandler = cachingConfigurerSupplier.adapt(CachingConfigurer::errorHandler); |
| 103 | + } |
| 104 | + |
| 105 | + |
| 106 | + protected static class CachingConfigurerSupplier { |
| 107 | + |
| 108 | + private final Supplier<CachingConfigurer> supplier; |
| 109 | + |
| 110 | + public CachingConfigurerSupplier(Supplier<CachingConfigurer> supplier) { |
| 111 | + this.supplier = SingletonSupplier.of(supplier); |
| 112 | + } |
| 113 | + |
| 114 | + /** |
| 115 | + * Adapt the {@link CachingConfigurer} supplier to another supplier |
| 116 | + * provided by the specified mapping function. If the underlying |
| 117 | + * {@link CachingConfigurer} is {@code null}, {@code null} is returned |
| 118 | + * and the mapping function is not invoked. |
| 119 | + * @param provider the provider to use to adapt the supplier |
| 120 | + * @param <T> the type of the supplier |
| 121 | + * @return another supplier mapped by the specified function |
| 122 | + */ |
| 123 | + @Nullable |
| 124 | + public <T> Supplier<T> adapt(Function<CachingConfigurer, T> provider) { |
| 125 | + return () -> { |
| 126 | + CachingConfigurer cachingConfigurer = this.supplier.get(); |
| 127 | + return (cachingConfigurer != null) ? provider.apply(cachingConfigurer) : null; |
| 128 | + }; |
| 129 | + } |
| 130 | + |
96 | 131 | }
|
97 | 132 |
|
98 | 133 | }
|
0 commit comments