总结简述:
-
- 在该xml 文档下配置如下
-
classpath:sqlmap/*/*.xml
-
- 在该xml 文档下配置如下
创建MapperScannerConfigurer
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware
- MapperScannerConfigurer 实现了BeanDefinitionRegistryPostProcessor 接口
- 初始化时,会自动调用 postProcessBeanDefinitionRegistry 方法
-
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { if (this.processPropertyPlaceHolders) { processPropertyPlaceHolders(); } ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); scanner.setAddToConfig(this.addToConfig); scanner.setAnnotationClass(this.annotationClass); scanner.setMarkerInterface(this.markerInterface); scanner.setSqlSessionFactory(this.sqlSessionFactory); scanner.setSqlSessionTemplate(this.sqlSessionTemplate); scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName); scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName); scanner.setResourceLoader(this.applicationContext); scanner.setBeanNameGenerator(this.nameGenerator); scanner.registerFilters(); scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); }
- ClassPathMapperScanner这个扫描器的主要的作用有以下几个:
- 第一扫描basePackage包下面所有的class类
- 第二将所有的class类封装成为spring的ScannedGenericBeanDefinition sbd对象
- 第三过滤sbd对象,只接受接口类,从下面的代码中可以看出
- isCandidateComponent
- 第四完成sbd对象属性的设置,
- 比如设置sqlSessionFactory、BeanClass等,
- 这个sqlSessionFactory是本文接下来要解析的SqlSessionFactoryBean
- 注意scanner
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
- 所以ClassPathMapperScanner 的doScan 要覆盖掉父类的
- 执行processBeanDefinitions,内部设置很关键(说明这里封装的Mapper 接口,都是mapperFactoryBean)
-
definition.setBeanClass(this.mapperFactoryBean.getClass());
- 后续使用 这些Mapper 接口的时候,其实获取实例调用的是
-
public T getObject() throws Exception { return getSqlSession().getMapper(this.mapperInterface); }
-
- 执行processBeanDefinitions,内部设置很关键(说明这里封装的Mapper 接口,都是mapperFactoryBean)
- 第五将过滤出来的sbd对象通过这个BeanDefinitionRegistry registry
- 注册器注册到DefaultListableBeanFactory中
创建SqlSessionFactoryBean
继承了FactoryBean<SqlSessionFactory>
- 注意 FactoryBean的方法
- 由于继承了InitializingBean 所以bean被创建的过程中
-
执行afterPropertiesSet方法
-
buildSqlSessionFactory
-
} else if (this.configLocation != null) { xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties); configuration = xmlConfigBuilder.getConfiguration(); }
-
return this.sqlSessionFactoryBuilder.build(configuration);
- return new DefaultSqlSessionFactory(config);
-
-
-
执行onApplicationEvent方法
- 用完上面的afterPropertiesSet方法之后,
- 第二个被调用的就是onApplicationEvent方法,
- 这个方法的调用时机是,spring容器初始化完成之后
执行getObject方法
- 第三个被调用的就是getObject方法,
- 该方法是接口FactoryBean<SqlSessionFactory>中的方法。
- 这个方法的调用时机是?
- 首先需要简单介绍一下这个FactoryBean的作用。
- Spring通过反射机制利用<bean>标签的class属性指定实现类实例化Bean
- 过于繁杂
- Spring为此提供了一个org.springframework.beans.factory.FactoryBean<T>的工厂类接口,
- 我们可以通过实现该接口定制实例化Bean的逻辑。
- Spring通过反射机制利用<bean>标签的class属性指定实现类实例化Bean
- 实现了FactoryBean<T>接口的Bean,不同于普通Bean,
- 根据该Bean的ID从BeanFactory中获取的
- 实际上是FactoryBean的getObject()返回的对象,
- 而不是FactoryBean本身,
- 如果要获取FactoryBean对象,请在id前面加一个&符号来获取。