添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
欢迎访问悦橙教程(wld5.com),关注java教程。 悦橙教程 java问答 | 每日更新
页面导航 : > > 文章正文

Springboot项目实现将类从@ComponentScan中排除,

来源: javaer 分享于 点击 42599 次 点评:60

Springboot项目实现将类从@ComponentScan中排除,

目录
  • 将类从@ComponentScan中排除
    • 问题描述
    • 方案一
    • 方案二
    • 方案三
    • 方案四
  • @ComponentScan 详解

    将类从@ComponentScan中排除

    最近在学习SpringCloud的Ribbon,在使用

    @RibbonClient(name = "SPRINGCLOUD-P-DEPT", configuration = RibbonConfig.class)

    为服务指定负载均衡策略的时候,根据Ribbon官方文档介绍,自定义的Ribbon配置类不允许被Springboot的**@ComponentScan**注解扫描到,所以需要将自定义的配置类RibbonConfig从在Springboot自动注入的范围内排除

    我们都知道,Springboot的**@SpringBootApplication**会自动扫描本类所在包下的所有类和子类,所以只需要将RibbonConfig定义在Springboot启动类所在包外面即可

    通过在启动类中添加

    @ComponentScan(excludeFilters = @ComponentScan.Filter( type = FilterType.ASSIGNABLE_TYPE, classes = RibbonConfig.class))

    通过FilterType.ASSIGNABLE_TYPE来指定要排除的类

    如果需要排除的类太多了这个就很麻烦

    通过自定义注解实现

    @ComponentScan(excludeFilters = @ComponentScan.Filter( type = FilterType.ANNOTATION, classes = ScanIgnore.class))

    与方案二不同的是,这里用的是FilterType.ANNOTATION

    通过实现TypeFilter类来自定义过滤器

    @ComponentScan(excludeFilters = { @Filter( type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter( type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

    此处给出的就是**@SpringbootApplication中的实现方式,通过FilterType.CUSTOM**来根据自动一过滤器来排除bean

    最后贴出枚举类FilterType:

    * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * https://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. package org.springframework.context.annotation; * Enumeration of the type filters that may be used in conjunction with * {@link ComponentScan @ComponentScan}. * @author Mark Fisher * @author Juergen Hoeller * @author Chris Beams * @since 2.5 * @see ComponentScan * @see ComponentScan#includeFilters() * @see ComponentScan#excludeFilters() * @see org.springframework.core.type.filter.TypeFilter public enum FilterType { * Filter candidates marked with a given annotation. * @see org.springframework.core.type.filter.AnnotationTypeFilter ANNOTATION, * Filter candidates assignable to a given type. * @see org.springframework.core.type.filter.AssignableTypeFilter ASSIGNABLE_TYPE, * Filter candidates matching a given AspectJ type pattern expression. * @see org.springframework.core.type.filter.AspectJTypeFilter ASPECTJ, * Filter candidates matching a given regex pattern. * @see org.springframework.core.type.filter.RegexPatternTypeFilter REGEX, /** Filter candidates using a given custom * {@link org.springframework.core.type.filter.TypeFilter} implementation. CUSTOM

    @ComponentScan 详解

    @ComponentScan 的作用就是根据定义的扫描路径,把符合扫描规则的类装配到spring容器中,注解定义如下。

    @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) @Documented @Repeatable(ComponentScans.class) public @interface ComponentScan { @AliasFor("basePackages") String[] value() default {}; @AliasFor("value") String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class; Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class; ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT; String resourcePattern() default "**/*.class"; boolean useDefaultFilters() default true; ComponentScan.Filter[] includeFilters() default {}; ComponentScan.Filter[] excludeFilters() default {}; boolean lazyInit() default false; @Retention(RetentionPolicy.RUNTIME) @Target({}) public @interface Filter { FilterType type() default FilterType.ANNOTATION; @AliasFor("classes") Class<?>[] value() default {}; @AliasFor("value") Class<?>[] classes() default {}; String[] pattern() default {};
  • basePackages value : 用于指定包的路径,进行扫描
  • basePackageClasses : 用于指定某个类的包的路径进行扫描
  • nameGenerator : bean的名称的生成器
  • useDefaultFilters : 是否开启对@Component,@Repository,@Service,@Controller的类进行检测
  • includeFilters : 包含的过滤条件
  • FilterType.ANNOTATION :按照注解过滤

    FilterType.ASSIGNABLE_TYPE :按照给定的类型

    FilterType.ASPECTJ :使用ASPECTJ表达式

    FilterType.REGEX :正则

    FilterType.CUSTOM :自定义规则

  • excludeFilters : 排除的过滤条件,用法和includeFilters一样
  • 我的工程结构如下,测试对controller和service的扫描,其中HelloController没有加@Controller等任何注解,就是一个普通类。

    修改配置类如下:应用默认的过滤器,扫描service包:

    @Configuration @ComponentScan(value = "com.xhx.spring.service", useDefaultFilters = true public class MyConfig {

    系统注入了两个service进去

    改成如下所示:HelloController所在的包的类也被扫描了进去

    @Configuration @ComponentScan(value = "com.xhx.spring.service", useDefaultFilters = true, basePackageClasses = HelloController.class public class MyConfig {

    系统中会注入下面就给类

    把默认的过滤器关掉,扫描带Controller注解的。

    @Configuration @ComponentScan(value = "com.xhx.spring", useDefaultFilters = false, includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}) public class MyConfig {

    按照类的类型扫描,虽然HelloController没有加注解,但是被注入到了spring容器中

    @Configuration @ComponentScan(value = "com.xhx.spring", useDefaultFilters = false, includeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {HelloController.class}) public class MyConfig {

    自定义扫描过滤器

    package com.xhx.spring.componentscan.config; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.TypeFilter; import java.io.IOException; * xuhaixing * 2018/9/18 23:07 public class MyTypeFilter implements TypeFilter { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { String className = metadataReader.getClassMetadata().getClassName(); if(className.contains("Controller")){ return true; return false;

    修改配置类

    @Configuration @ComponentScan(value = "com.xhx.spring", useDefaultFilters = false, includeFilters = { @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class}) public class MyConfig {

    输出结果:

    输出spring容器中的bean的测试类:只过滤输出了名字中含有hello的类。

    package com.xhx.spring.componentscan; import com.xhx.spring.componentscan.config.MyConfig; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.test.context.junit4.SpringRunner; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @RunWith(SpringRunner.class) @SpringBootTest public class ComponentScanApplicationTests { @Test public void testLoads() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); List<String> hello = Arrays.stream(context.getBeanDefinitionNames()).collect(Collectors.toList()); hello.stream().filter(name->name.contains("hello")).peek(System.out::println).count();

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持3672js教程。

    您可能感兴趣的文章:
    • 为什么说要慎用SpringBoot @ComponentScan
    • springboot @ComponentScan注解原理解析
    • SpringBoot中@ComponentScan的使用详解
    相关栏目: