spring是怎样管理mybatis的及注入mybatis mapper bean的
1.spring启动mybatis的两个重要类:SqlSessionFactoryBean和MapperFactoryBean,这两个类都是org.mybatis.spring jar包的。是用来启动mybatis的关键,spring为什么能识别这两个类?因为这两个类实现了spring的接口。这里面的重点就是 org.mybatis.spring.SqlSessionFactoryBean 与 o
spring bean 加载的拓展:https://blog.csdn.net/qq_31854907/article/details/107249516
1.spring启动mybatis的两个重要类:SqlSessionFactoryBean和MapperFactoryBean,这两个类都是org.mybatis.spring jar包的。
是用来启动mybatis的关键,spring为什么能识别这两个类?因为这两个类实现了spring的接口。
这里面的重点就是 org.mybatis.spring.SqlSessionFactoryBean 与 org.mybatis.spring.mapper.MapperFactoryBean[b] 实现了 spring 的接口,并产生对象。
org.mybatis.spring.SqlSessionFactoryBean
org.mybatis.spring.mapper.MapperFactoryBean
通过上面我们发现mybatis加载各个mapper bean 至spring容器是通过集成spring 的 InitializingBean 接口来实现bean的拓展
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--dataSource属性指定要用到的连接池-->
<property name="dataSource" ref="dataSource"/>
<!--configLocation属性指定mybatis的核心配置文件-->
<property name="configLocation" value="config/Configuration.xml"/>
</bean>
myabtis的mapper bean实现类叫org.mybatis.spring.mapper.MapperFactoryBean
所在jar包为org.mybatis.spring包
说白了就是mybatis的java实现类是MapperFactoryBean,所在jar包层次org.mybatis.spring.mapper.MapperFactoryBean
<!--sqlSessionFactory属性指定要用到的SqlSessionFactory实例-->
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
<!--mapperInterface属性指定映射器接口,用于实现此接口并生成映射器对象--> <property name="mapperInterface" value="com.yihaomen.mybatis.inter.IUserOperation" />
</bean>
mybatis的启动,第一步就是产生sqlsessionFactory
在使用mybatis框架时,第一步就需要产生SqlSessionFactory类的实例(相当于是产生连接池)
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.apache.ibatis.session;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.exceptions.ExceptionFactory;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
public class SqlSessionFactoryBuilder {
public SqlSessionFactoryBuilder() {
}
public SqlSessionFactory build(Reader reader) {
return this.build((Reader)reader, (String)null, (Properties)null);
}
public SqlSessionFactory build(Reader reader, String environment) {
return this.build((Reader)reader, environment, (Properties)null);
}
public SqlSessionFactory build(Reader reader, Properties properties) {
return this.build((Reader)reader, (String)null, properties);
}
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
SqlSessionFactory var5;
try {
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
var5 = this.build(parser.parse());
} catch (Exception var14) {
throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException var13) {
}
}
return var5;
}
public SqlSessionFactory build(InputStream inputStream) {
return this.build((InputStream)inputStream, (String)null, (Properties)null);
}
public SqlSessionFactory build(InputStream inputStream, String environment) {
return this.build((InputStream)inputStream, environment, (Properties)null);
}
public SqlSessionFactory build(InputStream inputStream, Properties properties) {
return this.build((InputStream)inputStream, (String)null, properties);
}
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
SqlSessionFactory var5;
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
var5 = this.build(parser.parse());
} catch (Exception var14) {
throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException var13) {
}
}
return var5;
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
}
从上图中可以看出,SqlSessionFactoryBuilder类负责构建SqlSessionFactory,并且提供了多个build的重载方法。但其实很多都是在调同一签名的方法,例如:
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) ,只是由于方法参数environment和 propertiese都可以为null,
所以为了提供调用的便利性,才提供了下面的三个方法:
public SqlSessionFactory build(InputStream inputStream)
public SqlSessionFactory build(InputStream inputStream, String environment)
public SqlSessionFactory build(InputStream inputStream, Properties properties)
按照上述思路去除重复的,真正的重载方法只有如下三种:
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties)
public SqlSessionFactory build(Reader reader, String environment, Properties properties)
public SqlSessionFactory build(Configuration config)
可以看出,配置信息可以以三种形式提供给SqlSessionFactory的build方法,分别是InputStream(字节流)、Reader(字符流)、Configuration(类),由于字节流与字符流都属于读取配置文件的方式,所以从配置信息的来源就很容易想到构建一个SqlSessionFactory有两种方式,大致代码如下:
(1) 读取xml文件构造方式
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream) ;
(2) 编程构造方式
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) ;
下面先来分析XML文件构造方式的build方法的源码:
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
通过上面这几行代码,就能看出基于XML文件的这种构造方式,通过从XML中读取信息的工作之后,也是构造出Configuration对象之后再继续进行SqlSessionFactory的构建工作的,只是多了些XML的解析工作,所以我们只需单刀直入,直按分析编程构造方式的代码就可以了,或者是直接分析 build(parser.parse())这句代码(参数产生过程先跳过)
编程构造方式的build方法源码如下(基于xml的构造方式的build(parser.parse())最终也是调了这个代码):
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
其实这么看来SqlSessionFactory在mybatis的默认实现类为org.apache.ibatis.session.defaults.DefaultSqlSessionFactory , 其构造过程主要是注入了Configuration的实例对象,Configuration的实例对象即可通过解析xml配置文件产生,也可能通过代码直接构造。以上代码使用了一个设计模式:建设者模式(Builder),SqlSessionFactoryBuilder扮演具体的建造者,Configuration类则负责建造的细节工作,SqlSession则是建造出来的产品。
以下是类图和建造者模式的基本形态图,读者自行对照阅读。
构造者模式是一种对象的创建模式。它可以将一个复杂对象的内部构成特征与对象的构建过程完全分开。
更多推荐
所有评论(0)