当前位置: 首页 > news >正文

免费网站下载大全百度开放云做网站

免费网站下载大全,百度开放云做网站,网站开发宣传图片,wordpress分类没有文章十一月月底#xff0c;宿舍楼失火啦#xff0c;搞得20多天没有网#xff0c;目测直到放假也不会来了。。。 正题 嗯~#xff0c;其实阅读源码不是为了应付面试#xff0c;更重要的让你知道#xff0c;大师是怎样去写代码的#xff0c;同样是用Java#xff0c;为啥Clint…十一月月底宿舍楼失火啦搞得20多天没有网目测直到放假也不会来了。。。   正题 嗯~其实阅读源码不是为了应付面试更重要的让你知道大师是怎样去写代码的同样是用Java为啥Clinton Begin写的叫源码而你写只能叫代码。 最简单的入门代码 先读取配置文件流然后构造个SqlSessionFactory然后开启一个SqlSession指定statement调用查询方法返回结果。那么你知道他是怎样实现的吗  SqlSessionFactoryBuilder.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.}}} 将输入流传入 XMLConfigBuilder 的构造方法来创建一个 XMLConfigBuilder 对象 调用 XMLConfigBuilder 的parse 方法进行解析配置文件返回一个 Configuration 对象 public SqlSessionFactory build(Configuration config) {return new DefaultSqlSessionFactory(config);}   将返回的 Configuration 对象传入另外一个重载的 build 方法实际上是传入了 DefaultSqlSessionFactory 的构造方法返回 sqlSessionFactory。 我比较关心的是 XMLConfigBuilder 的 parse 方法都干了什么事情 首先进入 XMLConfigBuilder 的构造方法后 真正使用配置文件输入流的是 XPathParser 它是负责解析 XML文件元素节点的 通俗地讲 XpathParser 负责将原料加工成零件 XMLConfigBuilder 负责按照工序组装零件成一个产品。 public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);}private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {super(new Configuration());ErrorContext.instance().resource(SQL Mapper Configuration);this.configuration.setVariables(props);this.parsed false;this.environment environment;this.parser parser;}   经过构造方法初始化好XPathParser后就要进入parse方法了。Parse 方法里有个判断如果已经解析过了就会抛出异常如果没解析就将解析标志设为 true。接着调用parseConfiguration  public Configuration parse() {if (parsed) {throw new BuilderException(Each XMLConfigBuilder can only be used once.);}parsed true;parseConfiguration(parser.evalNode(/configuration));return configuration;}private void parseConfiguration(XNode root) {try {Properties settings settingsAsPropertiess(root.evalNode(settings));//issue #117 read properties firstpropertiesElement(root.evalNode(properties));loadCustomVfs(settings);typeAliasesElement(root.evalNode(typeAliases));pluginElement(root.evalNode(plugins));objectFactoryElement(root.evalNode(objectFactory));objectWrapperFactoryElement(root.evalNode(objectWrapperFactory));reflectionFactoryElement(root.evalNode(reflectionFactory));settingsElement(settings);// read it after objectFactory and objectWrapperFactory issue #631environmentsElement(root.evalNode(environments));databaseIdProviderElement(root.evalNode(databaseIdProvider));typeHandlerElement(root.evalNode(typeHandlers));mapperElement(root.evalNode(mappers));} catch (Exception e) {throw new BuilderException(Error parsing SQL Mapper Configuration. Cause: e, e);}}   parseConfiguration 就是工序图 组装产品一定是按照一定顺序的 所以这也是建造者模式的核心。比如第一个是全局设置 settings第二个是属性文件第三个是别名。在这里我们看 environmentsElement很明显它是来构建 Environment 的 也就是我们配置的数据源信息。 private void environmentsElement(XNode context) throws Exception {if (context ! null) {if (environment null) {environment context.getStringAttribute(default);}for (XNode child : context.getChildren()) {String id child.getStringAttribute(id);if (isSpecifiedEnvironment(id)) {TransactionFactory txFactory transactionManagerElement(child.evalNode(transactionManager)); // 构建事务工厂DataSourceFactory dsFactory dataSourceElement(child.evalNode(dataSource)); // 构建数据源工厂DataSource dataSource dsFactory.getDataSource();Environment.Builder environmentBuilder new Environment.Builder(id).transactionFactory(txFactory).dataSource(dataSource);configuration.setEnvironment(environmentBuilder.build());}}}} 主要有两大块 transactionManagerElement 和 dataSourceElement。 private TransactionFactory transactionManagerElement(XNode context) throws Exception {if (context ! null) {String type context.getStringAttribute(type);Properties props context.getChildrenAsProperties();TransactionFactory factory (TransactionFactory) resolveClass(type).newInstance();factory.setProperties(props);return factory;}throw new BuilderException(Environment declaration requires a TransactionFactory.);}private DataSourceFactory dataSourceElement(XNode context) throws Exception {if (context ! null) {String type context.getStringAttribute(type);Properties props context.getChildrenAsProperties();DataSourceFactory factory (DataSourceFactory) resolveClass(type).newInstance();factory.setProperties(props);return factory;}throw new BuilderException(Environment declaration requires a DataSourceFactory.);} 注意看 resolveClass(type).newInstance() 这不就是反射吗 而那个 type 则是我们配置文件里面配置的比如 jdbc 或是 manage 对应 JdbcTransactionFactory 和 ManagedTransactionFactory。 Upooled 和 Pooled对应 UnpooledDataSourceFactory 和 PooledDataSourceFactory。 返回 environmentsElement 方法 我们还看到 Environment 有个 Builder 类 准确来说是静态内部类。 Environment.Builder environmentBuilder new Environment.Builder(id).transactionFactory(txFactory).dataSource(dataSource);configuration.setEnvironment(environmentBuilder.build());   具体的Environment类 public final class Environment {private final String id;private final TransactionFactory transactionFactory;private final DataSource dataSource;public Environment(String id, TransactionFactory transactionFactory, DataSource dataSource) {if (id null) {throw new IllegalArgumentException(Parameter id must not be null);}if (transactionFactory null) {throw new IllegalArgumentException(Parameter transactionFactory must not be null);}this.id id;if (dataSource null) {throw new IllegalArgumentException(Parameter dataSource must not be null);}this.transactionFactory transactionFactory;this.dataSource dataSource;}public static class Builder {private String id;private TransactionFactory transactionFactory;private DataSource dataSource;public Builder(String id) {this.id id;}public Builder transactionFactory(TransactionFactory transactionFactory) {this.transactionFactory transactionFactory;return this;}public Builder dataSource(DataSource dataSource) {this.dataSource dataSource;return this;}public String id() {return this.id;}public Environment build() {return new Environment(this.id, this.transactionFactory, this.dataSource);}}public String getId() {return this.id;}public TransactionFactory getTransactionFactory() {return this.transactionFactory;}public DataSource getDataSource() {return this.dataSource;}}   那么这里有一个设计模式的问题。为什么Environment里面要搞一个Builder类呢直接使用构造方法不也可以达到相同的目的吗 1. 首先 用内部类是因为内部类与外部类有一定的关系 往往只有该外部类调用此内部类。 静态内部类只能访问静态的成员变量和方法不能访问非静态变量的方法。但是普通内部类可以访问任意外部类的成员变量和方法。静态内部类可以声明普通成员变量和方法但是普通内部类不能声明 static 变量或方法。静态内部类 Inner I new Outer.Inner();普通内部类 Outer o new Outer(); Inner I o.new Inner();2. 另外 静态都是用来修饰类的内部成员的 比如静态方法 静态成员变量。 静态方法不能访问非静态变量和非静态方法。 Static 不能修饰局部变量。3. 总结如果类的构造函数有多个参数设计这样的类时 最好使用 Builder 模式 特别是大多数参数都是可选的时候。如果现在不能确定参数的个数最好一开始就使用建造者模式。   到此SqlSessionFactoryBuilder.build方法的作用是解析配置文件构建唯一的Configuration对象构建全局唯一并且线程安全的SqlSessionFactory。   SqlSessionFactory的openSession方法  进入openSession方法 Overridepublic SqlSession openSession() {return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);}   会发现它调用的是另外一个方法。 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {Transaction tx null;try {final Environment environment configuration.getEnvironment();final TransactionFactory transactionFactory getTransactionFactoryFromEnvironment(environment);tx transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);final Executor executor configuration.newExecutor(tx, execType);return new DefaultSqlSession(configuration, executor, autoCommit);} catch (Exception e) {closeTransaction(tx); // may have fetched a connection so lets call close()throw ExceptionFactory.wrapException(Error opening session. Cause: e, e);} finally {ErrorContext.instance().reset();}}   看try块第一行获得的Environment是前面由XMLConfigBuilder装配到Configuration里面的。第二三行的事务工厂和数据源都是在解析配置文件期间装配到Environment里面的。 到第四行这是个新东西Executor简单来说它是真正执行CRUD操作的工具给我们提供的SqlSession仅仅是个用户接口。Executor也是由Configuration对象来创建的可见Configuration是多么重要。 我们知道事务操作必不可少所以Executor的创建必须有Transaction对象。 第五行就是创建SqlSession了DefaultSqlSession是一个具体实现类。我们可以看到它把Executor传进去了那么就不难发现SqlSession不过是件衣裳。 接下来看SqlSession调用过程   调用 SqlSession 的 selectList 方法 先看selectOne方法 Overridepublic T T selectOne(String statement, Object parameter) {// Popular vote was to return null on 0 results and throw exception on too many.ListT list this.TselectList(statement, parameter);if (list.size() 1) {return list.get(0);} else if (list.size() 1) {throw new TooManyResultsException(Expected one result (or null) to be returned by selectOne(), but found: list.size());} else {return null;}}   看到这句话没 this.TselectList(statement, parameter); 我们调用返回一条数据的方法实际上也是调用selectList现在看selectList多个重载方法我就不全部贴了 Overridepublic E ListE selectList(String statement, Object parameter, RowBounds rowBounds) {try {MappedStatement ms configuration.getMappedStatement(statement);return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);} catch (Exception e) {throw ExceptionFactory.wrapException(Error querying database. Cause: e, e);} finally {ErrorContext.instance().reset();}}   MappedStatement你可以理解为你配置文件里面写的sql语句的映射比如 同样这个对象也来自Configuration。接着看return的是Executor的query方法ms作为参数。Executor有多个实现类BaseExecutor是最基础的实现来看其中的query实现 Overridepublic E ListE query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {BoundSql boundSql ms.getBoundSql(parameter);CacheKey key createCacheKey(ms, parameter, rowBounds, boundSql);return query(ms, parameter, rowBounds, resultHandler, key, boundSql);}   第一行从ms里面获得绑定的sql语句脑袋是不是跟配置产生一点联系了第二行不需要管看第三行的实现 SuppressWarnings(unchecked)Overridepublic E ListE query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {ErrorContext.instance().resource(ms.getResource()).activity(executing a query).object(ms.getId());if (closed) {throw new ExecutorException(Executor was closed.);}if (queryStack 0 ms.isFlushCacheRequired()) {clearLocalCache();}ListE list;try {queryStack;list resultHandler null ? (ListE) localCache.getObject(key) : null;if (list ! null) {handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);} else {list queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);}} finally {queryStack--;}if (queryStack 0) {for (DeferredLoad deferredLoad : deferredLoads) {deferredLoad.load();}// issue #601deferredLoads.clear();if (configuration.getLocalCacheScope() LocalCacheScope.STATEMENT) {// issue #482clearLocalCache();}}return list;}   当查询的时候先从缓存中找如果找不到就从数据库中找这里我们看 list queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); private E ListE queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {ListE list;localCache.putObject(key, EXECUTION_PLACEHOLDER);try {list doQuery(ms, parameter, rowBounds, resultHandler, boundSql);} finally {localCache.removeObject(key);}localCache.putObject(key, list);if (ms.getStatementType() StatementType.CALLABLE) {localOutputParameterCache.putObject(key, parameter);}return list;}    这句是关键 list doQuery(ms, parameter, rowBounds, resultHandler, boundSql); 在BaseExecutor里面有定义 protected abstract E ListE doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)throws SQLException;   它是需要子类去实现。总共有三种BatchExecutorReuseExecutorSimpleExecutor。这里我们选择SimpleExecutor Overridepublic E ListE doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {Statement stmt null;try {Configuration configuration ms.getConfiguration();StatementHandler handler configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);stmt prepareStatement(handler, ms.getStatementLog());return handler.Equery(stmt, resultHandler);} finally {closeStatement(stmt);}}    这里说一句题外话到处都需要Configuration它无疑是mybatis运行期间的核心。 StatementHandler是对java.sql.Statement的封装处理有三个实现类CallableStatementHandlerPreparedStatementHandlerSimpleStatementHandler。 同样利用Configuration来创建一个StatementHandler实例之后利用这个handler来创建一个java.sql.statement最后调用handler的Equery方法利用原生的Statement来执行查询操作。 PreparedStatementHandler.query方法 Overridepublic E ListE query(Statement statement, ResultHandler resultHandler) throws SQLException {PreparedStatement ps (PreparedStatement) statement;ps.execute();return resultSetHandler.E handleResultSets(ps);}    前两行都应该知道类型转换以及执行jdbc的查询。最后一行是利用原生的PreparedStatement来进行结果集的封装。ResultSetHandler有个默认实现类DefaultResultSetHandler具体就不在分析了。 到此为止返回结果集到最上层显示给用户。   先写这些吧写的不是特别满意望指教~  转载于:https://www.cnblogs.com/LUA123/p/8094573.html
http://www.pierceye.com/news/865568/

相关文章:

  • wordpress采集自动伪原创福州360手机端seo
  • 工信部网站备案要求重庆网站公司设计
  • 宛城区建网站淘宝网页设计报告
  • 网站后台需求字节跳动员工人数2019
  • saas建站 cms科技感背景素材
  • 武进区城乡建设局网站在线员工后台网站建设
  • 关于网站开发人员的薪资易语言怎么做无限打开网站
  • 网站备案名称几个字企业网站定制案例
  • 新浪云服务器做网站重庆建设厅官方网站
  • 苏州市住房和城乡建设局官方网站郑州专业旅游网站建设
  • 网站免费正能量直接进入浏览器下载安装公开课网站建设
  • 个人做电影网站合法吗网页制作与网站建设完全学习手册下载
  • 椒江做网站wordpress的分类
  • 新手做网站应该注意什么重庆市建设工程造价信息网公众号
  • 网址输入奉化seo页面优化外包
  • 坪山商城网站建设哪家效益快教务管理系统是应用软件吗
  • 深圳网站搭建找谁怎么在手机上制作app
  • 做app和做网站的区别桂林市天气预报15天
  • 高端织梦html5网站模板 dedecms网络公司模板关键词排名优化方法
  • 上海网站建设咨找个网站2021能看到
  • 可以用服务器做网站查询公司信息
  • 个人可以备案企业网站吗旅行社网站 模板
  • 三丰云做网站步骤网站怎么上传ftp
  • 做二手车有哪些网站有哪些手续网站建设单位有哪些方面
  • 建设网站的和服务器常州免费网站制作
  • 电子外贸网站重庆有什么好玩的
  • 商务网站的建设阶段包括郑州的做网站公司哪家好
  • 深圳网站建设网络公司七星彩网投网站建设
  • 手机建网站公司wordpress增加关键字
  • 招聘网站有哪些平台电商网站建设方式