曾经碰到过这样一种情况,想让某个使用了spring 注解的类不被spring扫描注入到spring bean池中,比如下面的类使用了@Component和@ConfigurationProperties("example1.user")自动绑定属性,不想让这个类被注入。

 package com.github.torlight.sbex;

 import java.io.Serializable;

 import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; @Component
@ConfigurationProperties("example1.user")
public class User implements Serializable{ private static final long serialVersionUID = 6913838730034509179L; private String name; private Integer age; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} }

一开始不想使用BeanPostProcessor接口的实现类来实现这样的功能,想可以借助@SpringBootApplication注解,使用exclude来实现该功能。

 package com.github.torlight.sbex;

 import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; /**
* Hello world!
*
*/
@SpringBootApplication(exclude={com.github.torlight.sbex.User.class})
public class Example1 { @Bean
public UserAction userAction(){
return new UserAction();
} public static void main( String[] args ) { ApplicationContext context= SpringApplication.run(Example1.class, args); ((UserAction)context.getBean(UserAction.class)).sysOutUserInfo(); }
}

运行程序后,控制台报如下错误:

2018-08-04 13:15:57.079 ERROR 4504 --- [           main] o.s.boot.SpringApplication               : Application startup failed

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [com.github.torlight.sbex.Example1]; nested exception is java.lang.IllegalStateException: The following classes could not be excluded because they are not auto-configuration classes:
- com.github.torlight.sbex.User at org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors(ConfigurationClassParser.java:556) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:185) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:308) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:270) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:93) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
at com.github.torlight.sbex.Example1.main(Example1.java:25) [classes/:na]
Caused by: java.lang.IllegalStateException: The following classes could not be excluded because they are not auto-configuration classes:
- com.github.torlight.sbex.User at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.handleInvalidExcludes(AutoConfigurationImportSelector.java:193) ~[spring-boot-autoconfigure-1.5.4.RELEASE.jar:1.5.4.RELEASE]
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.checkExcludedClasses(AutoConfigurationImportSelector.java:178) ~[spring-boot-autoconfigure-1.5.4.RELEASE.jar:1.5.4.RELEASE]
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.selectImports(AutoConfigurationImportSelector.java:100) ~[spring-boot-autoconfigure-1.5.4.RELEASE.jar:1.5.4.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors(ConfigurationClassParser.java:547) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
... 14 common frames omitted

错误提示不能使用exclude={com.github.torlight.sbex.User.class},因为该类并不是被spring boot自动装配的类,类似于RedisAutoConfiguration这样的类。仔细研究一番后,发现可以扩展org.springframework.boot.context.TypeExcludeFilter来实现这一功能。spring boot在执行扫描过程中,会使用TypeExcludeFilter进行过滤。

 public class TypeExcludeFilter implements TypeFilter, BeanFactoryAware {

     private BeanFactory beanFactory;

     @Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
} @Override
public boolean match(MetadataReader metadataReader,
MetadataReaderFactory metadataReaderFactory) throws IOException {
if (this.beanFactory instanceof ListableBeanFactory
&& getClass().equals(TypeExcludeFilter.class)) {
15 Collection<TypeExcludeFilter> delegates = ((ListableBeanFactory) this.beanFactory)
16 .getBeansOfType(TypeExcludeFilter.class).values();
for (TypeExcludeFilter delegate : delegates) {
if (delegate.match(metadataReader, metadataReaderFactory)) {
return true;
}
}
}
return false;
} @Override
public boolean equals(Object obj) {
throw new IllegalStateException(
"TypeExcludeFilter " + getClass() + " has not implemented equals");
} @Override
public int hashCode() {
throw new IllegalStateException(
"TypeExcludeFilter " + getClass() + " has not implemented hashCode");
} }

可以看出,spring boot会加载spring bean池中所有针对TypeExcludeFilter的扩展,并循环遍历这些扩展类调用其match方法。那么思路出来了,只要继承该类并重写match方法,在该方法内部进行相应的处理即可。示例代码如下:

 public class MyTypeExcludeFilter extends TypeExcludeFilter {

     @Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException { if("com.github.torlight.sbex.User".equals(metadataReader.getClassMetadata().getClassName())){
8 return true;
9 } return false;
} }
Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2018-08-04 13:27:14.556 ERROR 4964 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter : ***************************
APPLICATION FAILED TO START
*************************** Description: Field user in com.github.torlight.sbex.UserAction required a bean of type 'com.github.torlight.sbex.User' that could not be found. Action: Consider defining a bean of type 'com.github.torlight.sbex.User' in your configuration.

相关示例代码已经上传到github上面,https://github.com/gittorlight/springboot-example

spring boot之org.springframework.boot.context.TypeExcludeFilter的更多相关文章

  1. Spring Boot 引入org.springframework.boot.SpringApplication出错

    今天新建的一个spring boot maven项目, 写启动类时发现无法引入SpringApplication, 经查原来是冲突了,我早些时候用了比较低版本的spring boot创建了项目 ,导致 ...

  2. IDEA 创建Spring项目后org.springframework.boot报错

    IDEA 创建 Spring boot 项目后 ,在pom.xml文件中 org.springframework.boot出错,刷新也没有作用. 如图: 可以降低 org.springframewor ...

  3. spring boot 开发 org.springframework.context.ApplicationContextException: Unable to start web server;

    Error starting ApplicationContext. To display the conditions report re-run your application with 'de ...

  4. java.lang.NoClassDefFoundError: org/springframework/boot/context/embedded/FilterRegistrationBean

    昨天还好好的, 今天我的spring boot 项目就不能正常运行了! 出现: 018-07-06 10:01:41.776 WARN [mq-service,,,] 7 --- [ main] at ...

  5. 【spring cloud】spring cloud分布式服务eureka启动时报错:java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplicationBuilder.<init>([Ljava/lang/Object;)V

    spring cloud分布式服务eureka启动时报错:java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApp ...

  6. Spring boot java.lang.NoClassDefFoundError: org/springframework/boot/bind/RelaxedPropertyResolver

    Spring boot 2.0.3 RELEASE 配置报错 java.lang.NoClassDefFoundError: org/springframework/boot/bind/Relaxed ...

  7. SpringBoot整合nacos启动报错:java.lang.NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata

    报错信息 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'nacosCo ...

  8. Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/boot/context/embedded/ServletRegistrationBean

    异常信息 2017-09-02 18:06:37.223 [main] ERROR o.s.boot.SpringApplication - Application startup failed ja ...

  9. 构建eureka-server异常ClassNotFoundException: org.springframework.boot.context.embedded.FilterRegistrationBean

    Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.embedded.FilterRegistr ...

随机推荐

  1. js 正则表达式 整数或小数

    非零开头的整数或小数 /^[1-9][0-9]*([.][0-9]+)?$/ 非零开头的整数或两位小数 /^[1-9][0-9]*([.][0-9]{1,2})?$/ /^[1-9][0-9]*([. ...

  2. 解除单个文件的与svn服务器的关联

    有些文件和个人开发环境有关不需要和svn服务器做同步,可以取消其和svn服务的关联. 右键选中要取消关联的文件,右键菜单 Tortoise SVN  --->   unversion and a ...

  3. xgboost与sklearn的接口

    xgb使用sklearn接口(推荐) XGBClassifier from xgboost.sklearn import XGBClassifier clf = XGBClassifier( sile ...

  4. 【译】第十三篇 Integration Services:SSIS变量

    本篇文章是Integration Services系列的第十三篇,详细内容请参考原文. 简介在前一篇我们结合了之前所学的冒泡.日志记录.父子模式创建一个自定义的SSIS包日志记录模式.在这一篇,我们将 ...

  5. APScheduler API -- apscheduler.triggers.date

    apscheduler.triggers.date API Trigger alias for add_job(): date class apscheduler.triggers.date.Date ...

  6. Java编程思想 4th 第3章 操作符

    有了数据,还需要进行数据间的运算,因此Java中也有数据间运算的各种符号,书本称之为操作符,正确的翻译应该是运算符. Java中的运算符同C++相同,运算符同运算符对象构成表达式,表达式是运算对象及运 ...

  7. [转]双线性插值(Bilinear interpolation)

    1,原理 在图像的仿射变换中,很多地方需要用到插值运算,常见的插值运算包括最邻近插值,双线性插值,双三次插值,兰索思插值等方法,OpenCV提供了很多方法,其中,双线性插值由于折中的插值效果和运算速度 ...

  8. js中同步与异步处理方法

    在使用异步请求时,有时需要将异步请求的结果返回给另一个js函数,此种情况下会出现未等异步请求返回请求结果,该发送请求所在js函数已经执行完后续操作,即已经执行return ,这样会导致return的结 ...

  9. 【codeforces】【比赛题解】#940 CF Round #466 (Div. 2)

    人生的大起大落莫过如此,下一场我一定要回紫. [A]Points on the line 题意: 一个直线上有\(n\)个点,要求去掉最少的点,使得最远两点距离不超过\(d\). 题解: 暴力两重fo ...

  10. Cesium entity click

    var url = 'http://202.107.245.51:81/user/dev/api/v2/sql?rows_per_page=40&page=0&sort_order=a ...