曾经碰到过这样一种情况,想让某个使用了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. 安装并使用 Wowza 发布你的 RTMP 直播流

    转载自:http://blog.csdn.net/defonds/article/details/11979095 I. 下载 Wowza         官方下载地址 http://www.wowz ...

  2. Git记录-Git版本控制介绍

    git config命令用于获取并设置存储库或全局选项.这些变量可以控制Git的外观和操作的各个方面. 如果在使用Git时需要帮助,有三种方法可以获得任何git命令的手册页(manpage)帮助信息: ...

  3. 51 nod 1205 流水线调度

    51 nod 1205 流水线调度 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题   N个作业{1,2,…,n}要在由2台机器M1和M2组成的流水线上完成加工.每 ...

  4. PHP7 学习笔记(二)PHP5.9 升级到PHP7 遇到的一些坑的记录(php-fpm 图解)

    apache_event_php-fpm 示意图: nginx-php-fpm示意图: Worker-Master-Server TCP-Nginx_PHP Nginx-FastCGI 1.使用$_G ...

  5. Java并发编程原理与实战十四:Lock接口的认识和使用

    保证线程安全演进: synchronized volatile AtomicInteger Lock接口提供的方法: void lock():加锁 void unlock():解锁 void lock ...

  6. 当今最流行的Web项目管理工具精选

    代码管理 以前各种开源项目的代码都是通过博客和个人网页来发布的.这种分享方式并不是最容易的一种,也不便于他人对代码做出贡献.下面是几个管理项目代码的工具,不管对于个人开发者还是团队开发者来说,它们都是 ...

  7. 升级lamp中php5.6到php7.0过程

    升级过程我就直接摘录博友,http://www.tangshuang.net/1765.html,几乎问题和解决办法都是参照他的,所以我也就不另外写了.谢谢!! 周末看了一下php7的一些情况,被其强 ...

  8. java 多线程 Future callable

    面向对象5大设计原则 1.单一职责原则  一个类只包含它相关的方法,增删改查.一个方法只包含单一的功能,增加.一个类最多包含10个方法,一个方法最多50行,一个类最多500行.重复的代码进行封装,Do ...

  9. C# 浅谈 接口(Interface)的作用

    继承"基类"跟继承"接口"都能实现某些相同的功能,但有些接口能够完成的功能是只用基类无法实现的 1.接口用于描述一组类的公共方法/公共属性. 它不实现任何的方法 ...

  10. Intel大坑之一:丢失的SSE2 128bit/64bit 位移指令,马航MH370??

    缘由 最近在写一些字符串函数的优化,兴趣使然,可是写的过程中,想要实现 128bit 的按 bit 逻辑位移,遇到了一个大坑,且听我娓娓道来. 如果要追究标题,更确切的是丢失的SSE2 128 bit ...