【MyBatis源码解析】spring-mybatis 源码解析

一。前言

人们总是一边追逐一边回味。既要研究大型分布式框架,单机的优秀框架也不能错过。

一个框架的概览,在于入口,即配置项的解析;在于描述性配置,即如何识别和管理 bean;在于代理,即被管理的 bean 被代理成有什么样行为的类。

二。重要设计

每次使用 mybatis,都会引入 mybatis-spring 包,并且设置两个bean‘,SqlSessionFactoryBean 和 MapperScanConfigurer,并且把 SqlSessionFactoryBean 当作属性配置类,注入 MapperScanConfigurer。

SqlSessionFactoryBean 主要是设置 mapper xml文件包路径和 mybatis 配置文件属性。

MapperScanConfigurer 主要是扫描 mappe 接口,把接口 bean 替换为为 MapperFactoryBean。

1.MapperScannerConfigurer.postProcessBeanDefinitionRegistry(BeanDefinitionRegistry b)。第一步从 applicationContext 取出属性给成员变量(eg: basePackage、sqlSessionTemplateBeanName)赋值。第二步调用ClassPathMapperScanner.Scan(basePackage) 扫描 basePackage 中类文件。

2.ClassPathMapperScanner.Scan(basePackage),调用的是父类 ClassPathBeanDefinitionScanner.Scan(basePackage),父类回调子类的 doScan(basePackage)。doScan(basePackage) 第一步获取父类 Scan 扫描后的 Set 。第二步,对 BeanDefinition 进行处理,增加属性 SqlSessionFactory 和 SqlSessionTemplate 等。

3.ClassPathMapperScanner.processBeanDefinitions(beanDefinitions),即在 步骤2 doScan() 方法中调用,处理扫描 mapper 接口得到的 beanDefinition,接口是没法实例化的,所以在这个方法中,会把 beanDefinition 原有的 beanClass 属性替换为 MapperFactoryBean.class 。即 spring 最终会把扫描到的 mapper 接口实例化成这个类。

MapperFactoryBean 主要作用,提供 jdk 代理类 MapperProxy ,供运行时调用。

1。MapperFactoryBean.checkDaoConfig(),这个方法在父类 DaoSupport 实现的 InitializingBean.afterPropertiesSet() 方法中回调,这个方法主要作用,是调用 MapperRegistry.addMapper(mapperInterface), 把 mapper interface 注册到 MapperRegistry 中的 HashMap<Class, MapperProxyFactory> 中。

2。MapperFactoryBean 是一个工厂 bean,在调用 getObject() 时,会从 MapperRegistry 中,根据 mapper interface 取出 MapperProxyFactory,然后调用 MapperProxyFactory.newInstance() 返回 MapperProxy 实例。

3.MapperProxy 实现了 InvocationHandler,最终在 mapper interface 方法被调用时,会调用这个代理类进行具体方法的执行。

MapperProxy 维护了 Map<Method, MapperMethodInvoker> 缓存,即每个方法都有指定的 Invoker。

1.MapperProxy 在执行 invoke(Object,Method,Object[]) 方法时,会从维护的 map 中找对应方法的 MapperMethodInvoker,然后具体的执行托给 MapperMethodInvoker。

2.Invoker 有两种,一种是 java8 之后才有的 default 方法,转为 DefaultMethodInvoker,使用 MethodHandler.bindTo(object).invokeWithArgument(args) 反射调用。一种是正常的接口方法,转为 PlainMethodInvoker ,使用 MapperMethod 进行方法的执行。

3.MapperMethod.execute(SqlSession, Object[]),增删改查都是使用参数中的 SqlSessionTemplate进行操作。

三。有意思的写法

Optional.ofNullable(param).map(Function<? super T, ? extends U>).orElse();

其中 Function<? super T, ? extends U 是指方法对象。
方法对象指:被 T 类型对象调用处理对象本身,返回 R 类型对象。

还有类中嵌入私有的静态内部类实现内部接口,不同的条件,使用不同的静态内部类。

四。总结

spring-mybatis 通过解析配置中的包路径,扫描路径下的文件,使用工厂 bean,让接口在运行时,有不同的表现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值