Springboot項目實現(xiàn)將類從@ComponentScan中排除
將類從@ComponentScan中排除
問題描述
最近在學(xué)習(xí)SpringCloud的Ribbon,在使用
@RibbonClient(name = "SPRINGCLOUD-P-DEPT", configuration = RibbonConfig.class)
為服務(wù)指定負(fù)載均衡策略的時候,根據(jù)Ribbon官方文檔介紹,自定義的Ribbon配置類不允許被Springboot的**@ComponentScan**注解掃描到,所以需要將自定義的配置類RibbonConfig從在Springboot自動注入的范圍內(nèi)排除
方案一
我們都知道,Springboot的**@SpringBootApplication**會自動掃描本類所在包下的所有類和子類,所以只需要將RibbonConfig定義在Springboot啟動類所在包外面即可
方案二
通過在啟動類中添加
@ComponentScan(excludeFilters = @ComponentScan.Filter( type = FilterType.ASSIGNABLE_TYPE, classes = RibbonConfig.class))
通過FilterType.ASSIGNABLE_TYPE來指定要排除的類
如果需要排除的類太多了這個就很麻煩
方案三
通過自定義注解實現(xiàn)
@ComponentScan(excludeFilters = @ComponentScan.Filter( type = FilterType.ANNOTATION, classes = ScanIgnore.class))
與方案二不同的是,這里用的是FilterType.ANNOTATION
方案四
通過實現(xiàn)TypeFilter類來自定義過濾器
@ComponentScan(excludeFilters = {
@Filter(
type = FilterType.CUSTOM,
classes = TypeExcludeFilter.class),
@Filter(
type = FilterType.CUSTOM,
classes = AutoConfigurationExcludeFilter.class) })
此處給出的就是**@SpringbootApplication中的實現(xiàn)方式,通過FilterType.CUSTOM**來根據(jù)自動一過濾器來排除bean
最后貼出枚舉類FilterType:
/*
* Copyright 2002-2013 the original author or authors.
*
* 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 的作用就是根據(jù)定義的掃描路徑,把符合掃描規(guī)則的類裝配到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: 用于指定包的路徑,進(jìn)行掃描basePackageClasses: 用于指定某個類的包的路徑進(jìn)行掃描nameGenerator: bean的名稱的生成器useDefaultFilters: 是否開啟對@Component,@Repository,@Service,@Controller的類進(jìn)行檢測includeFilters: 包含的過濾條件
FilterType.ANNOTATION:按照注解過濾
FilterType.ASSIGNABLE_TYPE:按照給定的類型
FilterType.ASPECTJ:使用ASPECTJ表達(dá)式
FilterType.REGEX:正則
FilterType.CUSTOM:自定義規(guī)則
excludeFilters: 排除的過濾條件,用法和includeFilters一樣
我的工程結(jié)構(gòu)如下,測試對controller和service的掃描,其中HelloController沒有加@Controller等任何注解,就是一個普通類。

修改配置類如下:應(yīng)用默認(rèn)的過濾器,掃描service包:
@Configuration
@ComponentScan(value = "com.xhx.spring.service",
useDefaultFilters = true
)
public class MyConfig {
}
系統(tǒng)注入了兩個service進(jìn)去

改成如下所示:HelloController所在的包的類也被掃描了進(jìn)去
@Configuration
@ComponentScan(value = "com.xhx.spring.service",
useDefaultFilters = true,
basePackageClasses = HelloController.class
)
public class MyConfig {
}
系統(tǒng)中會注入下面就給類

把默認(rèn)的過濾器關(guān)掉,掃描帶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 {
}
輸出結(jié)果:

輸出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();
}
}
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
spring schedule實現(xiàn)動態(tài)配置執(zhí)行時間
這篇文章主要介紹了spring schedule實現(xiàn)動態(tài)配置執(zhí)行時間,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
如何使用Spring?Boot設(shè)置上傳文件大小限制
上傳文件是互聯(lián)網(wǎng)中常應(yīng)用的場景之一,最典型的情況就是上傳頭像等,下面這篇文章主要給大家介紹了關(guān)于如何使用Spring?Boot設(shè)置上傳文件大小限制的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01
詳解spring整合shiro權(quán)限管理與數(shù)據(jù)庫設(shè)計
這篇文章主要介紹了詳解spring整合shiro權(quán)限管理與數(shù)據(jù)庫設(shè)計,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05
SpringBoot實現(xiàn)識別圖片中的身份證號與營業(yè)執(zhí)照信息
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何實現(xiàn)識別圖片中的身份證號與營業(yè)執(zhí)照信息,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2024-01-01
java.io.IOException:你的主機(jī)中的軟件中止了一個已建立的連接踩坑實戰(zhàn)
最近在工作中遇到了個問題,分享給同樣遇到問題的同學(xué),這篇文章主要給大家介紹了關(guān)于java.io.IOException:你的主機(jī)中的軟件中止了一個已建立的連接的踩坑實戰(zhàn)記錄,需要的朋友可以參考下2023-03-03
SpringBoot事務(wù)鉤子函數(shù)的使用方式
本文介紹了SpringBoot中事務(wù)鉤子函數(shù)的使用方式,包括常見場景、使用方式等,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-11-11
Netty分布式ByteBuf中PooledByteBufAllocator剖析
這篇文章主要為大家介紹了Netty分布式ByteBuf剖析PooledByteBufAllocator簡述,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03

