简体   繁体   English

Spring 排除过滤器

[英]Spring exclude filter

Inside application-context.xml:内部应用程序上下文.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" />

Inside Main.java:在 Main.java 内部:

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

Inside ExtendedService:内部扩展服务:

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

But when I start, I get Invalid Bean definition because myService is bound error.但是当我开始时,我得到 Invalid Bean definition because myService is bound 错误。 How to exclude the original MyService?如何排除原来的MyService?

Exception:例外:

Caused by: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'myService' defined in URL [file:svc.xml]: Cannot register bean definition [Generic bean: class [com.myApp.ExtendedService];由以下原因引起:org.springframework.beans.factory.support.BeanDefinitionOverrideException:在 URL [文件:svc.xml] 中定义的名称为“myService”的无效 bean 定义:无法注册 bean 定义 [通用 bean:class [com.myApp.ExtendedService] ; scope=;范围=; abstract=false;摘要=假; lazyInit=false;懒惰初始化=假; autowireMode=1;自动接线模式=1; dependencyCheck=0;依赖检查=0; autowireCandidate=true; autowireCandidate=真; primary=false;初级=假; factoryBeanName=null;工厂BeanName=null; factoryMethodName=null;工厂方法名=空; initMethodName=null;初始化方法名=空; destroyMethodName=null; destroyMethodName=null; defined in URL [file:svc.xml]] for bean 'myService': There is already [Generic bean: class [com.myApp.MyService];在 URL [file:svc.xml]] 中为 bean 'myService' 定义:已经有 [Generic bean: class [com.myApp.MyService]; scope=singleton;范围=单例; abstract=false;摘要=假; lazyInit=false;懒惰初始化=假; autowireMode=0;自动接线模式=0; dependencyCheck=0;依赖检查=0; autowireCandidate=true; autowireCandidate=真; primary=false;初级=假; factoryBeanName=null;工厂BeanName=null; factoryMethodName=null;工厂方法名=空; initMethodName=null;初始化方法名=空; destroyMethodName=null; destroyMethodName=null; defined in URL [jar:file:/.m2/repository/com/myApp/myLib-1.0.0.jar./com/myApp/MyService.class]] bound.定义在 URL [jar:file:/.m2/repository/com/myApp/myLib-1.0.0.jar./com/myApp/MyService.class]] 绑定。

@SpringBootApplication is doing an package scan on the same (and sub) packages. @SpringBootApplication 正在对相同(和子)包进行 package 扫描。 This is the equivqlent of @Configuration @EnableAutoConfiguration @ComponentScan.这相当于@Configuration @EnableAutoConfiguration @ComponentScan。 You can replace by the 2 others if you don't want a package scan.如果您不想进行 package 扫描,可以替换为其他 2 个。

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

EDIT: you can use @Primary on ExtendedService, the context will use this one instead of MyService, then you don't need to exclude in the scan.编辑:您可以在 ExtendedService 上使用 @Primary,上下文将使用这个而不是 MyService,那么您不需要在扫描中排除。 This is working only if MyService is not primary.这仅在 MyService 不是主要服务时才有效。

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

EDIT2: you can't exlude with assignable as both services are assignable to MyService use regex. EDIT2:您不能使用 assignable 排除,因为这两个服务都可以分配给 MyService 使用正则表达式。

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

You don't really have to work with XML configurations, they're still supported but look really outdated.您实际上不必使用 XML 配置,它们仍然受支持,但看起来确实过时了。

Basically there are two different paths you can take:基本上,您可以采用两种不同的路径:

Solution 1解决方案 1

Use @Conditional to load the bean of ExtendedService only when some condition (expressed via property, presence of class in a classpath, or even custom logic) is met只有在满足某些条件(通过属性表示,类路径中存在 class,甚至自定义逻辑)时,才使用@Conditional加载ExtendedService的 bean

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

This will lead to the situation that the bean will be loaded only if the property is supplied as follows (in application.properties / yaml or in any other way that spring boot recognizes):这将导致只有在按如下方式提供属性时才会加载 bean(在 application.properties / yaml 或 spring 引导识别的任何其他方式):

feature.x.enabled=true

By far this is the cleanest solution I can recommend到目前为止,这是我可以推荐的最干净的解决方案

Solution 2方案二

Another solution is based on the ability to customize paths that are subject to component scanning.另一种解决方案基于定制受组件扫描影响的路径的能力。 By default is the same package where the main class (the one annotated with @SpringBootApplication resides) and all its subpackages at any level.默认情况下与 package 相同,其中主要的 class(带有@SpringBootApplication注释的那个所在)及其在任何级别的所有子包。

So if you want to exclude this class from component scanning process you can do the following:因此,如果您想从组件扫描过程中排除此 class,您可以执行以下操作:

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

Note, there are many types of filters you might want to read this tutorial for more information请注意,您可能需要阅读本教程以获取更多信息的多种过滤器类型

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM