`
blue2048
  • 浏览: 183700 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Mybatis深入剖析 - 配置框架初始化分析

阅读更多

原始的初始化流程

1.    配置Configuration xml文件

2.  SqlSessionFactoryBuilder.build拿到SqlSessionFactory(全局唯一)

3.  代码中的调用如下

       SqlSession session= sqlSessionFactory.openSession();

       UserDao userDao = session.getMapper(UserDao.class);

       UserVo vo = new UserVo();

       vo.setName("a")

       List<UserVo> users = userDao.queryUsers(user);

 

结合spring的初始化流程分析

以spring配置为例,对SqlSessionFactoryBean和SqlSessionTemplate进行分析

 

<bean id="bssSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="configLocation" value="classpath:mybatis-config.xml" />
        <property name="mapperLocations" value="classpath:/mapper/**/*Mapper.xml"></property>
        <property name="dataSource" ref="bssDataSource" />
 </bean>

 
 

进入SqlSessionFactoryBean类,其核心的初始化方法

 

在此方法初始化Mybatis核心类,Configuration,初始化的顺序如下

 

    a) 根据configLocation初始化配置信息

 

xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
            configuration = xmlConfigBuilder.getConfiguration();

 
      b) 根据typeAliasesPackage加载类别名(typeAliasesPackage:它一般对应我们的实体类所在的包,这个时候会自动取对应包中不包括包名的简单类名作为包括包名的别名。多个package之间可以用逗号或者分号等来进行分隔。

      c) 根据typeAliases接在xml配置的别名

      d) 根据typeHandlersPackage和typeHandlers加载自定义的类型转化类

      e) 根据传入的TransactionFactory构造configuration的Environment,如果为设置此项,默认使用spring的SpringManagedTransactionFactory

      f) 根据mapperLocations,调用XMLMapperBuilder解析mapper文件,Mapper文件中的片段解析成MappedStatement对象,以Id为key存储在Configuration的map中

      g) SqlSessionFactoryBuilder根据初始化好的configuration,构造SqlSessionFactory


              

public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

 
 SqlSessionTemplate是spring封装mybatis的另一个重要类,这个类是所有数据库操作的接口门面

 

 <bean id="bssSqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="bssSqlSessionFactory" />
    </bean>

 
 a)       根据构造函数的sqlSessionFactory,executorType,exceptionTranslator初始化,其中executorType有以下三种,分别对应了不同的sql执行策略

 

public enum ExecutorType {
  SIMPLE, REUSE, BATCH
}

 

 b)       这里可能比较重要的是sqlSession的代理对象,看拦截器的代码可以知道,此代理的作用是在非事务的session操作进行提交;异常处理;session close

 

 this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
                SqlSessionFactory.class.getClassLoader(),
                new Class[] { SqlSession.class }, 
                new SqlSessionInterceptor());

 
 

    private class SqlSessionInterceptor implements InvocationHandler {
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            final SqlSession sqlSession = SqlSessionUtils.getSqlSession(
                    SqlSessionTemplate.this.sqlSessionFactory,
                    SqlSessionTemplate.this.executorType,
                    SqlSessionTemplate.this.exceptionTranslator);
            try {
                Object result = method.invoke(sqlSession, args);
                if (!SqlSessionUtils.isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
                    sqlSession.commit();
                }
                return result;
            } catch (Throwable t) {
                Throwable unwrapped = ExceptionUtil.unwrapThrowable(t);
                if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
                    Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
                    if (translated != null) {
                        unwrapped = translated;
                    }
                }
                throw unwrapped;
            } finally {
                SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
            }
        }
    }

 
 

 

 附buildSqlSessionFactory源码

 

 protected SqlSessionFactory buildSqlSessionFactory() throws IOException {

        Configuration configuration;
        
        XMLConfigBuilder xmlConfigBuilder = null;
        if (this.configLocation != null) {
            xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
            configuration = xmlConfigBuilder.getConfiguration();
        } else {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Property 'configLocation' not specified, using default MyBatis Configuration");
            }
            configuration = new Configuration();
            configuration.setVariables(this.configurationProperties);
        }
                
        if (StringUtils.hasLength(this.typeAliasesPackage)) {
            String[] typeAliasPackageArray = StringUtils.tokenizeToStringArray(this.typeAliasesPackage, 
                ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
            for (String packageToScan : typeAliasPackageArray) {
                configuration.getTypeAliasRegistry().registerAliases(packageToScan);    
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Scanned package: '" + packageToScan + "' for aliases");
                }
            }
        }

        if (!ObjectUtils.isEmpty(this.typeAliases)) {
            for (Class<?> typeAlias : this.typeAliases) {
                configuration.getTypeAliasRegistry().registerAlias(typeAlias);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Registered type alias: '" + typeAlias + "'");
                }
            }
        }

        if (!ObjectUtils.isEmpty(this.plugins)) {
            for (Interceptor plugin : this.plugins) {
                configuration.addInterceptor(plugin);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Registered plugin: '" + plugin + "'");
                }
            }
        }

        if (StringUtils.hasLength(this.typeHandlersPackage)) {
            String[] typeHandlersPackageArray = StringUtils.tokenizeToStringArray(this.typeHandlersPackage, 
                ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
            for (String packageToScan : typeHandlersPackageArray ) {
                configuration.getTypeHandlerRegistry().register(packageToScan);    
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Scanned package: '" + packageToScan + "' for type handlers");
                }
            }
        }
        
        if (!ObjectUtils.isEmpty(this.typeHandlers)) {
            for (TypeHandler<?> typeHandler : this.typeHandlers) {
                configuration.getTypeHandlerRegistry().register(typeHandler);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Registered type handler: '" + typeHandler + "'");
                }
            }
        }

        if (xmlConfigBuilder != null) {
            try {
                xmlConfigBuilder.parse();
                
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Parsed configuration file: '" + this.configLocation + "'");
                }
            } catch (Exception ex) {
                throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex);
            } finally {
                ErrorContext.instance().reset();
            }
        }

        if (this.transactionFactory == null) {
            this.transactionFactory = new SpringManagedTransactionFactory(this.dataSource);
        }

        Environment environment = new Environment(this.environment, this.transactionFactory, this.dataSource);
        configuration.setEnvironment(environment);
        
        if (!ObjectUtils.isEmpty(this.mapperLocations)) {
            for (Resource mapperLocation : this.mapperLocations) {
                if (mapperLocation == null) {
                    continue;
                }

                // this block is a workaround for issue http://code.google.com/p/mybatis/issues/detail?id=235
                // when running MyBatis 3.0.4. But not always works. 
                // Not needed in 3.0.5 and above.
                String path;
                if (mapperLocation instanceof ClassPathResource) {
                    path = ((ClassPathResource) mapperLocation).getPath();
                } else {
                    path = mapperLocation.toString();
                }

                try {
                    XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
                            configuration, path, configuration.getSqlFragments());
                    xmlMapperBuilder.parse();
                } catch (Exception e) {
                    throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
                } finally {
                    ErrorContext.instance().reset();
                }

                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Parsed mapper file: '" + mapperLocation + "'");
                }
            }
        } else {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Property 'mapperLocations' was not specified or no matching resources found");
            }
        }

        return this.sqlSessionFactoryBuilder.build(configuration);
    }

 

 

 

 

分享到:
评论

相关推荐

    Mybatis系列教程Mybatis源码剖析共15页.pd

    SqlSessionFactory可以通过Configuration配置类初始化,配置文件通常包含数据库连接信息、映射文件路径等。 3. **SqlSession**:SqlSession是与数据库交互的接口,提供了增删查改操作。每次数据库操作后,建议关闭...

    自定义mybatis流程分析.rar

    1. 配置初始化:MyBatis启动时会读取配置文件(mybatis-config.xml),加载全局配置、数据源、事务管理器等信息。同时,它还会扫描并加载所有的Mapper配置文件,构建出Mapper接口与XML配置的映射关系。 2. SQL会话...

    MyBatis源码详解学习.zip

    SqlSessionFactory根据配置文件(如mybatis-config.xml)初始化,提供了一种线程安全的方式来获取SqlSession,后者是执行SQL命令的接口。 在执行SQL时,MyBatis的Executor执行器起着核心作用。它有SimpleExecutor、...

    spring源码合集spring源码合集

    本合集深入剖析了Spring的诸多关键特性,包括依赖注入、配置类解析、Bean生命周期管理、以及与MyBatis的整合等,旨在帮助读者构建起对Spring全面而深入的认识。 1. **依赖注入源码解析**:在"06-Spring之依赖注入...

    lss.zip项目Demo

    本文将深入剖析该项目,帮助读者理解其核心概念和技术栈。 一、SpringBoot简介 SpringBoot是Spring框架的简化版,旨在简化Spring应用的初始搭建以及开发过程。它预设了常见的配置,如Tomcat服务器、Spring MVC、...

    springboot+mybatis简单选课系统demo.zip

    Spring Boot以其便捷的初始化和配置,使得创建和运行微服务变得极其简单。MyBatis则是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射,有效解决了ORM的难题。 1. **需求分析**:在构建选课系统时,...

    spring原理技术详细解析 深入剖析

    它们负责实例化、配置、初始化和装配对象,是Spring进行DI的基础。 4. **IoC容器**:IoC(Inversion of Control,控制反转)是DI的另一种表述方式,Spring IoC容器负责管理对象的生命周期和对象之间的依赖关系。 5...

    Spring+MyBatis企业应用实战 hrmapp源码下载

    本篇将深度剖析"Spring+MyBatis企业应用实战 hrmapp源码下载"中的核心概念和技术要点,帮助开发者深入理解这两个框架的协同工作原理,提升项目开发效率。 首先,Spring框架以其强大的依赖注入(DI)和面向切面编程...

    毕设项目:基于springboot+mybatis的员工信息管理系统.zip

    SpringBoot的核心优势在于其“开箱即用”的特性,通过自动配置和起步依赖,可以极大地减少项目初始化的复杂度。在本系统中,SpringBoot负责提供基础的web服务和依赖管理,使得系统能够快速启动并运行。 MyBatis则是...

    官方原版源码spring-framework-5.1.0.RELEASE.zip

    2. **Spring Beans**:实现了IoC容器,通过XML或注解方式配置bean,并负责bean的初始化、装配和销毁。 3. **Spring AOP**:面向切面编程模块,允许定义方法拦截器和切入点,实现代码的解耦和模块化。 4. **Spring ...

    基于SpringBoot和Vue框架的创新方法推理系统的设计与实现.docx

    首先,SpringBoot框架是Java生态系统中的一个重要组件,它简化了传统Spring应用程序的初始化和配置过程。在论文中,作者详细阐述了SpringBoot的开发流程,包括如何快速搭建项目、设置依赖、编写配置文件等步骤,帮助...

    马士兵Spring源码剖析文档

    容器通过XML、注解或Java配置来管理Bean的生命周期,包括初始化、配置、装配和销毁等步骤。 **Bean对象的管理**涉及Bean的实例化、配置、作用域、初始化和销毁。Spring提供了多种Bean的作用域,如单例(Singleton)...

    spring源码解读-地址.txt

    下面,我们将从以下几个方面对Spring框架进行深入剖析:Spring AOP(面向切面编程)、Spring Boot、Spring IoC容器以及Spring与MyBatis的集成。 ### Spring AOP(面向切面编程) 面向切面编程(Aspect Oriented ...

    Java进阶SpringBoot原理深入及源码剖析共18页

    接着,源码分析可能包括SpringApplication的启动流程,包括如何加载和执行配置,如何初始化ApplicationContext,以及Spring Boot Application Runner和CommandLineRunner接口的使用。 在数据访问层面,文档可能会...

    SPRING技术内幕:深入解析SPRING架构与设计原理

    书中深入剖析了Spring框架的核心架构和设计原理,旨在帮助读者理解和掌握Spring的内在工作机制,提升在实际项目中的应用能力。 Spring作为Java企业级应用开发的首选框架,其灵活性、可扩展性和模块化设计深受开发者...

    java框架SSM架构教程

    SpringBoot是Spring的现代化版本,它简化了Spring应用的初始搭建和配置,强调“约定优于配置”的原则。《SpringBoot实战_清晰版.pdf》介绍了SpringBoot的快速启动、自动配置、内嵌服务器、健康检查、微服务集成等...

    springboot源码解析视频

    - `SpringApplication`是SpringBoot启动的入口,它负责初始化SpringApplicationContext,并处理运行时环境。 3. **自动配置机制** - `@Conditional`注解家族:例如`@ConditionalOnClass`、`@ConditionalOnBean`等...

Global site tag (gtag.js) - Google Analytics