【问题标题】:Spring exclude filter弹簧排除过滤器
【发布时间】:2020-12-21 05:27:51
【问题描述】:

application-context.xml 内部:

<context:component-scan base-package="com.myApp">
        <context:exclude-filter type="assignable" expression="com.myApp.MyService"/>
</context:component-scan>

<bean id="myService" class="com.myApp.ExtendedService" />

Main.java 内部:

@SpringBootApplication
@ImportResource(locations = {"classpath:application-context.xml"})
public class Main{
    //...
}

ExtendedService 内部:

@Service
public class ExtendedService extends MyService{
    //...
}

但是当我开始时,我得到 Invalid Bean definition 因为 myService is bound 错误。如何排除原有的MyService?

例外:

原因:org.springframework.beans.factory.support.BeanDefinitionOverrideException:在 URL [file:svc.xml] 中定义的名称为“myService”的 bean 定义无效:无法注册 bean 定义 [通用 bean:类 [com.myApp] .ExtendedService];范围=;摘要=假;懒惰初始化=假;自动线模式=1;依赖检查=0;自动接线候选=真;主要=假;工厂BeanName=空;工厂方法名=空;初始化方法名=空;销毁方法名=空;在 URL [file:svc.xml]] 中为 bean 'myService' 定义:已经有 [Generic bean: class [com.myApp.MyService];范围=单例;摘要=假;懒惰初始化=假;自动线模式=0;依赖检查=0;自动接线候选=真;主要=假;工厂BeanName=空;工厂方法名=空;初始化方法名=空;销毁方法名=空;在 URL [jar:file:/.m2/repository/com/myApp/myLib-1.0.0.jar!/com/myApp/MyService.class]] 中定义。

【问题讨论】:

    标签: java spring


    【解决方案1】:

    @SpringBootApplication 正在对相同(和子)包进行包扫描。这是@Configuration @EnableAutoConfiguration @ComponentScan 的等价物。如果您不想进行包裹扫描,可以由另外 2 个人替换。

    @Configuration
    @EnableAutoConfiguration
    @ImportResource(locations = {"classpath:application-context.xml"})
    public class Main{
        //...
    }
    

    编辑:您可以在 ExtendedService 上使用@Primary,上下文将使用这个而不是 MyService,那么您不需要在扫描中排除。这仅在 MyService 不是主要服务时才有效。

    @Primary
    @Service
    public class ExtendedService extends MyService{
        //...
    }
    

    EDIT2:您不能使用 assignable 排除,因为这两个服务都可以分配给 MyService 使用正则表达式。

    <context:exclude-filter type="regex" expression="com.myApp.MyService"/>
    

    【讨论】:

    • 你能在你的帖子中添加例外吗?
    • 这两个服务都可以分配给MyService,你不能这样排除。您可以将一个定义为@Primary,它将被用来代替另一个。
    【解决方案2】:

    您实际上不必使用 XML 配置,它们仍然受支持,但看起来确实过时了。

    基本上有两种不同的路径可供选择:

    解决方案 1

    仅在满足某些条件(通过属性、类路径中存在的类,甚至自定义逻辑表示)时才使用@Conditional 加载ExtendedService 的bean

    @Service
    @ConditionalOnProperty(name = "feature.x.enabled", havingValue = "true")
    public class ExtendedService extends MyService {
    }
    

    这将导致bean只有在属性提供如下的情况下才会被加载(在application.properties / yaml中或以spring boot识别的任何其他方式):

    feature.x.enabled=true
    

    到目前为止,这是我推荐的最干净的解决方案

    解决方案 2

    另一种解决方案是基于自定义受组件扫描的路径的能力。默认情况下,主类(带有@SpringBootApplication 注释的类所在的包)及其所有级别的所有子包所在的包是同一个包。

    因此,如果您想将此类从组件扫描过程中排除,您可以执行以下操作:

    @SpringBootApplication
    @ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
            classes = ExtendedService .class))
    public class Main {
        public static void main(...) {...}
    }
    

    请注意,您可能需要阅读多种类型的过滤器this tutorial 了解更多信息

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-17
      • 2017-03-18
      • 2017-03-18
      • 2019-01-11
      相关资源
      最近更新 更多