关于spring中的BeanDefinitionRegistryPostProcessor和ImportBeanDefinitionRegistrar接口

Spring——Bean注入几种方式(放入容器) Spring系列初体验,使用Spring怎么能不知道这几种将Bean放入容器中的方法呢?XML、注解、实现接口.. 阅读详情

这两个接口都可以用于动态注册bean到容器中。

BeanDefinitionRegistryPostProcessor实现了BeanFactoryPostProcessor接口,是Spring框架的BeanDefinitionRegistry的后处理器,用来注册额外的BeanDefinition。postProcessBeanDefinitionRegistry方法会在所有的BeanDefinition已经被加载了,但是所有的Bean还没有被创建前调用。BeanDefinitionRegistryPostProcessor经常被用来注册BeanFactoryPostProcessor的BeanDefinition。

Mybatis和spring整合时,我们通常会在application.xml中配置一个Bean,也就是MapperScannerConfigurer(该类实现了BeanDefinitionRegistryPostProcessor接口,所以支持动态注册mapper为Bean组件,并注入到spring容器中)。指定该Bean的包扫描路径属性。

 

ImportBeanDefinitionRegistrar
@Import注解用来支持在Configuration类中引入其他的配置类,包括Configuration类,ImportSelector和ImportBeanDefinitionRegistrar的实现类。ImportBeanDefinitionRegistrar在ConfigurationClassPostProcessor处理Configuration类期间被调用,用来生成该Configuration类所需要的BeanDefinition。而ConfigurationClassPostProcessor正实现了BeanDefinitionRegistryPostProcessor接口(所以支持mapper注册成bean,并注入到spring容器中)。

Mybatis和springboot整合时,我们通常是在main方法启动类中,添加@MapperScan(basePackage = "")来指定包的扫描,具体可以参考MybatisMapperScannerRegistrar源码的实现。该类就实现了ImportBeanDefinitionRegistrar接口。具体到该接口方法执行时,会去查找该注解指定的包扫描范围。如下图,通过annoAttrs可以保存注解@MapperScan的属性和值的键值对。这里的关键点,是注解引入了@Import,这样该类中才会生效,并执行。

package org.mybatis.spring.annotation;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.mybatis.spring.mapper.MapperFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.annotation.Import;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
public @interface MapperScan {

  String[] value() default {};

  String[] basePackages() default {};

  Class<?>[] basePackageClasses() default {};

  Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

  Class<? extends Annotation> annotationClass() default Annotation.class;

  Class<?> markerInterface() default Class.class;
  
  String sqlSessionTemplateRef() default "";

  String sqlSessionFactoryRef() default "";

  Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;

}
@Override
  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

    AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);

    // this check is needed in Spring 3.1
    if (resourceLoader != null) {
      scanner.setResourceLoader(resourceLoader);
    }

    Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
    if (!Annotation.class.equals(annotationClass)) {
      scanner.setAnnotationClass(annotationClass);
    }

    Class<?> markerInterface = annoAttrs.getClass("markerInterface");
    if (!Class.class.equals(markerInterface)) {
      scanner.setMarkerInterface(markerInterface);
    }

    Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
    if (!BeanNameGenerator.class.equals(generatorClass)) {
      scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass));
    }

    Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
    if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
      scanner.setMapperFactoryBean(BeanUtils.instantiateClass(mapperFactoryBeanClass));
    }

    scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
    scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));

    List<String> basePackages = new ArrayList<String>();
    for (String pkg : annoAttrs.getStringArray("value")) {
      if (StringUtils.hasText(pkg)) {
        basePackages.add(pkg);
      }
    }
    for (String pkg : annoAttrs.getStringArray("basePackages")) {
      if (StringUtils.hasText(pkg)) {
        basePackages.add(pkg);
      }
    }
    for (Class<?> clazz : annoAttrs.getClassArray("basePackageClasses")) {
      basePackages.add(ClassUtils.getPackageName(clazz));
    }
    scanner.registerFilters();
    scanner.doScan(StringUtils.toStringArray(basePackages));
  }

 

需要注意的是,如果某一个Bean实现了BeanDefinitionRegistryPostProcessor或者ImportBeanDefinitionRegistrar接口,那我们在这个类中使用@Autowired或者@Value注解,我们会发现失效了。原因是,spring容器执行接口的方法时,此时还没有去解析@Autowired或者@Value注解。如果我们要使用获取配置文件属性,可以通过原始方式,直接用IO读取配置文件,然后得到Properties对象,然后再获取配置值。

 

@Import的底层实现原理是什么 Import注解是 Spring 框架中用于导入其他配置类的一个重要机制。它使得开发者能够以声明的方式将分散的配置逻辑组合在一起,从而实现模块化的配置管理。下面详细介绍@Import的底层实现原理。 阅读详情

相关推荐

Spring : ImportBeanDefinitionRegistrar源码分析

1.美图 2.概述 使用方式参考:Spring : ImportBeanDefinitionRegistrar动态注入 DynamicImportBeanDefinitionRegistrar是被导入的,所以要加载到DynamicImportBeanDefinitionRegistrar必然要先加载DynamicConfiguration才行;所以先看Configuration的代码。 找到Co...

九师兄 761

BeanDefinitionRegistryPostProcessor 和 ImportBeanDefinitionRegistrar

这两个接口都可以用于动态注册bean对应BeanDefinition到容器中。 BeanDefinitionRegistryPostProcessor BeanDefinitionRegistryPostProcessor 实现了BeanFactoryPostProcessor接口,是Spring框架的 BeanDefinitionRegistry的后处理器, 用来注册额外的 BeanDefinition。 postProcessBeanDefinitionRegistry方法会在所有的BeanDefini

weixin_44730681的博客 1514

Spring中使用 BeanDefinitionRegistryPostProcessor、ImportBeanDefinitionRegi,自定义注册 Bean 以及改变 Bean 的实例化加载顺序

2、使用 BeanDefinitionRegistryPostProcessor 接口 + Spring容器初始化器接口(ApplicationContextInitializer) + /META-INFO/spring.factories 这种方式注册的Bean,优先级高于 @Component、@Configuration、@Bean、@Service 等扫描注解方式注册的bean。注意:这里自定义注册bean后,那么该bean类上标注的 @Component 注解需要去掉,否则会报错bean重复。

hkl_Forever的博客 310

简单易懂的Spring扩展点原理,看不懂你来打我

简单易懂的Spring扩展点原理,看不懂你来打我

qq_35068291的博客 970

全国大学校园网—拓扑图欣赏

全国大学网络拓扑图(一百张) 典型十张 1、 中央财经大学 2、国防科技大学 3、济南大学 4、西安石油大学 5、南通大学IPV6网络 6、中国矿业大学 7、青海师范大学 8、内蒙古科技大学 9、三峡大学 10、中共江苏省党校 剩余90张 点赞、评论获取 ...

LiBai'S BLOG 5万+

Qt 5.15.2静态编译避坑实录:MinGW 32位版从源码到Creator配置的全流程踩坑总结

本文详细介绍了Qt 5.15.2 MinGW 32位版本的静态编译全流程,包括环境准备、配置参数优化、编译过程监控及安装后配置。重点解决了静态编译中的常见问题,如参数顺序敏感、路径引号问题等,并提供了性能对比实测数据,帮助开发者高效完成静态编译。

weixin_26749245的博客 271

Spring源码之BeanFactory后置处理器BeanDefinitionRegistryPostProcessor和ImportBeanDefinitionRegistrar

BeanFactory后置处理器 BeanDefinitionRegistryPostProcessor和ImportBeanDefinitionRegistrar的区别 要想了解BeanDefinitionRegistryPostProcessor, 那就要从他的父接口BeanFactoryPostProcessor说起 1、BeanFactoryPostProcessor @Functiona...

qq_36446085的博客 1892

iTunes备份文件路径修改方法

因为以前的很多帖子iTunes都不是从微软下载的,而现在的iTunes一般都是微软商店里面的,它的路径为:“C:\Users\ 你的用户名 \Apple\MobileSync” (注:用户名,根据个人电脑名称更改)打开iTunes备份路径:“C:\Users\txh\AppData\Roaming\Apple Computer\MobileSync”,其中文件夹MobileSync就是用来存放备份文件的。创建你想备份纯在的目录创建备份文件目录(我的是G:/APPLE/Backup)2.粘贴的剪切文件目录。

尘玥的故事 1万+

SpringBoot启动过程深度解析——BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor-启动过程解析&常见实现类

详细解析BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor的执行 与重要的实现类

weixin_39072857的博客 1544

Calibre电子书阅读器个性化样式定制指南

本文详细介绍了如何通过Calibre电子书阅读器的用户样式表功能进行深度个性化样式定制。从修改全局字体、行距、背景配色(包括深色/浅色模式)到美化代码块、引用等特殊元素,本指南提供了完整的CSS代码示例与实战技巧,帮助用户打造专属的舒适阅读环境,显著提升电子书阅读体验。

vv45678的博客 920

HFSS学习记录——0. HFSS软件安装(ANSYS Electromagnetics Suite 2023 R1)

HFSS 2023 R1安装步骤

plmxu34的博客 15万+

spring手动注册bean到容器中——实现ImportBeanDefinitionRegistrar接口示例

1、创建一个maven项目(创建maven项目过程省略),pom.xml文件引入如下依赖: <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.0.RELEASE&...

小志的博客 1525

串并装换器的设计及仿真结果

串/并转换是高速数据流处理的重要技巧之一。串/并转换的实现方法多种多样,根据数据的的顺序和数量要求,可以选用寄存器,双扣RAM,SRAM,FIFO,等实现。对于 数量比较小的设计可以采用移位寄存器完成串/并转换。       在工程中,如何体现串/并转换的设计思想呢? 怎样才能提高系统的处理速度呢 ?       一个简单的串/并转换框架如下图所示,串行输入的数据通过FPGA内部的 n 个移

stubben_bear的专栏 2273

【Spring】BeanDefinitionRegistryPostProcessor

BeanFactoryPostProcessor 向容器添加自定义bean 在之前的一篇文章中写到通过BeanFactoryPostProcessor向Spring容器中添加自定义bean,最近在学习Spring源码过程中发现一个更强大更严谨的方式–BeanDefinitionRegistryPostProcessor,这是一个继承了BeanFactoryPostProcessor的接口,该接口增加了如下方法 /** * Modify the application context's internal

hansirl的博客 344

JAVA:Spring Boot 集成 Baidu UID-Generator ID 生成器

百度UID-Generator是一款高性能分布式ID生成器,支持600万QPS,提供Snowflake扩展版和Cache模式两种实现方式。文章详细介绍了如何在Spring Boot项目中集成该组件,包括Maven依赖配置、MySQL表结构初始化、Spring Boot数据源配置、WorkerId分配策略实现以及UID生成器的核心配置。该方案具有无中心依赖、ID单调递增、支持集群部署等特点,适用于订单号、用户ID等分布式场景。通过缓存模式(Cache-Buffer)可进一步提升性能,满足高并发业务需求。

木头 487

Python爬虫实战:逆向解析天猫商品详情API,精准捕获规格、SKU与促销活动

及浏览器开发者工具),绕过前端渲染的复杂性,直接逆向分析并调用其内部数据接口,从而高效、稳定地抓取商品的关键信息,包括商品规格、多维度SKU信息以及复杂的促销活动。print(f"SKU ID: {sku.sku_id}, 价格: ¥{sku.price}, 库存: {sku.stock}, 规格: {sku.props}")当你访问一个商品链接时,浏览器首先会加载一个几乎为空的HTML骨架,然后通过执行大量的JavaScript代码,向后台服务器发起多个异步请求,最终将获取到的数据填充到页面中。

2201_76125261的博客 1128

Spring组件之BeanDefinitionRegistrar动态注册bean

BeanFactory后置处理器 BeanDefinitionRegistryPostProcessor和ImportBeanDefinitionRegistrar的区别要想了解BeanDefinitionRegistryPostProcessor,那就要从他的父接口BeanFactoryPostProcessor说起 1、BeanFactoryPostProcessor @FunctionalInterface public interface BeanFactoryPostProcessor {

brandon333的博客 1599

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Spring核心扩展点BeanDefinitionRegistryPostProcessor源码分析

我们知道,只要在一个Java类上加上@Component、@Service、@Controller等注解,就可以被加载到Spring容器中,除了以上方式,加了@Bean和@Import好像也可以将对象添加到Spring容器中,究竟Spring是如何实现这些功能的呢?让我们一起来一探究竟。

道阻且长,行则将至! 918

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Mybatis是如何向Spring注册Mapper的

1. 前言有时候我们需要自行定义一些注解来标记某些特定功能的类并将它们注入Spring IoC容器。比较有代表性的就是Mybatis的Mapper接口。假如有一个新的需求让你也实现类似的...

码农小胖哥 1532

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

springframework的钩子方法和钩子接口的介绍

前言 SpringFramework其实具有很高的扩展性,只是很少人喜欢挖掘那些扩展点,而且官方的Refrence也很少提到那些Hook类或Hook接口 1、Aware接口族 Spring中提供了各种Aware接口,方便从上下文中获取当前的运行环境,比较常见的几个子接口有:BeanFactoryAware,BeanNameAware,ApplicationContextAware,Envir...

霓虹深处 499

完全搞懂Spring的BeanDefintion和加载自定义BeanDefintion

一、什么是BeanDefinition BeanDefinition描述了Bean的定义,包括该bean有哪些属性、构造函数参数、作用域、是否是抽象的等. 在Spring中是根据BeanDefinition来创建Bean的. BeanDefinition是Spring非常核心的概念. 1.1.BeanDefinition源码介绍 public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement { /**

qq_28136919的博客 1132

spring钩子

Spring钩子方法和钩子接口的使用详解 前言 SpringFramework其实具有很高的扩展性,只是很少人喜欢挖掘那些扩展点,而且官方的Refrence也很少提到那些Hook类或Hook接口,至于是不是Spring官方有意为之就不得而知。本文浅析一下笔者目前看到的Spring的一些对外开放的扩展点、Hook接口或者Hook类,如果有什么错误,希望多多交流指正,一切以Spring的源码为准,文章...

likunpeng6656201的博客 477

带你跳出源码地狱,从原理上理解MyBatis对Spring源码的扩展实现

注意今天的文章只会对原理进行分析,可能会涉及少部分代码,但是不会太多,具体的源码分析,请移步牛逼哄哄的Spring是怎么被MyBatis给征服了? ! 建议先阅读本文章,了解原理之后再去观看源码,效果会稍微好一点! 今天我们大概从以下几点去讲解MyBatis对于Spring的一个扩展思路! 一、FactoryBean是干什么? 首先我们至少要知道一个事情,就是FactoryBean的一个大致结构: 可以看到,整个 FactoryBean有三个方法: getObject(): 返回具体创建的真实对象!

皇甫嗷嗷叫 311

spring注册bean

手动注册bean的两种方式: 实现ImportBeanDefinitionRegistrar 实现BeanDefinitionRegistryPostProcessor 实现ImportBeanDefinitionRegistrar ImportBeanDefinitionRegistrar其本质也是通过BeanDefinitionRegistryPostProcessor来实现的。实现Impor...

mingwulipo的博客 316
上一篇: java扫描包(包含自己写的包或者jar中的包)及子包下的所有类
下一篇: spring中的RuntimeBeanReference的使用
lichuangcsdn
博客等级 码龄12年 161粉丝 108原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值