- mybaits spring 实现原理
- spring 容器启动过程
Spring 中常见类介绍
1 BeanDefinition 用于封装 spring bean 的配置信息
2 BeanDefinitionRegistry 用于存放解析后的BeanDefinition对象,spring 提供了扩展机制,允许用户在 spring 框架启动时动态的往BeanDefinitionRegistry容器中注册对象
3 BeanFactory 是 Spring 的Bean 工厂,负责 Bean 创建和属性注入
4 BeanFactoryPostProcessor 是 spring 提供的扩展机制,用于在所有 Bean 配置信息解析完成后,修改 Bean 工厂信息.例如向BeanDefinitionRegistry注册BeanDefinition对象
5 ImportBeanDefinitionRegistrar接口作用于 Spring 解析 Bean 的配置阶段,当解析@Configuration 注解时调用. 需要配合@Import 注解使用
6 BeanPostProcessor Bean 的后置处理器.在 Bean 初始化方法(init-method 属性指定的方法或者 afterPropertiesSet()方法)调用前后,会执行 BeanPostProcessor的拦截逻辑
7 ClassPathBeanDefinitionScanner 是BeanDefinition扫描器,能够对象指定包下的 Class 进行扫描,将 Class 转换为BeanDefinition对象注册到BeanDefinitionRegistry 容器中
8 FactoryBean 是 Spring 中的工厂 bean,通常用于处理 spring 中配置较为复杂或者由动态代理生成的 Bean 实例.
实现了该接口的 Bean 不能作为普通的 Spring bean 使用而是作为单个对象的工厂.
当通过 Bean 名称获取 FactoryBean 实例时,获取到的并不是FactoryBean对象本身,而是FactoryBean对象 getObject()方法返回的对象
- BeanDefinition 用于封装 spring bean 的配置信息,spring bean 配置方式有 3 种:
//1 xml 方式配置
<beans>
<bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>
//2 java 注解, 如:@Service @Component
//3 java config 方式 (spring 3.0 开始支持)
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
Spring 容器在启动的时候,首先会对 Bean 的配置进行解析,把 Bean 的配置信息转换为BeanDefinition对象.
BeanDefinition是一个接口,通过不同的实现类来描述不同方式配置的 Bean 信息
- BeanFactoryPostProcessor 是 spring 提供的扩展机制,用于在所有 Bean 配置信息解析完成后,修改 Bean 工厂信息.例如向BeanDefinitionRegistry注册BeanDefinition对象
@FunctionalInterface
public interface BeanFactoryPostProcessor {
/**
* 解析完Bean 配置并且注册到BeanDefinitionRegistry容器后,
*
* 就会获取BeanFactoryPostProcessor接口的所有实现类,调用所有BeanFactoryPostProcessor对象的postProcessBeanFactory()方法
* @param beanFactory
* @throws BeansException
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
- BeanPostProcessor Bean 的后置处理器.在 Bean 初始化方法(init-method 属性指定的方法或者 afterPropertiesSet()方法)调用前后,会执行 BeanPostProcessor的拦截逻辑
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
spring 容器启动过程
- 解析所有Bean 配置信息,包括 xml 配置,java 注解以及 java config方式配置的 Bean,把 Bean 的配置信息转换为BeanDefinition对象.,注册到 BeanDefinitionRegistry容器中
- BeanDefinitionRegistry获取实现了BeanFactoryPostProcessor接口的 Bean 定义,然后实例化 Bean.调用所有BeanFactoryPostProcessor对象的 postProcessBeanFactory()方法
- 根据 BeanDefinitionRegistry 容器中的BeanDefinition对象.实例化所有的单例 bean,并且对 bean 的属性进行填充
- 执行所有实现了BeanPostProcessor接口的postProcessBeforeInitialization()方法
- 执行bean的初始化方法(初始化方法: 包括配置bean的 init-method方法或者通过实现 InitializingBean接口重写的afterPropertiesSet()方法)
- 执行所有实现了BeanPostProcessor接口的postProcessAfterInitialization()方法
mybatis 与 spring 整合
- mybatis-spring 中文文档 //mybatis.org/spring/zh/index.html
- 什么是 MyBatis-Spring?
MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException
- 要和 Spring 一起使用 MyBatis,需要在 Spring 应用上下文中定义至少两样东西:一个 SqlSessionFactory 和至少一个数据映射器类。
// 1 引入 MyBatis-Spring 依赖,只需要在类路径下包含 mybatis-spring-2.0.7.jar 文件和相关依赖即可
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
// java config 方式配置 SqlSessionFactory,MapperScannerConfigurer
@Configuration
@MapperScan("org.mybatis.spring.sample.mapper") //扫描 mapper 文件
public class MyBatisConfig {
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource());
return factoryBean.getObject();
}
@Bean
public SqlSessionTemplate sqlSession() throws Exception {
return new SqlSessionTemplate(sqlSessionFactory());
}
}
mybatis-spring 中 Mapper 动态代理对象注册过程
- mybatis-spring 模块提供了@MapperScan注解,该注解用于扫描指定包下的 Mapper 接口并创建 Mapper 动态代理对象
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
//通过@Import 导入 BeanDefinition 注册类 MapperScannerRegistrar
@Import({MapperScannerRegistrar.class})
public @interface MapperScan {
//扫描包路径
String[] value() default {};
//扫描包路径
String[] basePackages() default {};
//扫描Mapper 接口对应的 class 对象
Class<?>[] basePackageClasses() default {};
//bean 名称生成策略
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
//只扫描 某种注解修饰的类或者接口
Class<? extends Annotation> annotationClass() default Annotation.class;
//只扫描某种类型的子类型
Class<?> markerInterface() default Class.class;
//指定使用哪个sqlSessionTemplate对象
String sqlSessionTemplateRef() default "";
String sqlSessionFactoryRef() default "";
Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;
}
@MapperScan注解通过@Import 导入 BeanDefinition 注册类 MapperScannerRegistrar
public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
private ResourceLoader resourceLoader;
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//工具类,用于获取MapperScan注解属性值
AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
// 创建spring ClassPathMapperScanner对象
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
... 配置了xxx 属性则赋值给ClassPathMapperScanner对象
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();
//扫描路径下的 java 接口 bean 注册到 spring 容器
scanner.doScan(StringUtils.toStringArray(basePackages));
//...接下来去学习 spring 吧
}
}
spring 学习文档:
- spring 官方文档中文版 https://www.springcloud.cc/spring-reference.html
- Spring Framework 5 中文文档 https://www.cntofu.com/book/95/index.html
- mybatis-spring 中文文档 //mybatis.org/spring/zh/index.html