首页 > 解决方案 > 如何强制排除递归@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

标签: springspring-bootspring-cache

解决方案


推荐阅读