mybatis-Spring ClassPathMapperScanner源码分析(自定义注解加载Bean)

保姆级教程:在Android车机上从零配置USB Gadget,搞定CarPlay有线连接 本文详细介绍了在Android车机上从零配置USB Gadget以实现CarPlay有线连接的完整实践指南。涵盖内核驱动开发、Android系统配置及用户空间通信架构,帮助开发者深入理解USB子系统和iAP2协议栈,实现稳定可靠的CarPlay有线连接功能。 阅读详情

摘要:

在使用mybatis时,可以通过mybatis-spring的MapperFactoryBean来配置一系列的DAO接口,MapperFactoryBean的getObject方法能返回DAO接口对应的动态代理类,实际是通过DefaultSqlSession以动态代理的方式生成DAO接口的实现类。而当DAO类很多时,可以通过mybatis-spring的MapperCannerConfigurer类配置要描述的包,来实现生成MapperFactoryBean对象,减少配置。

一、MapperFactoryBean 与MapperCannerConfigurer 配置回顾

MapperFactoryBean 配置要使用的DAO
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">  
  <property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />  
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />  
</bean>  
通过上面的配置在 Service层中就可以直接注入 userMapper这个DAO,MapperFactoryBean内部会调用DefaultSqlSession以动态代理的方式生成DAO接口的实现类。

MapperCannerConfigurer配置多个要使用的DAO
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
  <property name="basePackage" value="org.mybatis.spring.sample.mapper" />  
  <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>  

通过上面的配置在包org.mybaits.spring.sample.mapper中下面对应的DAO接口,便能生成对应的MapperFactoryBean对象,然后被Service层调用。因为在DefaultSqlSession
内部是以动态代理的方式生成DAO接口对应的实现类,这里DAO要声明为接口。
MapperCannerConfigurer是通过实现BeanDefinitionRegistryPostProcessor接口,完成对BeanDefinitionRegistry自定义与修改,postProcessBeanDefinitionRegistry方法中则调用了ClassPathMapperScanner类。该类通过扫描包来指定
要生成的Bean。。。

二、ClassPathMapperScanner代码分析

ClassPathMapperScanner类实现了ClassPathBeanDefinitionScanner并对registerFilters方法与doScan方法进行了重写。
registerFilters方法主要是根据annotationClass或者是markerInterface属性来指定只扫描指定包下面的类带有某个注解的接口或者是为某个接口的子接口的接口。
public void registerFilters() {
    boolean acceptAllInterfaces = true;

    // if specified, use the given annotation and / or marker interface
    if (this.annotationClass != null) {
      addIncludeFilter(new AnnotationTypeFilter(this.annotationClass));
      acceptAllInterfaces = false;
    }

    // override AssignableTypeFilter to ignore matches on the actual marker interface
    if (this.markerInterface != null) {
      addIncludeFilter(new AssignableTypeFilter(this.markerInterface) {
        @Override
        protected boolean matchClassName(String className) {
          return false;
        }
      });
      acceptAllInterfaces = false;
    }

    if (acceptAllInterfaces) {
      // default include filter that accepts all classes
      addIncludeFilter(new TypeFilter() {
        public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
          return true;
        }
      });
    }

    // exclude package-info.java
    addExcludeFilter(new TypeFilter() {
      public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        String className = metadataReader.getClassMetadata().getClassName();
        return className.endsWith("package-info");
      }
    });
  }

doScan方法用来将包下面的接口转化为MapperFactoryBean的类。
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);

    if (beanDefinitions.isEmpty()) {
      logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
    } else {
      for (BeanDefinitionHolder holder : beanDefinitions) {
        GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();

        if (logger.isDebugEnabled()) {
          logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() 
              + "' and '" + definition.getBeanClassName() + "' mapperInterface");
        }

        // the mapper interface is the original class of the bean
        // but, the actual class of the bean is MapperFactoryBean
        definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName());
        definition.setBeanClass(MapperFactoryBean.class);

        definition.getPropertyValues().add("addToConfig", this.addToConfig);

        boolean explicitFactoryUsed = false;
        if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
          definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
          explicitFactoryUsed = true;
        } else if (this.sqlSessionFactory != null) {
          definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
          explicitFactoryUsed = true;
        }

        if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
          if (explicitFactoryUsed) {
            logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
          }
          definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
          explicitFactoryUsed = true;
        } else if (this.sqlSessionTemplate != null) {
          if (explicitFactoryUsed) {
            logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
          }
          definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
          explicitFactoryUsed = true;
        }

        if (!explicitFactoryUsed) {
          if (logger.isDebugEnabled()) {
            logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");
          }
          definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
        }
      }
    }

    return beanDefinitions;
  }

三、通过实现ClassPathBeanDefinitionScanner类自下定义bean注解的扫描

1、定义自己的注解

这里的注解并没有被@Component注解,而通过ClassPathBeanDefinitionScanner 类实现扫描。
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CustomizeComponent {
 String value() default "";
}

2、被注解的类

@CustomizeComponent
public class ScanClass1 {
public void print() {
    System.out.println("scanClass1");
}
}

3、自定义的BeanScannerConfigurer类

BeanScannerConfigurer用于嵌入到Spring的加载过程的中,这里用到了BeanFactoryPostProcessor 和 ApplicationContextAware。Spring提供了一些的接口使程序可以嵌入Spring的加载过程。这个类中的继承ApplicationContextAware接口,Spring会读取ApplicationContextAware类型的的JavaBean,并调用setApplicationContext(ApplicationContext applicationContext)传入Spring的applicationContext。
同样继承BeanFactoryPostProcessor接口,Spring会在BeanFactory的相关处理完成后调用postProcessBeanFactory方法,进行定制的功能。
@Component
public static class BeanScannerConfigurer implements  BeanFactoryPostProcessor, ApplicationContextAware {
	private ApplicationContext applicationContext;
	
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
	    this.applicationContext = applicationContext;
	}
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
	    Scanner scanner = new Scanner((BeanDefinitionRegistry) beanFactory);
	    scanner.setResourceLoader(this.applicationContext);
	    scanner.scan("org.wcong.test.spring.scan");
	}
}

4、ClassPathBeanDefinitionScanner实现类Scanner

Scanner继承的ClassPathBeanDefinitionScanner是Spring内置的Bean定义的扫描器。
includeFilter里定义了类的过滤器,newAnnotationTypeFilter(CustomizeComponent.class)表示只取被CustomizeComponent修饰的类。只扫描我们自已定义的注解。
doScan里扫面了包底下的读取到BeanDefinitionHolder,自定义GenericBeanDefinition相关功能。

public final static class Scanner extends ClassPathBeanDefinitionScanner {
	  public Scanner(BeanDefinitionRegistry registry) {
	      super(registry);
	  }
	  public void registerDefaultFilters() {
	      this.addIncludeFilter(new AnnotationTypeFilter(CustomizeComponent.class));
	  }
	  public Set<BeanDefinitionHolder> doScan(String... basePackages) {
	      Set<BeanDefinitionHolder> beanDefinitions =   super.doScan(basePackages);
	      for (BeanDefinitionHolder holder : beanDefinitions) {
	          GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();
	          definition.getPropertyValues().add("innerClassName", definition.getBeanClassName());
	          definition.setBeanClass(FactoryBeanTest.class);
	      }
	      return beanDefinitions;
	  }
	  public boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
	     return super.isCandidateComponent(beanDefinition) && beanDefinition.getMetadata()
	.hasAnnotation(CustomizeComponent.class.getName());
	  }
}

5、得到我们Bean

FactoryBean是Spring中比较重要的一个类。它的描述如下

Interface to be implemented by objects used within a BeanFactory which are themselves factories. 
If a bean implements this interface, it is used as a factory for an object to expose, not directly as a bean* instance that will be exposed itself
普通的JavaBean是直接使用类的实例,但是如果一个Bean继承了这个借口,就可以通过getObject()方法来自定义实例的内容,在FactoryBeanTest的getObject()就通过代理了原始类的方法,自定义类的方法。
public static class FactoryBeanTest<T> implements InitializingBean, FactoryBean<T> {
	  private String innerClassName;
	  public void setInnerClassName(String innerClassName) {
	      this.innerClassName = innerClassName;
	  }
	  public T getObject() throws Exception {
	      Class innerClass = Class.forName(innerClassName);
	      if (innerClass.isInterface()) {
	          return (T) InterfaceProxy.newInstance(innerClass);
	      } else {
	          Enhancer enhancer = new Enhancer();
	          enhancer.setSuperclass(innerClass);
	          enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
	          enhancer.setCallback(new MethodInterceptorImpl());
	          return (T) enhancer.create();
	      }
	  }
	  public Class<?> getObjectType() {
	      try {
	            return Class.forName(innerClassName);
	      } catch (ClassNotFoundException e) {
	            e.printStackTrace();
	      }
	      return null;
	  }
	  public boolean isSingleton() {
	      return true;
	  }
	  public void afterPropertiesSet() throws Exception {
      }
}
public static class InterfaceProxy implements InvocationHandler {
	  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	      System.out.println("ObjectProxy execute:" + method.getName());
	      return method.invoke(proxy, args);
	  }
	  public static <T> T newInstance(Class<T> innerInterface) {
	      ClassLoader classLoader = innerInterface.getClassLoader();
	      Class[] interfaces = new Class[] { innerInterface };
	      InterfaceProxy proxy = new InterfaceProxy();
	      return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
	  }
}
public static class MethodInterceptorImpl implements MethodInterceptor {
      public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
	      System.out.println("MethodInterceptorImpl:" + method.getName());
	      return methodProxy.invokeSuper(o, objects);
      }
}

6、main函数

@Configuration
public class CustomizeScanTest {
   public static void main(String[] args) {
    AnnotationConfigApplicationContext annotationConfigApplicationContext = new        AnnotationConfigApplicationContext();                
    annotationConfigApplicationContext.register(CustomizeScanTest.class);
    annotationConfigApplicationContext.refresh();
    ScanClass1 injectClass = annotationConfigApplicationContext.getBean(ScanClass1.class);
    injectClass.print();
   }
}
详解代码见https://github.com/wcong/learn-java/blob/master/src/main/java/org/wcong/test/spring/CustomizeScanTest.java

Android 15.0 系统开机屏幕设置默认横屏显示 在15.0的系统ROM产品定制化开发中,对于产品需求来说,由于是宽屏设备所以产品需要开机默认横屏显示,开机横屏显示这就需要从 两部分来实现,一部分是系统开机动画横屏显示,另一部分是系统屏幕显示横屏显示,从这两方面就可以做到开机默认横屏显示了 阅读详情

相关推荐

QComboBox设置最大显示数量多余的用滑动条,以及QComboBox::setMaxVisibleItems()不起作用的问题

QComoboBox是Qt封装的一个选择框的东西,但是我在使用过程中有一点感觉很不好,如图: 不论你往里面添加多少个它都会给你显示全部,甚至给你铺满全屏,后来看了官方文档发现有个setMaxVisibleItems()的方法,我欣喜若狂啊,终于特么的能解决了,但是,很遗憾,不知为啥,我设置上之后并没有起作用,依然会显示全部,后来搜了百度发现有个人是这样解决的 QComboBox *box = ne...

Aboveground的博客 4919

mapper扫描,自动装配

自动装配是springboot的一大特点 关键类: 1、MapperScannerConfigurer 2、ClassPathMapperScanner 类定义及图 MapperScannerConfigurer public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware

才子佳人的博客 1398

Codesys电子凸轮Cam表实战:从可视化配置到程序化构建

本文详细介绍了Codesys电子凸轮Cam表的实战应用,从可视化配置到程序化构建的全过程。通过包装机和印刷机案例,解析Cam表的基础设置、调试技巧及动态构建方法,帮助工程师快速掌握电子凸轮技术,提升运动控制精度和效率。

weixin_29309785的博客 298

org.mybatis.spring.mapper.ClassPathMapperScanner和tk.mybatis.spring.annotation.MapperScan

org.mybatis.spring.mapper.ClassPathMapperScanner - No MyBatis mapper was found in '[com.xxx.xxx.xxx]' package. Please check your configuration.

qq_42553504的博客 1625

FreeRTOS-Plus-CLI在STM32F429上的高效移植与调试技巧

本文详细介绍了如何将FreeRTOS-Plus-CLI高效移植到STM32F429平台,并分享关键的调试技巧。内容涵盖使用HAL库进行底层驱动适配(特别是DMA+IDLE中断方案)、工程集成、自定义命令开发以及常见问题解决方案,旨在帮助开发者快速为嵌入式系统添加强大的命令行调试接口,提升开发与维护效率。

weixin_29224309的博客 334

提升仿真效率:Synopsys VCS高级编译选项优化技巧(2023最新版)

本文深入探讨了Synopsys VCS 2023版本中的高级编译选项优化技巧,帮助工程师提升仿真效率。通过并行编译、智能代码分析、精准覆盖率采样等策略,结合真实案例展示如何显著缩短仿真周期并优化资源使用,适用于数字芯片验证和大型SoC设计。

weixin_30338481的博客 113

mybatis与spring的整合之ClassPathMapperScanner

mybatis与spring的整合之ClassPathMapperScannerjava配置应用配置类源码分析@MapperScanMapperScannerRegistrar.registerBeanDefinitionsClassPathMapperScanner.doScan父类ClassPathBeanDefinitionScanner.doScan扫描注册bdprocessBeanDef...

yu_kang的博客 1万+

银行卡密码键盘 SM4 ECB模式+ANSI X9.8 格式标准(带主账号信息)PIN 加解密示例

文章目录1.软加解密示例2.知识点①ANSI X9.8 格式标准②主密钥,工作密钥加解密基本概念:加密种类:3.密码键盘操作4.工具 1.软加解密示例 ————————————————————————————————————————————------ 已知数据: 银行测试主密钥TMK: 1234567890ABCDEFABCDEF0987654321 通过签到接口得到: 工作密钥密文KeyVal...

老孟嘚吧嘚 6653

MyBatis入门系列(25) -MyBatis-Spring核心之@MapperScan使用及源码分析

注册映射器 在使用Mybatis中,我们需要将Mapper接口注册到Spring中,这叫注册映射器。 注册映射器的方法根据你的配置方法,即经典的 XML 配置或新的 3.0 以上版本的 Java 配置(也就是常说的 @Configuration),而有所不同。 XML 配置 在你的 XML 中加入 MapperFactoryBean 以便将映射器注册到 Spring 中。就像下面一样: <bean id="userMapper" class="org.mybatis.spring.mapper.Map

记录知识、锤炼自我 7760

Cadence PSpice 仿真6:反向放大器傅里叶仿真(FFT,谐波分析)实战图文教程

总谐波失真(THD)指音频信号源通过功率放大器时,由于非线性元件所引起的输出信号比输入信号多出的额外谐波成分。比如理想运放输出为5V 1Khz的正玄波时,实际输出的信号按照傅里叶展开后不但含有5V 1KHZ的分量,还有1V 2KHZ的分量,那么多出来的1V的分量就是二次谐波,二次谐波失真系数就是20%,由于任意1个波形按照傅里叶展开是可以展开到n次的,所以除了二次谐波外,输出的信号还有3,4,5……n次谐波,随着n的变大谐波的分量会变小,总谐波失真系数就是所有谐波分量和1次谐波(基波)的比值。Cadence

fydar的博客 4956

Unity 佳能SDK 及数据获取

3. 把CameraControl 下面只要是绿色的 .cs 文件都复制到Unity 中。1. 填写信息跟官方申请SDK,大概1-2个工作日会邮件回复你。2. 将SDK这两个文件放到 Unity Plugins文件夹。

我知道你很急,但是路要一步步走 1477

MyBatis-Spring核心之MapperScan使用及源码分析

在使用Mybatis中,我们需要将Mapper接口注册到Spring中,这叫注册映射器。注册映射器的方法根据你的配置方法,即经典的 XML 配置或新的 3.0 以上版本的 Java 配置(也就是常说的 @Configuration),而有所不同。

Roy0826的博客 9164

2026华为OD面试题084:贪心的商人

商人经营一家店铺,有 `number` 种商品。由于仓库限制,每件商品的最大持有数量是 `item[index]`。 每种商品每天有一个价格 `item_price[item_index][day]`。通过对商品买进和卖出获取利润,请给出商人在 `days` 天内能获取到的最大利润。 注:同一件商品可以反复买进和卖出。 输入描述: - 第一行输入商品数量 `number` - 第二行输入商人售货天数 `days` - 第三行输入 `number` 个整数,表示每件商品的最大持有数量 `item[in

琅嬛福地 273

MyBatis-Spring Mapper自动扫描机制揭秘:@MapperScan注解的完整使用手册

🚀 **快速掌握MyBatis-Spring集成框架中最重要的自动配置神器!** 在Spring Boot和MyBatis集成的开发中,`@MapperScan`注解是实现Mapper自动注册的终极利器。通过本文,你将彻底理解这个强大注解的工作原理和最佳实践。💡 MyBatis-Spring集成框架中的`@MapperScan`注解是Spring 3.1+环境下配置MyBatis映射器的首选

gitblog_00994的博客 661

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

MyBatis 整合Spring解析 【侧重mapper怎么变成bean】

基于spring提供的接口,ImportBeanDefinitionRegistrar 接口介绍: ImportBeanDefinitionRegistrar类只能通过其他类@Import的方式来加载,通常是启动类或配置类。(在mybatis 通过Mapper Scan 注解实现) 使用@Import,如果括号中的类是ImportBeanDefinitionRegistrar的实现类,则会调用接口方法,将其中要注册的类注册成bean。 实现该接口的类拥有注册bean的能力。 官方说明: /** .

Heihei 's note 1176

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

使用MyBatis时为什么Dao层不需要@Repository

问题Service层注入Dao时, Intellij 总会以红色波浪线提示我们 12@Autowiredprivate UserDao userDao; Could not autowire. No beans of ‘UserDao’ type found.Checks autowiring problems in a bean class. 尽管我...

hehyyoulan的博客 6383

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

@Repository与@Mapper

问题 Service层注入Dao时, Intellij 总会以红色波浪线提示我们 @Autowired private UserDao userDao; Could not autowire. No beans of ‘UserDao’ type found. Checks autowiring problems in a bean class. 尽管我们都知道 Dao 层的 Bean 实际上都是有的,并且可以设置关闭这恼人的提示,但是我们有没有想过为什么 Intellij 就找不到这个 Bean 呢?甚

Ryze 505

mybatis plus 按月的数据_深入理解Mybatis解析Mapper底层原理

背景最近在使用高版本Spring Boot 2.x整合mybatis-plus 3.4.1时,控制台出现大量的warn提示XxxMapper重复定义信息:Bean already defined with the same name。2020-12-0719:37:26.025WARN25756---[main]o.m.s.mapper.ClassPa...

weixin_39819671的博客 710

Mybatis的Mapper扫描机制:@MapperScan源码

通过@Import注解导入了MapperScannerRegistrarMapperScannerRegistrar向容器中注入是一个BeanDefinitionRegistryPostProcessor,将会被Spring容器回调方法在方法中创建了,并且调用ClassPathMapperScanner的scan方法重写了父类ClassPathBeanDefinitionScanner的doScan方法,在扫描完Bean获取到BeanDefinition后,在方法对其进行了额外的处理。

zzzj的博客 9259

ClassPathMapperScanner具体是如何工作的?

注解配置:首先,开发者在配置类上使用注解指定要扫描的包路径。初始化与配置:当 Spring 应用上下文启动时,作为的实现,在 Spring 上下文刷新之前处理注解,初始化并配置。扫描过程根据配置的包路径扫描这些包及其子包,查找所有符合要求的组件(即 Mapper 接口)。注册 Bean:对于找到的每个 Mapper 接口,创建相应的并将其注册到 Spring 容器中。自动扫描自动扫描指定包路径下的 Mapper 接口。灵活配置:支持通过注解或接口类型过滤扫描结果。动态代理:利用。

Java的专栏 419

浅入浅出Mybatis:(二)Mapper interface加载过程

前言 在上一篇中,我们对MyBatis的整体项目结构进行了大览,本篇,开始正式进入源码分析的第一篇,来一起了解一下MyBatis的mapper interface与XML配置文件的加载过程。 本篇源代码基于SpringBoot 1.5x,Mybatis-spring 1.3x、Mybatis 3.4x。 SpringBoot加载MyBaits的过程 在Spring项目中,我们对Mybatis进行配...

wtopps的专栏 4796

基于MapperScan注解的Mybatis动态代理加载机制

1.在springboot项目通过MapperScan注解方式,扫描dao,并通过动态代理的方式。 /** * 程序注解配置 * * @author ruoyi */ @Configuration // 表示通过aop框架暴露该代理对象,AopContext能够访问 @EnableAspectJAutoProxy(exposeProxy = true) // 指定要扫描的Mapper类的包的路径 @MapperScan("com.ruoyi.**.mapper") public class Ap

xl649138628的专栏 1438

spring集成Mybatis学习三种方式扫描加载mapper接口

@MapperCan @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(MapperScannerRegistrar.class) public @interface MapperScan { /** * Alias for the {@link #basePackages()} attribute. Allows for more concise * annotatio.

qq_41665121的博客 2701

ClassPathMapperScanner 重写了 isCandidateComponent 方法

ClassPathMapperScanner 重写了 isCandidateComponent 方法

u014244856的博客 391

mybatis-spring注解MapperScan的原理

很多开发者应该都知道,我们只使用@MapperScan这个注解就可以把我们写的Mybatis的Mapper接口加载到Spring的容器中,不需要对每个Mapper接口加@Mapper这个注解了,加快了我们开发的效率。

接需求(Java),各个平台都同名,欢迎搜索关注 970

@MapperScan源码解析

MapperScan以@Import为切入点的注入一个类型为MapperScannerConfigurer的BeanDefinitionMapperScannerConfigurer继承BeanDefinitionRegistryPostProcessor接口,在某个阶段执行postProcessBeanDefinitionRegistry方法。

好记性不如烂笔头 1614
上一篇: Java垃圾回收机制
下一篇: Mybatis3源码分析(21)-Mapper实现-动态代理
风云叶易
博客等级 码龄16年 54粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值