0%

代码来自于Spring Boot 2.0.4.RELEASE

SpringApplication类负责由main方法启动spring应用,文档中给出了启动的主要步骤:

  • 创建ApplicationContext
  • 处理命令行参数
  • refresh ApplicationContext,加载bean
  • 触发各类Runner
阅读全文 »

ConcurrentHashMap 的实现比较复杂,里面涉及到的内容很多,而且有很多的性能优化的策略,想全部搞清楚比较困难,所以主要对里面感兴趣的并发的处理方面,相关的几个函数的实现看下,难免有理解不到位的地方,以后随时修改补充吧。

这里看的是 java 7 中的实现。

另外,推荐一篇文章,写的很详细: The Concurrency Of ConcurrentHashMap

阅读全文 »

看了下 java 8 中 HashMap 的源码,结合网上一些文章,大概明白了 HashMap 中几个一直很疑惑的地方。这里就记录一下 HashMap 的学习。

数据结构和一些参数的作用

HashMap 的数据结构“平平无奇”,就是我们熟悉的“数组+链表”的方式(链地址法),并且在链表长度超过某个值(默认为 8)后,将链表转换为红黑树以提高效率。

HashMap 存储数据的数组是:

1
transient Node<K,V>[] table;

也即一个 Node 数组,Node 实现 Entry 接口,每个 Node 存储一个键值对,如下:

1
2
3
4
final int hash;
final K key;
V value;
Node<K,V> next;

其中,hash 是存储的 node 中的 key 的哈希值,key、value 即键和值,而 next 则显然是构建链表的,指向链表的下一个节点。

阅读全文 »

在 Spring Boot 中观察了一下有新的请求时,Servlet filter 的执行情况,做下记录。

Spring Boot 默认 Servlet filter

Spring Boot 会按照 ApplicationFilterChain 中的数组 filters 里保存的 filter 按顺序执行,对于 OrderedFilter 可以指定 order 值(一个 int 值),值小的先执行,不指定 order 时按照首字母顺序执行。

默认情况下,有 CharacterEncodingFilter、HiddenHttpMethodFilter、FormContentFilter 和 RequestContextFilter,以及 webSocket 的 WsFilter。CharacterEncodingFilter、HiddenHttpMethodFilter、FormContentFilter 和 RequestContextFilter 都是使用了 Ordered***Filter 实例,order 值分别是 -2147483648、-10000、-9900 和 -105。

RequestContextFilter 主要用于使用第三方 Servlet 时的情况。关于 CharacterEncodingFilter、HiddenHttpMethodFilter 和 FormContentFilter,其作用可见如下。

阅读全文 »

一直想了解一下 Spring AOP 的实现,所以看了下 java 动态代理(jdk 8)。

java Proxy 实现动态代理

Proxy 原理是在运行期创建指定的被代理接口的一个实现类,这个类是 Proxy 的子类,并使用反射机制,对接口中声明的方法,用 InvocationHandler 转发函数调用。

Proxy 只能代理接口的实现,会被转发到从其原理不难看出,这是因为生成的代理类已经继承了 Proxy,因为 java 单继承的机制,所以只能实现接口作为其代理。

阅读全文 »

项目打包时,直接用spring-boot maven plugin之类插件组装出一个包含了所有依赖的jar,即fat-jar的形式,可以直接启动,部署方便。但是并不是任何时候fat-jar都是最优解。

依赖文件分离打包在几种场景下的优化

稳定版本依赖包的分离对部署的优化

在项目开发中,依赖包我们期望是稳定的:版本的升级一定是审慎进行的,新依赖的加入也需要考量。也因此,在项目部署时,如果只打包源代码到一个thin-jar、将固定不变依赖包分离,打包得到的部署文件体积将大大减小——使用spring boot开发的项目打包成fat-jar百兆起步,但其实源代码打包的thin-jar体积很可能是KB级的。

尤其是在使用docker镜像部署jar时,对于镜像打包有优化:虽然对镜像体积减小不会有优化,但是可以将依赖文件置入单独的镜像层复用,镜像构建时多数情况下(依赖未变更的情况下)只需要重新构建源代码及它之上的层,构建速度将会得到提升。

阅读全文 »

CMD,有多个的话之后最后一个生效,作为启动时的默认命令行和用于向 ENTRYPOINT 传递参数,会被 docker run 带的命令行和参数覆盖。

ENTRYPOINT,有多个时最后一个生效,启动时执行,不会被 docker run 带的命令行和参数覆盖。

exec form 和 shell form

两者都有 exec 和 shell 两种格式的写法,如下:

1
2
3
4
# exec form
ENTRYPOINT ["executable", "param1", "param2"]
#shell form
ENTRYPOINT command param1 param2
阅读全文 »

要在服务器进行一些重复性的体力活,干脆简单看了下shell,下面记录一些内容,都是最基本的用法。

``、’’和””(反引号、单引号和双引号)

以输出为例,``内的内容作为一个命令,先执行其中命令,再执行原命令,即代表命令替换;’’内的原原本本的输出;””内的内容,进行参数替换(如$name)和命令替换(如`echo abc`)。

比如下面代码

1
2
echo "`echo hello world`"
echo '`echo hello world`'

输出将是

1
2
hello world
`echo hello world`
阅读全文 »

对于正则表达式一向了解不多,假期期间随着《正则表达式必知必会》快速学习了一下正则表达式的基本使用,在此记录一下。

正则表达式语法笔记

常用元字符

元字符 作用
. 换行符外任意字符
\d 一个数字,等价于 [0-9]
\D 一个非数字,等价于 [^0-9]
\w 一个数字、字符及下划线,等价于[a-zA-Z0-9_](最后一个是下划线_)
\W 一个非数字、字符和下划线,等价于[^a-zA-Z0-9_](最后一个是下划线_),注意,[]内的 ^,对之后每个组合都取非,不只是紧接的
\s 一个空白字符,等价于[\f\n\r\t\v ](最后有个空格),换页、换行、回车、制表、垂直制表符、空格
\S 一个非空白字符,等价于[^\f\n\r\t\v ](最后有个空格)

要注意,[]内出现的的元字符对应字符,不按照元字符处理,不需要要转义,如“.”、“$”等

阅读全文 »