Mybatis之SqlSessionFactoryBean源码初步解析(一)

更新时间:2023-06-20 23:39:59 阅读: 评论:0

Mybatis之SqlSessionFactoryBean源码初步解析(⼀)
⾸先先道歉⼀下, 我之前并没有研究太深⼊,然后发现有些东西写错了。然后7⽉7 号,忙到夜⾥2点改这篇⽂章。改完之后太累了就关了电脑。。。然后没保存发布,⼜重写了⼀遍。
Mybatis 的两个⼊⼝⼀个是SqlSessionFactoryBean, 另外⼀个是MapperScannerConfigurer。这个可以在l 配置中找到。SqlSessionFactoryBean实现了InitializingBean接⼝,InitializingBean接⼝必须得实现afterpropertiest()⽅法,此⽅法将配置⽂件中的各种属性列如 mapperlocation 、typealias、plugins等等放⼊configuration中,configuration就相当于mybatis的⼤管家, 各种解析封装后的属性都会放到这⾥。 然后您会看到
el if (figLocation != null) {
xmlConfigBuilder = new InputStream(), null, figurationProperties);
configuration = Configuration();
xmlConfigBuilder这个东西是解析xml 的⼀个类
xmlConfigBuilder = new InputStream(), null, figurationProperties);
这⾥就是装配配置⽂件
if (xmlConfigBuilder != null) {
try {
老婆用英语怎么说xmlConfigBuilder.par();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Pard configuration file: '" + figLocation + "'");
}
} catch (Exception ex) {
throw new NestedIOException("Failed to par config resource: " + figLocation, ex);
} finally {
ErrorContext.instance().ret();
}
}
继续往下运⾏的时候会发现
xmlConfigBuilder.par();
这个就是开始解析xml了 这边是专门解析下图中configLocation 对应的xml
<configuration>吊兰可以水培吗
<!-- 全局的tting配置根据需要添加需要⼆级缓存延迟加载就可以配置-->
<!-- 配置别名 -->
<typeAlias>
<!-- 批量扫描别名 -->
<package name="batis.pojo"/>
<!--<package name="cn.zx.ssm.po"/>  -->
</typeAlias>
<!-- 使⽤⾃动扫描器时,l⽂件如果和mapper.java接⼝在⼀个⽬录则此处不⽤定义mappers    -->
<mappers>
<package name="batis.mapper" />
</mappers>
</configuration>
这个xml ⾥⾯的最外层标签是configuration;所以下⾯最先解析的是configuration
public Configuration par() {
if (pard) {
throw new BuilderException("Each XMLConfigBuilder can only be ud once.");
}
pard = true;
parConfiguration(parr.evalNode("/configuration"));
return configuration;
}
private void parConfiguration(XNode root) {
try {
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties ttings = ttingsAsProperties(root.evalNode("ttings"));
loadCustomVfs(ttings);
typeAliasElement(root.evalNode("typeAlias"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));复习法
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
ttingsElement(ttings);
// read it after objectFactory and objectWrapperFactory issue #631
environmentsElement(root.evalNode("environments"));
databaIdProviderElement(root.evalNode("databaIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
正月十五的诗句
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cau: " + e, e);
}
}
有configuration标签的话就开始解析了。然后我们主讲⼀下mappers 标签。
mapperElement(root.evalNode("mappers"));
这句话就是解析mappers的⼦元素了
如果⼦元素是package 那么调⽤configuration的addMappers()将包路径扔给configuration.
如果mappers标签的⼦元素标签不是package 。那么得到他⼦元素3个属性的值,分别是resource、url、class 。三者只能同时存在⼀个。同时存在多以⼀个则报异常。因为configuration.addMappers()⽅法最终也是调到XMLMapperBuilder.
configuration.addMappers() ⾥⾯是调⽤mapperRegistry.addMappers()。
private void mapperElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : Children()) {
if ("package".Name())) {
String mapperPackage = StringAttribute("name");
configuration.addMappers(mapperPackage);
} el {
String resource = StringAttribute("resource");
String url = StringAttribute("url");
String mapperClass = StringAttribute("class");
if (resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
InputStream inputStream = ResourceAsStream(resource);
XMLMapperBuilder mapperParr = new XMLMapperBuilder(inputStream, configuration, resource, SqlFragments());
mapperParr.par();
} el if (resource == null && url != null && mapperClass == null) {
ErrorContext.instance().resource(url);
InputStream inputStream = UrlAsStream(url);
XMLMapperBuilder mapperParr = new XMLMapperBuilder(inputStream, configuration, url, SqlFragments());
mapperParr.par();
} el if (resource == null && url == null && mapperClass != null) {
Class<?> mapperInterface = Resources.classForName(mapperClass);
configuration.addMapper(mapperInterface);
} el {
throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
}
ipth}
}
}
}
我对于mapperRegistry是哪⾥来的 很感兴趣。于是我看到了下⾯代码所⽰
protected MapperRegistry mapperRegistry = new MapperRegistry(this);
public void addMappers(String packageName) {
mapperRegistry.addMappers(packageName);
}
这⾥的this 代表的就是Configuration这个类。
进⼊mapperRegistry.addMappers() ⽅法会进⼊下图。 先调⽤下⾯代码中最后⼀个⽅法, 再调⽤上⼀个⽅法。
public void addMappers(String packageName, Class<?> superType) {
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
Set<Class<? extends Class<?>>> mapperSet = Class();
for (Class<?> mapperClass : mapperSet) {
短暂的反义词
addMapper(mapperClass);
}
}
/**
* @since 3.2.2
蛇属相*/
public void addMappers(String packageName) {
addMappers(packageName, Object.class);
}
这边再道个歉。 先不上图了,本来有图的 我忘了保存。 我就嘴说说吧
这边的mapperSet 呢解析出来是什么格式呢:
[interface batis.mapper.DailyMapper, interface batis.mapper.EmployeeMapper]
意思就是interface+全路径。 很有意思的是:⽐如我这样配置的
<package name="batis.mapper" />
那么只会解析batis.mapper下的。 如果你的xml放在st。这个包下, 那么是不会在mapperSet中的。注意看图下的size.
我们继续看调到addMapper()⽅法:
public <T> void addMapper(Class<T> type) {
if (type.isInterface()) {
if (hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
怎么挤痘痘boolean loadCompleted = fal;
try {
knownMappers.put(type, new MapperProxyFactory<T>(type));
// It's important that the type is added before the parr is run
// otherwi the binding may automatically be attempted by the
// mapper parr. If the type is already known, it won't try.
MapperAnnotationBuilder parr = new MapperAnnotationBuilder(config, type);
parr.par();
loadCompleted = true;
} finally {
if (!loadCompleted) {
}
}
}
}
hasMapper(type)⽅法调⽤的是什么呢?看下⾯代码
public <T> boolean hasMapper(Class<T> type) {
ainsKey(type);
}
意思就是看看knownMappers ⾥⾯有没有,即是缓存⾥⾯存在不存在。knownMappers 这个属性很重要 再之后的代码中会出现正到。如果没有的话就存到knownMappers 中
这个 newMapperProxyFactory()重中之重 ⼲了什么 呢? 没错动态代理, 掉个胃⼝,下次再说。
然后要看MapperAnnotationBuild这个⽅法了。
type传进去只为了再后⾯拼接⼀个.java 然后赋值给resource属性
我们主要看par.par();
下⾯代码 中主要的是loadXmlResource(), 和parStatement(method);

本文发布于:2023-06-20 23:39:59,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1001843.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:解析   配置   属性
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图