Mybatis初始化(全局配置文件解析)

文章详细阐述了Mybatis初始化过程,主要涉及全局配置文件mybatis-config.xml的加载,通过Resources类获取输入流,然后使用XMLConfigBuilder解析配置,创建Configuration对象,最终构建SqlSessionFactory。解析过程中包括了XPathParser的使用,Configuration对象的构建以及mappers标签的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Mybatis初始化(全局配置文件解析)

实际上就是读取解析mybatis-config.xml配置文件里面的各种标签,并创建一个 Configuration 对象,把配置文件中的内容存到 Configuration 对象中(可以看作mybatis工作所需的上下文,存储mybatis工作时所需要的信息),返回SqlSessionFactory(实际上返回的是其子类DefaultSqlSessionFactory对象),Configuration 对象是DefaultSqlSessionFactory的属性

    @Test
    void t1() throws IOException {
        String resource = "mybatis-config.xml";
        // getResourceAsStream方法内部通过classLoader加载mybatis-config.xml配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 通过 SqlSessionFactoryBuilder 创建 SqlSessionFactory 实例对象(解析mybatis-config.xml配置)
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.queryById(1L);

        System.out.println("user = " + user);
    }

流程

1. 通过 Resources 类的 getResourceAsStream 方法加载全局配置文件 mybatis-config.xml

   @Test
   void t1() throws IOException {
       String resource = "mybatis-config.xml";
   	// getResourceAsStream方法内部通过classLoader加载mybatis-config.xml配置文件
       InputStream inputStream = Resources.getResourceAsStream(resource);
		// 通过 SqlSessionFactoryBuilder 创建 SqlSessionFactory 实例对象(解析mybatis-config.xml配置)
       SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

       SqlSession sqlSession = sqlSessionFactory.openSession();
       UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
       User user = userMapper.queryById(1L);

       System.out.println("user = " + user);
   }

2. SqlSessionFactory的build方法中创建XMLConfigBuilder对象用于构建Configuration对象

public SqlSessionFactory build(InputStream inputStream) {
   return build(inputStream, null, null);
 }

 public SqlSessionFactory build(InputStream inputStream, String environment) {
   return build(inputStream, environment, null);
 }

 public SqlSessionFactory build(InputStream inputStream, Properties properties) {
   return build(inputStream, null, properties);
 }

 /**
  *  核心build方法
  */
 public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
   try {
     // 创建XMLConfigBuilder对象(XMLConfigBuilder构造方法创建了一个XPathParser对象用于解析xml配置文件)
     XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
     ...
   }
 }

2.1 XMLConfigBuilder构造方法

 public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
   // 创建
   this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
 }
2.1.1 XPathParser
 public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
   commonConstructor(validation, variables, entityResolver);
   // 将inputStream转为document
   this.document = createDocument(new InputSource(inputStream));
 }

2.2 在2.1中通过this调用另一个构造方法,此 构造方法中创建 Configuration 对象

 private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
   // 创建Configuration对象
   super(new Configuration());
   ErrorContext.instance().resource("SQL Mapper Configuration");
   this.configuration.setVariables(props);
   this.parsed = false;
   this.environment = environment;
   this.parser = parser;
 }

2.3 Configuration 对象构造方法

typeAliasRegistry向一个名为typeAliases的map注册别名,其实就是map.put(“alias”, Class)
languageRegistry注册使用的driver,告诉mybatis使用的哪种数据库

 public Configuration() {
   typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
   typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);

   typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
   typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
   typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
   ...
     
   languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
   languageRegistry.register(RawLanguageDriver.class);
 }

3. 调用parse()方法解析配置文件

 /**
  *  核心build方法
  */
 public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
   try {
     // 创建XMLConfigBuilder对象(XMLConfigBuilder构造方法创建了一个XPathParser对象用于解析xml配置文件)
     XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
     // 调用parse()方法解析配置文件,并返回Configuration(可以看作对前面创建的Configuration做属性填充)
     return build(parser.parse());
     ...
   }
 }

3.1 parse方法解析配置文件标签

 public Configuration parse() {
   if (parsed) {
     throw new BuilderException("Each XMLConfigBuilder can only be used once.");
   }
   parsed = true;
   parseConfiguration(parser.evalNode("/configuration"));
   return configuration;
 }

 /*
     解析全局配置文件mybatis-config.xml中的各种标签,存储到Configuration对象中
  */
 private void parseConfiguration(XNode root) {
   try {
     // issue #117 read properties first
     // 解析properties标签
     propertiesElement(root.evalNode("properties"));
     // 解析settings标签
     Properties settings = settingsAsProperties(root.evalNode("settings"));
     loadCustomVfs(settings);
     loadCustomLogImpl(settings);
     // typeAliases标签
     typeAliasesElement(root.evalNode("typeAliases"));
     pluginElement(root.evalNode("plugins"));
     objectFactoryElement(root.evalNode("objectFactory"));
     objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
     reflectorFactoryElement(root.evalNode("reflectorFactory"));
     // 此方法中如果没有解析到对应的配置,使用默认配置
     settingsElement(settings);
     // read it after objectFactory and objectWrapperFactory issue #631
     environmentsElement(root.evalNode("environments"));
     databaseIdProviderElement(root.evalNode("databaseIdProvider"));
     typeHandlerElement(root.evalNode("typeHandlers"));
     // 解析mapper,放到Configuration对象中的一个map中,key为Class对象,value值为代理工厂
     mapperElement(root.evalNode("mappers"));
   } catch (Exception e) {
     throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
   }
 }

3.2 解析mappers标签

https://www.yuque.com/u5277/rxcryq/gb65gpcngxurkwyt

4. 调用 build 方法创建 SqlSessionFactory 并返回

 public SqlSessionFactory build(Configuration config) {
     // Configuration 存储在 DefaultSqlSessionFactory 中
     return new DefaultSqlSessionFactory(config);
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值