spring boot之org.springframework.boot.context.TypeExcludeFilter
曾经碰到过这样一种情况,想让某个使用了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的更多相关文章
- Spring Boot 引入org.springframework.boot.SpringApplication出错
今天新建的一个spring boot maven项目, 写启动类时发现无法引入SpringApplication, 经查原来是冲突了,我早些时候用了比较低版本的spring boot创建了项目 ,导致 ...
- IDEA 创建Spring项目后org.springframework.boot报错
IDEA 创建 Spring boot 项目后 ,在pom.xml文件中 org.springframework.boot出错,刷新也没有作用. 如图: 可以降低 org.springframewor ...
- 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 ...
- java.lang.NoClassDefFoundError: org/springframework/boot/context/embedded/FilterRegistrationBean
昨天还好好的, 今天我的spring boot 项目就不能正常运行了! 出现: 018-07-06 10:01:41.776 WARN [mq-service,,,] 7 --- [ main] at ...
- 【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 ...
- Spring boot java.lang.NoClassDefFoundError: org/springframework/boot/bind/RelaxedPropertyResolver
Spring boot 2.0.3 RELEASE 配置报错 java.lang.NoClassDefFoundError: org/springframework/boot/bind/Relaxed ...
- SpringBoot整合nacos启动报错:java.lang.NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
报错信息 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'nacosCo ...
- 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 ...
- 构建eureka-server异常ClassNotFoundException: org.springframework.boot.context.embedded.FilterRegistrationBean
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.embedded.FilterRegistr ...
随机推荐
- codevs 1500 后缀排序
codevs 1500 后缀排序 http://codevs.cn/problem/1500/ 时间限制: 1 s 空间限制: 128000 KB 题目描述 Description 天凯是MI ...
- ZeroMQ API(四) 套接字
1.创建一个套接字 1.1 zmq_socket(3) 1.1.1 名称 zmq_socket - 创建ZMQ套接字 1.1.2 概要 void * zmq_socket(void * context ...
- 2016.5.21——atoi()函数的测试
对函数atoi()函数的测试: atoi()函数将字符串型转换为整型 代码: #include "stdafx.h" #include "iostream" # ...
- Count of Smaller Number before itself
Give you an integer array (index from 0 to n-1, where n is the size of this array, value from 0 to 1 ...
- Task多线程进行多进程
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using Sys ...
- c# CTS 基础数据类型笔记
C#中的基础数据类型并没有内置于c#语言中,而内置于.net freamework. C#有15个预定义类型,其中13个是值类型,两个是引用类型(string和object) 一.值类型 值类型 数据 ...
- C#里partial关键字的作用
1. 什么是局部类型?C# 2.0 引入了局部类型的概念.局部类型允许我们将一个类.结构或接口分成几个部分,分别实现在几个不同的.cs文件中.局部类型适用于以下情况: (1) 类型特别大,不宜放在一个 ...
- Scrapy官网程序执行示例
Windows 10家庭中文版本,Python 3.6.4,Scrapy 1.5.0, Scrapy已经安装很久了,前面也看了不少Scrapy的资料,自己尝试使其抓取微博的数据时,居然连登录页面(首页 ...
- docker centos:last 开启sshd 遇到的证书问题
启动sshd: # /usr/sbin/sshd 一.问题描述 这时报以下错误: [root@ xxx/]# /usr/sbin/sshd Could not load host key: /etc/ ...
- 深度解析eclipse控制台
第一个按钮:scroll lock 控制台在打印sql语句的时候会一直滚动,用这个按钮可以固定住控制台不乱跑; 第二个按钮:show console when standard out changes ...