1. 前言

我们在上一篇Mybatis如何将Mapper接口注入Spring IoC进行了分析,有同学问胖哥这个有什么用,这个作用其实挺大的,比如让你实现一个类似@Controller的注解(或者继承某个统一接口)来完成比如定时任务的统一注入或者Websocket处理器的统一注入等这种将某种共性的Bean动态注入。

// 模仿 Controller
@XBean(description = "ETL JOB")
public class JobShedule { @Caller(cron = "* * 0/5 * * ?")
public void exec(){
// job
}
}

以上伪代码就是一个模仿Controller的定时任务Bean。

2. 设计思路

详细的开发设计思路我已经总结好了,各位同学只要按部就班就可以实现这个功能了。

2.1 定义扫描注解

定义一个类似@MappScan的进行导入自定义ImportBeanDefinitionRegistrar,并指定扫描包范围。

@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Import(XBeanDefinitionRegistrar.class)
public @interface XBeanScan { String[] basePackages();
}

我们自定义了一个扫描注解@XBeanScan。它有两个作用:

  • 通过basePackages指定扫描包的范围。
  • 导入我们自定义ImportBeanDefinitionRegistrar 的实现XBeanDefinitionRegistrar

2.2 定义目标Bean的通用标记

通常我们可以选择一个标识接口,所有其实现类都会注入Spring IoC;或者用更加方便的注解,所有被该注解标记的类都将注入Spring IoC。这里我们使用更加灵活方便的注解,实现了一个@XBean标记注解:

@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface XBean {
String description() default "";
}

2.3 实现扫描器

Spring框架为我们提供了扫描器来注册被标记的Bean,它就是上节提到的ClassPathBeanDefinitionScanner,我们继承它进行稍加改造:

public class XBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {
public XBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
super(registry, useDefaultFilters);
super.addIncludeFilter(new AnnotationTypeFilter(XBean.class));
}
}

这里我们不使用默认的过滤器,我们指定了扫描器扫描的目标为被@XBean标记的那些Bean

2.4 实现 Bean 注册机

重头戏来了,我们需要将2.12.3定义的这些组件在ImportBeanDefinitionRegistrar的实现中组装起来。

/**
* The type X bean definition registrar.
*
* @author felord.cn
* @since 2020 /9/18 22:59
*/
public class XBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
private ResourceLoader resourceLoader; @Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 不使用默认过滤器
XBeanDefinitionScanner xBeanDefinitionScanner = new XBeanDefinitionScanner(registry, false);
xBeanDefinitionScanner.setResourceLoader(resourceLoader);
// 扫描XBeanScan注解指定的包
xBeanDefinitionScanner.scan(getBasePackagesToScan(importingClassMetadata));
} @Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
} /**
* 获取{@link XBeanScan}中声明的扫描包路径
* @param metadata the meta
* @return 包路径数组
*/
private String[] getBasePackagesToScan(AnnotationMetadata metadata) {
String name = XBeanScan.class.getName();
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(name, true));
Assert.notNull(attributes, () -> "No auto-configuration attributes found. Is " + metadata.getClassName()
+ " annotated with " + ClassUtils.getShortName(name) + "?");
return attributes.getStringArray("basePackages");
}
}

从注解元数据importingClassMetadata解析我们需要的扫描路径basePackages等元数据,然后让扫描器在该路径扫描即可。

2.5 使用

在具有@Configuration标记的类或者Spring BootMain类上使用@XBeanScan即可,是不是非常简单!

其实@ComponentScan提供类似的功能。

3. 总结

本篇是对上一篇理论的具体应用,说实话上一篇比较枯燥甚至抓不住重点,但是有时候理论就是这样的。一旦你结合本篇来看你会恍然大悟。如果你需要更加细粒度控制就加上那些BeanDefinitionRegistryPostProcessorFactoryBeanSpring提供的功能性接口。从这两篇中更多需要你学习的是如何从阅读源码中触类旁通,来利用已有的组件来实现自己的逻辑。这对你的提高是极大的。好了今天就到这里,多多关注:码农小胖哥 更多干货等着你。

关注公众号:Felordcn 获取更多资讯

个人博客:https://felord.cn

山寨一个Spring的@Component注解的更多相关文章

  1. Spring Boot@Component注解下的类无法@Autowired的问题

    title: Spring Boot@Component注解下的类无法@Autowired的问题 date: 2019-06-26 08:30:03 categories: Spring Boot t ...

  2. Spring中@Component注解,@Controller注解详解

    在使用Spring的过程中,为了避免大量使用Bean注入的Xml配置文件,我们会采用Spring提供的自动扫描注入的方式,只需要添加几行自动注入的的配置,便可以完成 Service层,Controll ...

  3. Spring中@Component注解,@Controller注解详解

    在使用Spring的过程中,为了避免大量使用Bean注入的Xml配置文件,我们会采用Spring提供的自动扫描注入的方式,只需要添加几行自动注入的的配置,便可以完成 Service层,Controll ...

  4. spring中@Component注解

    1.@controller 控制器(注入服务) 2.@service 业务(注入dao) 3.@repository dao(实现dao访问) 4.@component (把普通pojo实例化到spr ...

  5. Spring Boot 之注解@Component @ConfigurationProperties(prefix = "sms") 使用@ConfigurationProperties读取yml配置

    从spring-boot开始,已经支持yml文件形式的配置,@ConfigurationProperties的大致作用就是通过它可以把properties或者yml配置直接转成对象 @Componen ...

  6. 0000 - Spring 中常用注解原理剖析

    1.概述 Spring 框架核心组件之一是 IOC,IOC 则管理 Bean 的创建和 Bean 之间的依赖注入,对于 Bean 的创建可以通过在 XML 里面使用 <bean/> 标签来 ...

  7. Spring 中常用注解原理剖析

    前言 Spring 框架核心组件之一是 IOC,IOC 则管理 Bean 的创建和 Bean 之间的依赖注入,对于 Bean 的创建可以通过在 XML 里面使用 <bean/> 标签来配置 ...

  8. java spring mvc 全注解

    本人苦逼学生一枚,马上就要毕业,面临找工作,实在是不想离开学校.在老师的教导下学习了spring mvc ,配置文件实在繁琐,因此网上百度学习了spring mvc 全注解方式完成spring的装配工 ...

  9. Spring 中 @EnableXXX 注解的套路

    前言 在 Spring 框架中有很多实用的功能,不需要写大量的配置代码,只需添加几个注解即可开启. 其中一个重要原因是那些 @EnableXXX 注解,它可以让你通过在配置类加上简单的注解来快速地开启 ...

随机推荐

  1. 无法创建新虚拟机: 无法打开配置文件“F:\BigData\vm12\centos01\centos01.vmx”: 拒绝访问。

    退出,右键vmware选择以管理员身份运行即可.

  2. 基于PHP实现CMS识别

    最近正在开发一款基于PHP实现的Web安全检测平台,写到了CMS识别这一功能,便写一篇文章总结一下. 首先需要梳理的是CMS识别的几种方法: 1.网页源代码特征:例如源代码中包含CMS的名称或是某种特 ...

  3. SSM整合+WebUpload使用(spring+springmvc+mybatis+maven)

      SSM框架整合以及webupload的集成与使用 在项目中最近用到了webupload.js,也方方面面遇到了不少问题,比如上传文件前对表单参数校验,当校验失败不予提交,及在文件上传成功后,选择同 ...

  4. css动画实现吃豆豆

    话不多说,直接上代码:(作为一个初学者写的代码,多么0基础都能看的懂吧.) HTML部分 <!DOCTYPE html> <html lang=en> <head> ...

  5. shell小技巧(7)shell运行调试

    可以在sh内使用set -x,使用后,会打印每条命令的输出 在shell中设置 set -x 开启 set +x 关闭 也可以在执行脚本时加参数 sh -x *.sh

  6. Asp.Net中的三种分页方式总结

    本人ASP.net初学,网上找了一些分页的资料,看到这篇文章,没看到作者在名字,我转了你的文章,只为我可以用的时候方便查看,2010的文章了,不知道这技术是否过期. 以下才是正文 通常分页有3种方法, ...

  7. Apache Jmter 压力测试教程

    1.官网下载安装包,地址:http://jmeter.apache.org/download_jmeter. 2.下载得到解压包,双击解压. 3.点击/bin目录下面的jmeter.bat 启动软件 ...

  8. Windows安装tensorflow教程 GPU版

    PS:这是GPU版本,CPU版会用笔记本环境另写一篇博客. 前置准备 查看GPU型号 电脑桌面->右键我的电脑->选择管理->点击设备管理器  如下图: 如果不是英伟达显卡,那么不用 ...

  9. 阿里云短信服务验证码封装类 - PHP

    本文记录在ThinkPHP6.0中使用阿里云短信验证码,该封装类不仅仅局限于TP,拿来即用 使用该类之前必须引入 flc/dysms 扩展,该封装类就是基于这个扩展写的 composer requir ...

  10. linux下ftp如何使用

    linux下ftp可以上传.下载文件 centos7环境: 1.检查是否安装过ftp服务 rpm -qa|grep vsftpd 如果没有输出则表示没有安装过 安装ftp yum -y install ...