源码分析

Mybatis3.3.x技术内幕(三):Mybatis事务管理(将颠覆你心中目前对事务的理解)

那年仲夏 提交于 2020-03-20 20:53:40
3 月,跳不动了?>>> 1.说到数据库事务,人们脑海里自然不自然的就会浮现出事务的四大特性、四大隔离级别、七大传播特性。四大还好说,问题是七大传播特性是哪儿来的?是Spring在当前线程内,处理多个数据库操作方法事务时所做的一种事务应用策略。事务本身并不存在什么传播特性,不要混淆事务本身和Spring的事务应用策略。(当然,找工作面试时,还是可以巧妙的描述传播特性的) 2.一说到事务,人们可能又会想起create、begin、commit、rollback、close、suspend。可实际上,只有commit、rollback是实际存在的,剩下的create、begin、close、suspend都是虚幻的,是业务层或数据库底层应用语意,而非JDBC事务的真实命令。 create(事务创建):不存在。 begin(事务开始):姑且认为存在于DB的命令行中,比如Mysql的start transaction命令,以及其他数据库中的begin transaction命令。JDBC中不存在。 close(事务关闭):不存在。应用程序接口中的close()方法,是为了把connection放回数据库连接池中,供下一次使用,与事务毫无关系。 suspend(事务挂起):不存在。Spring中事务挂起的含义是,需要新事务时,将现有的connection1保存起来(它还有尚未提交的事务)

基础知识-HashMap知识点

天大地大妈咪最大 提交于 2020-03-16 18:01:16
某厂面试归来,发现自己落伍了!>>> key值为null时的存取 我们知道HashMap允许插入元素的key值为null,我们看下这部分的源代码: private V putForNullKey(V value) { for (Entry<K,V> e = table[0]; e != null; e = e.next) { if (e.key == null) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(0, null, value, 0); return null; } 可以看出,key=null时,对应的数据是保存在内部数组第一个位置的链表中。知道了它是如何保存的,那么获取也就简单了:编译内部数组第一个位置的列表,找到key=null的数据项,返回该数据项中的value即可。 private V getForNullKey() { for (Entry<K,V> e = table[0]; e != null; e = e.next) { if (e.key == null) return e.value; } return null; } hashCode和equals方法 在上一篇博文:《 基础知识

Mybatis3.3.x技术内幕(十一):执行一个Sql命令的完整流程

混江龙づ霸主 提交于 2020-03-04 17:36:54
Mybatis中的Sql命令,在枚举类SqlCommandType中定义的。 public enum SqlCommandType { UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH; } 下面,我们以Mapper接口中的一个方法作为例子,看看Sql命令的执行完整流程。 public interface StudentMapper { List<Student> findAllStudents(Map<String, Object> map, RowBounds rowBounds, ResultSetHandler rh); } 参数RowBounds和ResultSetHandler是可选参数,表示分页对象和自定义结果集处理器,一般不需要。 一个完整的Sql命令,其执行的完整流程图如下: (Made In Edrawmax) 对于上面的流程图,如果看过前面的博文的话,大部分对象我们都比较熟悉了。一个图,就完整展示了其执行流程。 MapperProxy的功能: 1. 因为Mapper接口不能直接实例化, MapperProxy的作用,就是使用JDK动态代理功能,间接实例化Mapper的proxy对象。可参看系列博文的第二篇。 2. 缓存 MapperMethod对象。 private final Map<Method,

java容器源码分析(四)——HashMap

情到浓时终转凉″ 提交于 2020-01-09 23:56:20
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 本文内容: Hash HashMap概述 HashMap源码分析 Hash表 数据结构中都学过Hash,我们要说的HashMap采用拉链法(数组+链表)实现。数组具有根据下标快速查找的特点,链表动态增加删除元素。 (来源:http://www.cnblogs.com/hzmark/archive/2012/12/24/HashMap.html) 看上图,对于HashMap的内部结构应该是一目了然了。 HashMap概述 HashMap是一个Key-Value容器,应该是使用得最多的map了吧。看继承关系图 HashMap继承了AbstractMap、Map,实现了Cloneable和Serializable HashMap源码分析 看一下HashMap的一些属性 /** * The default initial capacity - MUST be a power of two. */ static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 /** * The maximum capacity, used if a higher value is implicitly specified * by either of the

对象池common-pool2策略分析

人走茶凉 提交于 2019-12-17 20:28:28
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 上一篇: 对象池common-pool2分析 common-pool2策略 上一篇对象池common-pool2分析从三个主要的接口进行分析,这一篇将对源码进行详细的分析,力图找出对象池的管理策略.从之前的分析可以看出ObjectPool定义了对象池需要实现的功能,所以重点分析ObjectPool. GenericObjectPool:一般对象池 Generic KeyedObjectPool:可以根据key分组的对象池 SoftReferenceObjectPool:软引用对象池. GenericObjectPool public GenericObjectPool(PooledObjectFactory<T> factory, GenericObjectPoolConfig config) { super(config, ONAME_BASE, config.getJmxNamePrefix()); if (factory == null) { jmxUnregister(); // tidy up throw new IllegalArgumentException("factory may not be null"); } this.factory = factory; /

从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式(二)

[亡魂溺海] 提交于 2019-12-11 17:28:42
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 下面再来看看Tomcat是如何使用NIO来构架Connector这块的。 先看看Tomcat Connector这块的类图: 其中: NioEndpoint负责组装各部件 Acceptor负责监听新连接,并把连接交给Poller Poller负责监听所管辖的channel队列,并把请求交给SocketProcessor处理 SocketProcessor负责数据处理,并把请求传递给后端业务处理模块 在整个服务端处理请求的过程可以分为三个阶段,时序图如下所示: 阶段一:监听并建立连接 这一阶段主要是Acceptor监听新连接,并轮询取一个Poller ,把连接交付给Poller 阶段二: 监听客户端的请求 这一过程主要是让每个Poller监听所管辖的channel队列,select到新请求后交付给SocketProcessor处理 阶段三:处理请求 这一过程就是从多线程执行SocketProcessor,做数据和业务处理 于是乎我们发现抛开具体代码细节,Tomcat和Jetty在NIO的使用方面是非常一致的,采用的模式依然是下图: 来源: oschina 链接: https://my.oschina.net/u/59889/blog/49696

从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式(一)

风格不统一 提交于 2019-12-11 17:27:58
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 如何正确使用NIO来构架网络服务器一直是最近思考的一个问题,于是乎分析了一下Jetty、Tomcat和Mina有关NIO的源码,发现大伙都基于类似的方式,我感觉这应该算是NIO构架网络服务器的经典模式,并基于这种模式写了个小小网络服务器,压力测试了一下,效果还不错。废话不多说,先看看三者是如何使用NIO的。 Jetty Connector的实现 先看看有关类图: 其中: SelectChannelConnector负责组装各组件 SelectSet负责侦听客户端请求 SelectChannelEndPoint负责IO的读和写 HttpConnection负责逻辑处理 在整个服务端处理请求的过程可以分为三个阶段,时序图如下所示: 阶段一:监听并建立连接 这一过程主要是启动一个线程负责accept新连接,监听到后分配给相应的SelectSet,分配的策略就是轮询。 阶段二:监听客户端的请求 这一过程主要是启动多个线程(线程数一般为服务器CPU的个数),让SelectSet监听所管辖的channel队列,每个SelectSet维护一个Selector,这个Selector监听队列里所有的channel,一旦有读事件,从线程池里拿线程去做处理请求 阶段三:处理请求 这一过程就是每次客户端请求的数据处理过程

从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式(三)

纵然是瞬间 提交于 2019-12-11 17:27:47
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 最后我们再看看NIO方面最著名的框架Mina,抛开Mina有关session和处理链条等方面的设计,单单挑出前端网络层处理来看,也采用的是与Jetty和Tomcat类似的模式,只不过它做了些简化,它没有隔开请求侦听和请求处理两个阶段,因此,宏观上看它只分为两个阶段。 先看看它的类图: 其中: SocketAcceptor起线程调用SocketAcceptor.Work负责新连接侦听,并交给SocketIoProcessor处理 SocketIoProcessor起线程调用SocketIoProcessor.Work负责侦听所管辖的channel队列, select到新请求后交给IoFilterChain处理 IoFilterChain组装了mina的处理链条 在整个服务端处理请求的过程可以分为两个阶段,时序图如下所示: 阶段一:监听并建立连接 阶段二: 监听并处理客户端的请求 总结来看Jetty、tomcat和Mina,我们也大概清楚了该如何基于NIO来构架网络服务器,通过这个提炼出来的模式,我写了个很简单的NIO Server,在保持连接的情况下,可以很轻松的保持6万连接(由于有65535连接限制),并能在负载只有3左右的情况下(4核),承担3到4万的TPS请求(当然做的事情很简单

java容器源码分析(六)——HashSet

情到浓时终转凉″ 提交于 2019-12-10 15:43:55
本文内容 HashSet概述 HashSet源码分析 HashSet概述 HashSet是Set的一种实现,其底层是用HashMap实现的,整个HashSet看起来就像一个包装类! HashSet的继承图如下: HashSet继承了Set、Abstract类,实现了Cloneable 、Serializable 接口。 HashSet实现 看一下HashSet的属性 private transient HashMap<E,Object> map; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); 底层直接用了HashMap.PRESENT就是用来填充map的value。为何不用null呢?? 默认构造函数: public HashSet() { map = new HashMap<>(); } public HashSet(Collection<? extends E> c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); } public HashSet(int initialCapacity,

Rust语言实现的Slab内存管理器源码分析

泄露秘密 提交于 2019-12-10 05:49:25
Linux 所使用的 slab 分配器的基础是 Jeff Bonwick 为 SunOS 操作系统首次引入的一种算法。Jeff 的分配器是围绕对象缓存进行的。在内核中,会为有限的对象集(例如文件描述符和其他常见结构)分配大量内存。Jeff 发现对内核中普通对象进行初始化所需的时间超过了对其进行分配和释放所需的时间。因此他的结论是不应该将内存释放回一个全局的内存池,而是将内存保持为针对特定目而初始化的状态。 我们来看看rust中如何实现这一算法,也借此学习rust的应用技术。 源码: carllerche/slab :Preallocate memory for values of a given type. Slot结构(抽屉) 先来看一个基础数据结构Slot,这个数据结构对后面理解Slab至关重要。 enum Slot<T> { Empty(usize), Filled(T), Invalid, } 可以把Slot想象为一个抽屉,有三种状态: Empty 空抽屉,什么都没有装。Empty(usize) 一个带有编号的空抽屉。 Filled 装满的抽屉,Filled(T) 一个装了一个T类型对象的抽屉。 Invalid 无效的抽屉,这个抽屉当前处于无效状态。 一个Slot可以为空,可以无效,可以装一个T类型对象且只能装一个。 Slab结构(大柜子) 接着来看Slab数据结构