Springboot源码分析之TypeFilter魔力
摘要:
在平常的开发中,不知道大家有没有想过这样一个问题,为什么我们自定义注解的时候要使用spring的原生注解(这里指的是类似@Component,@Service........),要么就是 随便弄个注解,搭配自己的切面编程来实现某些业务逻辑。这篇文章主要给大家分享一下,如何脱离Spring原生注解自定义注解注入IOC
SpringBootApplication注解分析

从源代码很容易看出来,它的作用就是自动装配和扫描我们的包,并将符合的类进行注册到容器。自动装配非常简单,这里不做过多分析,接下来分析一下什么叫做符合规则的类。在@ComponentScan注解上面的过滤器类型的定义
public enum FilterType {
ANNOTATION, //注解类型
ASSIGNABLE_TYPE, //指定的类型
ASPECTJ, //按照Aspectj的表达式,基本上不会用到
REGEX, //按照正则表达式
CUSTOM; //自定义
private FilterType() {
}
}
excludeFilters排除过滤器
这个是给我们排除符合的类,不让他注册到IOC的时候使用的, Springboot默认使用两个排除过滤器,很简单的,网上随便搜都可以找到相关说明,在这儿我举个特舒列子就行了.
package com.github.dqqzj.springboot.filter;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author qinzhongjian
* @date created in 2019-07-30 19:14
* @description: TODO
* @since JDK 1.8.0_212-b10
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Dqqzj {
String value();
}
package com.github.dqqzj.springboot.filter;
import org.springframework.stereotype.Component;
/**
* @author qinzhongjian
* @date created in 2019-07-29 22:30
* @description: TODO
* @since JDK 1.8.0_212-b10
*/
@Dqqzj(value = "dqqzj")
@Component
public class Tt {
}
package com.github.dqqzj.springboot.filter;
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;
/**
* @author qinzhongjian
* @date created in 2019-07-30 19:13
* @description: TODO
* @since JDK 1.8.0_212-b10
*/
public class MyTypeFilter implements TypeFilter {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
if (metadataReader.getAnnotationMetadata().isAnnotated(Dqqzj.class.getName())) {
return true;
}
return false;
}
}

以上代码是正常逻辑,反过来这样想,如果将Tt类的@Component注解去掉是不是也行的,所以这种排除注解一般都用在正常可以注入到容器的时候进行添加的,那么我们上面说过,脱离Spring也可以注入到容器,该怎么实现呢?
includeFilters包含过滤器
脱离Spring原生注解,将将Tt类的@Component注解去掉
package com.github.dqqzj.springboot.filter;
import org.springframework.stereotype.Component;
/**
* @author qinzhongjian
* @date created in 2019-07-29 22:30
* @description: TODO
* @since JDK 1.8.0_212-b10
*/
@Dqqzj(value = "dqqzj")
//@Component
public class Tt {
}

透过现象看本质
流程进行梳理一下,注解驱动在注入容器的关键扫描类(注意这里是指的扫描,而不是什么@Bean,@Import等其余注解都是建立在这个基础之上的)
- ComponentScanAnnotationParser
- ClassPathBeanDefinitionScanner
- ClassPathScanningCandidateComponentProvider
ClassPathScanningCandidateComponentProvider#registerDefaultFilters
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(ClassUtils.forName("javax.annotation.ManagedBean", cl), false));
this.logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
} catch (ClassNotFoundException var4) {
}
try {
this.includeFilters.add(new AnnotationTypeFilter(ClassUtils.forName("javax.inject.Named", cl), false));
this.logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
} catch (ClassNotFoundException var3) {
}
}
此处会将@Component,JSR-250 'javax.annotation.ManagedBean' ,JSR-330 'javax.inject.Named' 的注解进行注册,所以难怪我们的自定义注解必须要有这些派生注解,换一个角度来思考,它们这个地方进行类AnnotationTypeFilter的添加,我们也可以自定义AnnotationTypeFilter来将自己的定义规则的注解进行注入容器。
Springboot源码分析之TypeFilter魔力的更多相关文章
- SpringBoot源码分析之SpringBoot的启动过程
SpringBoot源码分析之SpringBoot的启动过程 发表于 2017-04-30 | 分类于 springboot | 0 Comments | 阅读次数 SpringB ...
- Springboot源码分析之项目结构
Springboot源码分析之项目结构 摘要: 无论是从IDEA还是其他的SDS开发工具亦或是https://start.spring.io/ 进行解压,我们都会得到同样的一个pom.xml文件 4. ...
- 从SpringBoot源码分析 配置文件的加载原理和优先级
本文从SpringBoot源码分析 配置文件的加载原理和配置文件的优先级 跟入源码之前,先提一个问题: SpringBoot 既可以加载指定目录下的配置文件获取配置项,也可以通过启动参数( ...
- springboot源码分析-SpringApplication
SpringApplication SpringApplication类提供了一种方便的方法来引导从main()方法启动的Spring应用程序 SpringBoot 包扫描注解源码分析 @Spring ...
- Springboot源码分析之jar探秘
摘要: 利用IDEA等工具打包会出现springboot-0.0.1-SNAPSHOT.jar,springboot-0.0.1-SNAPSHOT.jar.original,前面说过它们之间的关系了, ...
- Springboot源码分析之代理三板斧
摘要: 在Spring的版本变迁过程中,注解发生了很多的变化,然而代理的设计也发生了微妙的变化,从Spring1.x的ProxyFactoryBean的硬编码岛Spring2.x的Aspectj注解, ...
- Springboot源码分析之事务拦截和管理
摘要: 在springboot的自动装配事务里面,InfrastructureAdvisorAutoProxyCreator ,TransactionInterceptor,PlatformTrans ...
- SpringBoot源码分析(二)启动原理
Springboot的jar启动方式,是通过IOC容器启动 带动了Web容器的启动 而Springboot的war启动方式,是通过Web容器(如Tomcat)的启动 带动了IOC容器相关的启动 一.不 ...
- Springboot源码分析之Spring循环依赖揭秘
摘要: 若你是一个有经验的程序员,那你在开发中必然碰到过这种现象:事务不生效.或许刚说到这,有的小伙伴就会大惊失色了.Spring不是解决了循环依赖问题吗,它是怎么又会发生循环依赖的呢?,接下来就让我 ...
随机推荐
- 【错误】【vscode】输出中文是乱码问题
- css实现左边高度自适应右边高度
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- Java.基础 -------- 一个Java源文件中可以有很多类,但只能有一个类是public的
一个Java源文件中可以有很多类,但只能有一个类是public的 Java程序是从一个public类main函数开始执行的,只能有一个public是为了给类装载器提供方便,一个publi ...
- Linux之各程序安装
python安装 安装python3.6 安装python前的库环境,非常重要 yum install gcc patch libffi-devel python-devel zlib-devel b ...
- Xcodebuild命令使用
Xcodebuild简介 Xcodebuild是命令行工具包的其中一项. 命令行工具包(Command Line Tools)是一个轻量的.可以与XCode分开的.在Mac上单独下载的命令行工具包. ...
- (转载)分享常用的GoLang包工具
分享常用的GoLang包工具 包名 链接地址 备注 Machinery异步队列 https://github.com/RichardKnop/machinery Mqtt通信 github.com/e ...
- net core Webapi基础工程搭建(四)——日志功能log4net
目录 前言 log4net 依然是,NuGet引用第三方类库 整合LogUtil 小结 前言 一个完整的项目工程离不开日志文件的记录,而记录文件的方法也有很多,可以自己通过Stream去实现文件的读写 ...
- 『深度应用』NLP机器翻译深度学习实战课程·壹(RNN base)
深度学习用的有一年多了,最近开始NLP自然处理方面的研发.刚好趁着这个机会写一系列NLP机器翻译深度学习实战课程. 本系列课程将从原理讲解与数据处理深入到如何动手实践与应用部署,将包括以下内容:(更新 ...
- HuffmanTree
/* 例如,对于数列{pi}={5, 3, 8, 2, 9},Huffman树的构造过程如下: 1. 找到{5, 3, 8, 2, 9}中最小的两个数,分别是2和3,从{pi}中删除它们并将和5加入, ...
- mysql/mariadb 初体验
距离申请这个博客号已经过了九个月,思前想后还是把知识沉淀放这里吧,不过初心一样,依旧是 '谨以此文,见证成果'.有 兴趣的话也欢迎大家去我的csdn博客转一转.以下是正文: 1.mysql安装 win ...