Insight MyBatis-Spring 解析过程,调用执行

看懂,再整理出来应该就是真明白了。

疑问:MyBatis-Spring集成,spring 是怎么样托管的?

看源码,这个过程应该是这样的:

1.spring配置文件中注册 MapperScannerConfigurer (看参考1),完成scan Mapper并定义为MapperFactoryBean。scan实现参考:Insight context:component-scan 实现class scan

public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor{
	
    // AbstractApplicationContext.invokeBeanFactoryPostProcessors调用 core!
    // Invoke factory processors registered as beans in the context.
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // 类似context:component-scan 过程,scan指定package的Mapper 接口并注册到beanFactory。
        // 1.create Scanner
        ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
        scanner.setMarkerInterface(this.markerInterface);// addIncludeFilter
        scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);// PropertyValues
        // 2.Scanner.scan 注意super.doScan完成后beanDefinition 的处理
        scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
    }
}// 自定义 Scanner
public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {
	
    /**
     * Calls the parent search that will search and register all the candidates.
     * Then the registered objects are post processed to set them as MapperFactoryBeans
     * 
     */
    @Override
    public Set
   
   
    
     doScan(String... basePackages) {
        Set
    
    
     
      beanDefinitions = super.doScan(basePackages);
        for (BeanDefinitionHolder holder : beanDefinitions) {
            GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();
            
            // 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);
            // 配置sqlSessionFactoryBeanName
            definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
        }
        //...
    }
}
    
    
   
   
...

2.在上述Mapper definition 初始化过程中,需要Inject sqlSessionFactory 也就是调用MapperFactoryBean.setSqlSessionFactory()方法。而在此过程中,首先需要初始化sqlSessionFactory(beanFactory 就是自底向上的完成bean的组装、初始化,链式反应,boom)。

public class MapperFactoryBean
   
   
    
     extends SqlSessionDaoSupport {
    // set 注入
    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        if (!this.externalSqlSession) {
            // 根据sqlSessionFactory 构造sqlSession
            // SqlSessionTemplate 典型的JDK Proxy 应用案例,实现事务的控制 !!!
            this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
        }
    }
    // return an instance of mapperInterface,直接用吧
    public T getObject() throws Exception {
        return getSqlSession().getMapper(this.mapperInterface);
    }
}
   
   
...

3.上述2过程中涉及的sqlSessionFactory初始化

public class SqlSessionFactoryBean {
    
    public void afterPropertiesSet() throws Exception {
    	// 处理过程类似文档 Building SqlSessionFactory without XML
    	this.sqlSessionFactory = buildSqlSessionFactory();
    }
}
...

4.至此,MyBatis-Spring 托管解析、初始化完成。

...

参考:

// http://www.mybatis.org/spring/mappers.html
Scanning for mappers
1.Using the 
   
    element.
2.Using the annotation @MapperScan
3.Using a classic Spring xml file and registering the MapperScannerConfigurer

// http://www.mybatis.org/mybatis-3/getting-started.html
// demo1: Building SqlSessionFactory without XML
DataSource dataSource = BlogDataSourceFactory.getBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
// demo2: Acquiring a SqlSession from SqlSessionFactory
SqlSession session = sqlSessionFactory.openSession();
try {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  Blog blog = mapper.selectBlog(101);
} finally {
  session.close();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值