结合Mybatis源码说说sqlSession创建流程和从中用到的一些设计模式
程序员文章站
2022-09-04 12:12:28
根据下面这行代码,结合Mybatis源码说说sqlSession创建流程和从中用到的一些设计模式: 1 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 读取配置文件,生成Configuration对象,其中包含数据源、事 ......
-
1 usermapper usermapper = sqlsession.getmapper(usermapper.class);
-
读取配置文件,生成configuration对象,其中包含数据源、事务、mapper文件资源以及影响数据库行为属性settings;
-
sqlsessionfactorybuilder通过读取configuration对象,生成sqlsessionfactory(构建者模式);
1 public sqlsessionfactory build(reader reader, string environment, properties properties) { 2 sqlsessionfactory var5; 3 try { 4 xmlconfigbuilder parser = new xmlconfigbuilder(reader, environment, properties); 5 var5 = this.build(parser.parse()); 6 } catch (exception var14) { 7 throw exceptionfactory.wrapexception("error building sqlsession.", var14); 8 } finally { 9 errorcontext.instance().reset(); 10 11 try { 12 reader.close(); 13 } catch (ioexception var13) { 14 } 15 16 } 17 18 return var5; 19 }
1 private void bindmapperfornamespace() { 2 string namespace = this.builderassistant.getcurrentnamespace(); 3 if (namespace != null) { 4 class boundtype = null; 5 6 try { 7 boundtype = resources.classforname(namespace); 8 } catch (classnotfoundexception var4) { 9 } 10 11 if (boundtype != null && !this.configuration.hasmapper(boundtype)) { 12 this.configuration.addloadedresource("namespace:" + namespace); 13 this.configuration.addmapper(boundtype); 14 } 15 } 16 17 }
1 public sqlsessionfactory build(configuration config) { 2 return new defaultsqlsessionfactory(config); 3 }
-
在调用build()方法时,通过xmlconfigbuilder类bindmapperfornamespace()方法,将mapper接口注册到mapperregistry类的一个hashmap属性中,key=mapper.class,value=创建当前mapper的工厂;
-
通过sqlsessionfactory生成sqlsession实例对象(工厂模式);
-
sqlsession通过getmapper()方法拿到代理对象(代理模式),运用了jdk动态代理,生成了目标mapper对象的代理对象;
-
通过mapperproxyfactory工厂,生成动态代理的代理类是mapperproxy(工厂模式),实现了invocationhandler接口,对invoke()方法进行了包装,将非object类的方法进行了增强,包装成mappermethod,最后执行execute()方法完成sql增删改查的操作。
public object invoke(object proxy, method method, object[] args) throws throwable { try { //如果method方法是来自object的方法,那么直接执行,无需增强; //意思是假如我们执行的是tostring()方法,是不需要增强的。 if (object.class.equals(method.getdeclaringclass())) { return method.invoke(this, args); } if (this.isdefaultmethod(method)) { return this.invokedefaultmethod(proxy, method, args); } } catch (throwable var5) { throw exceptionutil.unwrapthrowable(var5); } //做了缓存 mappermethod mappermethod = this.cachedmappermethod(method); //执行增删改查操作 return mappermethod.execute(this.sqlsession, args); }
-