摘要:

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

SpringBootApplication注解分析



从源代码很容易看出来,它的作用就是自动装配和扫描我们的包,并将符合的类进行注册到容器。自动装配非常简单,这里不做过多分析,接下来分析一下什么叫做符合规则的类。在@ComponentScan注解上面的过滤器类型的定义

  1. public enum FilterType {
  2. ANNOTATION, //注解类型
  3. ASSIGNABLE_TYPE, //指定的类型
  4. ASPECTJ, //按照Aspectj的表达式,基本上不会用到
  5. REGEX, //按照正则表达式
  6. CUSTOM; //自定义
  7. private FilterType() {
  8. }
  9. }

excludeFilters排除过滤器

这个是给我们排除符合的类,不让他注册到IOC的时候使用的, Springboot默认使用两个排除过滤器,很简单的,网上随便搜都可以找到相关说明,在这儿我举个特舒列子就行了.

  1. package com.github.dqqzj.springboot.filter;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. /**
  7. * @author qinzhongjian
  8. * @date created in 2019-07-30 19:14
  9. * @description: TODO
  10. * @since JDK 1.8.0_212-b10
  11. */
  12. @Target(ElementType.TYPE)
  13. @Retention(RetentionPolicy.RUNTIME)
  14. public @interface Dqqzj {
  15. String value();
  16. }
  1. package com.github.dqqzj.springboot.filter;
  2. import org.springframework.stereotype.Component;
  3. /**
  4. * @author qinzhongjian
  5. * @date created in 2019-07-29 22:30
  6. * @description: TODO
  7. * @since JDK 1.8.0_212-b10
  8. */
  9. @Dqqzj(value = "dqqzj")
  10. @Component
  11. public class Tt {
  12. }
  1. package com.github.dqqzj.springboot.filter;
  2. import org.springframework.core.type.classreading.MetadataReader;
  3. import org.springframework.core.type.classreading.MetadataReaderFactory;
  4. import org.springframework.core.type.filter.TypeFilter;
  5. import java.io.IOException;
  6. /**
  7. * @author qinzhongjian
  8. * @date created in 2019-07-30 19:13
  9. * @description: TODO
  10. * @since JDK 1.8.0_212-b10
  11. */
  12. public class MyTypeFilter implements TypeFilter {
  13. @Override
  14. public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
  15. if (metadataReader.getAnnotationMetadata().isAnnotated(Dqqzj.class.getName())) {
  16. return true;
  17. }
  18. return false;
  19. }
  20. }



以上代码是正常逻辑,反过来这样想,如果将Tt类的@Component注解去掉是不是也行的,所以这种排除注解一般都用在正常可以注入到容器的时候进行添加的,那么我们上面说过,脱离Spring也可以注入到容器,该怎么实现呢?

includeFilters包含过滤器

脱离Spring原生注解,将将Tt类的@Component注解去掉

  1. package com.github.dqqzj.springboot.filter;
  2. import org.springframework.stereotype.Component;
  3. /**
  4. * @author qinzhongjian
  5. * @date created in 2019-07-29 22:30
  6. * @description: TODO
  7. * @since JDK 1.8.0_212-b10
  8. */
  9. @Dqqzj(value = "dqqzj")
  10. //@Component
  11. public class Tt {
  12. }

透过现象看本质

流程进行梳理一下,注解驱动在注入容器的关键扫描类(注意这里是指的扫描,而不是什么@Bean,@Import等其余注解都是建立在这个基础之上的)

  • ComponentScanAnnotationParser
  • ClassPathBeanDefinitionScanner
  • ClassPathScanningCandidateComponentProvider
ClassPathScanningCandidateComponentProvider#registerDefaultFilters
  1. protected void registerDefaultFilters() {
  2. this.includeFilters.add(new AnnotationTypeFilter(Component.class));
  3. ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
  4. try {
  5. this.includeFilters.add(new AnnotationTypeFilter(ClassUtils.forName("javax.annotation.ManagedBean", cl), false));
  6. this.logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
  7. } catch (ClassNotFoundException var4) {
  8. }
  9. try {
  10. this.includeFilters.add(new AnnotationTypeFilter(ClassUtils.forName("javax.inject.Named", cl), false));
  11. this.logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
  12. } catch (ClassNotFoundException var3) {
  13. }
  14. }

此处会将@Component,JSR-250 'javax.annotation.ManagedBean' ,JSR-330 'javax.inject.Named' 的注解进行注册,所以难怪我们的自定义注解必须要有这些派生注解,换一个角度来思考,它们这个地方进行类AnnotationTypeFilter的添加,我们也可以自定义AnnotationTypeFilter来将自己的定义规则的注解进行注入容器。

Springboot源码分析之TypeFilter魔力的更多相关文章

  1. SpringBoot源码分析之SpringBoot的启动过程

    SpringBoot源码分析之SpringBoot的启动过程 发表于 2017-04-30   |   分类于 springboot  |   0 Comments  |   阅读次数 SpringB ...

  2. Springboot源码分析之项目结构

    Springboot源码分析之项目结构 摘要: 无论是从IDEA还是其他的SDS开发工具亦或是https://start.spring.io/ 进行解压,我们都会得到同样的一个pom.xml文件 4. ...

  3. 从SpringBoot源码分析 配置文件的加载原理和优先级

    本文从SpringBoot源码分析 配置文件的加载原理和配置文件的优先级     跟入源码之前,先提一个问题:   SpringBoot 既可以加载指定目录下的配置文件获取配置项,也可以通过启动参数( ...

  4. springboot源码分析-SpringApplication

    SpringApplication SpringApplication类提供了一种方便的方法来引导从main()方法启动的Spring应用程序 SpringBoot 包扫描注解源码分析 @Spring ...

  5. Springboot源码分析之jar探秘

    摘要: 利用IDEA等工具打包会出现springboot-0.0.1-SNAPSHOT.jar,springboot-0.0.1-SNAPSHOT.jar.original,前面说过它们之间的关系了, ...

  6. Springboot源码分析之代理三板斧

    摘要: 在Spring的版本变迁过程中,注解发生了很多的变化,然而代理的设计也发生了微妙的变化,从Spring1.x的ProxyFactoryBean的硬编码岛Spring2.x的Aspectj注解, ...

  7. Springboot源码分析之事务拦截和管理

    摘要: 在springboot的自动装配事务里面,InfrastructureAdvisorAutoProxyCreator ,TransactionInterceptor,PlatformTrans ...

  8. SpringBoot源码分析(二)启动原理

    Springboot的jar启动方式,是通过IOC容器启动 带动了Web容器的启动 而Springboot的war启动方式,是通过Web容器(如Tomcat)的启动 带动了IOC容器相关的启动 一.不 ...

  9. Springboot源码分析之Spring循环依赖揭秘

    摘要: 若你是一个有经验的程序员,那你在开发中必然碰到过这种现象:事务不生效.或许刚说到这,有的小伙伴就会大惊失色了.Spring不是解决了循环依赖问题吗,它是怎么又会发生循环依赖的呢?,接下来就让我 ...

随机推荐

  1. 【游记】NOIP2018初赛

    声明 本文最初的版本创建之时,本人甚至只是个电脑的小白,因而不太会用电脑编辑文字,最初的版本写在一个Word文档里,被随意的丢弃在我杂乱无比的网盘的某一个角落,直到我决定整理自己的成长历程,将散落的游 ...

  2. Flink+Druid构建实时OLAP的探索

    场景 k12在线教育公司的业务场景中,有一些业务场景需要实时统计和分析,如分析在线上课老师数量.学生数量,实时销售额,课堂崩溃率等,需要实时反应上课的质量问题,以便于对整个公司的业务情况有大致的了解. ...

  3. Scala集合(四)

    1. 集合 集合主要有三种: Sequence Map Set sequence是一种线性元素的集合,可能会是索引或者线性的(链表).map是包含键值对的集合,就像Java的Map,set是包含无重复 ...

  4. 使用webstorm调试node.js

    折腾半天,还是webstorm顺手,但也遇到一些小问题. 1.代码补全问题 nodeJS自身的补全 File->Project Setting->JavaScript->Librar ...

  5. abc -- 牛客

    题目描述 设a.b.c均是0到9之间的数字,abc.bcc是两个三位数,且有:abc+bcc=532.求满足条件的所有a.b.c的值. 输入描述: 题目没有任何输入. 输出描述: 请输出所有满足题目条 ...

  6. MySQL-EXPLAIN执行计划字段解释

    做 MySQL 查询优化遇到明明建了索引查询仍然很慢,看这个 SQL 的执行计划,看它到底有没有用到索引,执行的具体情况.我们可以用 EXPLAIN 命令查看 SQL 的执行计划,SQL 优化的重要性 ...

  7. netty源码解解析(4.0)-17 ChannelHandler: IdleStateHandler实现

    io.netty.handler.timeout.IdleStateHandler功能是监测Channel上read, write或者这两者的空闲状态.当Channel超过了指定的空闲时间时,这个Ha ...

  8. Jenkins持续集成项目搭建——基于Python Selenium自动化测试

    参考链接:https://www.liaoxuefeng.com/article/1083282007018592 第一步:去官网https://jenkins.io/下载最新的war包 第二步:安装 ...

  9. 物联网时代-跟着Thingsboard学IOT架构-HTTP设备协议及API相关限制

    thingsboard官网: https://thingsboard.io/ thingsboard GitHub: https://github.com/thingsboard/thingsboar ...

  10. Day 01--选题与设计(一)

    1.第一天我们主要确定了软件课设的项目,做一个学校内食堂订送餐的微信小程序.我们大体的设计思路是:可以实现学生身份的认证,幷使学生们能自行选择校园内的食堂,挑选各个食堂各个窗口菜谱上可以选择的菜,选择 ...