spring - 如何强制排除递归@ComponentScan拾取的Spring @Configuration
问题描述
我们的顶级@ComponentScan 扫描一个包,该包又包含@ComponentScan,它选择我们想要忽略的@Configuration 类。在顶级 @ComponentScan 上使用 excludeFilters 似乎并没有让我们排除我们想要避免的 @Configuration 。
我们正在尝试向我们的 spring 项目添加一个依赖项,并使用 @ComponentScan 引入我们想要的库。
但是,我们要排除一个 @Configuration 类,因为它包含一个使用 spring 4 中已弃用的 GuavaCache 的 @Bean。我们使用的是 spring 5,因此如果尝试使用该类,则会得到 NoClassDefFoundError。
使用较新的 spring 5 缓存创建我们自己的实现很简单,但无法弄清楚如何排除现有的@Configuration。我们需要扫描的基础包不是包含坏类的包,而是扫描包含带有@ComponentScan 注释的其他类的包,这会导致它被拾取。
我们在顶级 spring-boot Application 类中尝试过的注释,thirdparty.infrastructure.requestcontext 中的类是然后 @ComponentScan 找到我们想要排除的 JwtCacheConfig
@SpringBootApplication
@ComponentScan(basePackages = {
"com.ourpackage",
"thirdparty.infrastructure.requestcontext"},
excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX,
pattern = "fourthparty\\.common\\.jwtvalidation\\.domain\\.config\\..*"))
public class MyApplication
也试过:
@SpringBootApplication
@ComponentScan(basePackages = {
"com.ourpackage",
"thirdparty.infrastructure.requestcontext"},
excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
classes = fourthparty.common.jwtvalidation.domain.config.JwtCacheConfig.class))
public class MyApplication
要忽略的类:
package fourthparty.common.jwtvalidation.domain.config
import com.google.common.cache.CacheBuilder
import org.springframework.beans.factory.annotation.Value
import org.springframework.cache.Cache
import org.springframework.cache.annotation.EnableCaching
import org.springframework.cache.guava.GuavaCache
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.util.concurrent.TimeUnit
@Configuration
@EnableCaching
class JwtCacheConfig {
@Value('${px.cache.jwtPublicKeys.maximumSize:50}')
Integer maximumCacheSize
@Value('${px.cache.jwtPublicKeys.expireAfterWrite:1440}')
Integer expirationTime
@Bean
Cache jwtPublicKeyCache(){
return new GuavaCache('jwtPublicKeys', CacheBuilder.newBuilder()
.maximumSize(maximumCacheSize).expireAfterWrite(expirationTime, TimeUnit.MINUTES).build(), true)
}
}
我们要设置的类
package com.ourpackage.config
import java.time.Duration
import com.github.benmanes.caffeine.cache.Caffeine
import org.springframework.beans.factory.annotation.Value
import org.springframework.cache.Cache
import org.springframework.cache.annotation.EnableCaching
import org.springframework.cache.caffeine.CaffeineCache
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
@Configuration
@EnableCaching
class MyJwtCacheConfig
{
@Value('${px.cache.jwtPublicKeys.maximumSize:50}')
Integer maximumCacheSize
// cache it for 24 hours (60 min * 24 hours)
@Value('${px.cache.jwtPublicKeys.expireAfterWrite:1440}')
Integer expirationTime
@Bean
Cache myJwtPublicKeyCache(){
def cacheMap = Caffeine.newBuilder()
.expireAfterWrite(Duration.ofMinutes(expirationTime))
.maximumSize(maximumCacheSize)
.build()
return new CaffeineCache('jwtPublicKeys', cacheMap, true)
}
}
每次尝试启动应用程序时,我们要排除的那个类仍然会被选中,我们得到:
java.lang.NoClassDefFoundError: org/springframework/cache/guava/GuavaCache
...
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'cacheManager' defined in class path resource [org/springframework/boot/autoconfigure/cache/GenericCacheConfiguration.class]:
Unsatisfied dependency expressed through method 'cacheManager' parameter 0;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'jwtPublicKeyCache' defined in class path resource
[fourthparty/common/jwtvalidation/domain/config/JwtCacheConfig.class]:
Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cache.Cache]:
Factory method 'jwtPublicKeyCache' threw exception;
nested exception is java.lang.NoClassDefFoundError: org/springframework/cache/guava/GuavaCache