
在我们对数据库 DAO 类进行单元测试时,通常不应该依赖于一个外部数据库,所以会选用特定比较接近于真实数据库类型的内存或嵌入式数据库,如 HSQLDB(HyperSQL), H2, Derby 等。但总难免会用到特定数据库的特性,这时候就无法用前述各种数据库进行测试了。非要单元测试中覆盖到所用的数据库特性的话可以选择用 docker,如 Testcontainers, 经过模块扩展,它可以由 docker 来启动许多种类型的数据库,MySQL, Postgres, Oracle-XE, MS SQL Server, Couchbase 等等,详情见 Database containers。刚了解到的是它的模块化的无限可能,像支持 Kafka Containers 和 Localstack Module 等。
这里就不走 Testcontainers 那条路 -- 要求构建服务器上也要有 docker。早先希望能找到一种嵌入式或内存 PostgreSQL 数据库,后来发现 PostgreSQL 未能提供 In-Process 和 In-Memory 的启动方式,好在 PostgreSQL 是开源,有人可以把它改造为小型的可由测试代码启停的本地数据库。有两个具有代表性的组件,分别是 OpenTable Embedded PostgreSQL Component 和 Embedded PostgreSQL Server,它们都号称是 Embedded,所谓嵌入式,其实是进测试进程外的数据库。
下面简单体验下两个组件的用法 Read More
- 写 Java 代码至今,在应对可能冲突的共享资源操作时会尽量用 JDK 1.5 开始引入的并发锁(如 Lock 的各类实现类, ReentrantLock 等) 进行锁定,而不是原来的
synchronized关键字强硬低性能锁。
这里是应用 JDK 1.5 的Lock的基本操作步骤private Lock lock = new ReentrantLock(); private void operate() {
如此,
// 安全操作 ....
lock.lock();
try {
// 对共享资源的操作 ...
} finally {
lock.unlock();
}
}operate()就是一个线程安全的方法,任何对它的调用都安排到了一个队列里等着。但有时候上锁需要考虑更细的粒度,下面是一个演示案例,引出第一个问题
Read More 
Java 1.5(Tiger) 个人认为最为激动人心的两个特性是泛型与注解(Java Versions, Features and History)。泛型自然是不必说了,注解对 Java 世界的改变比泛型伟大的多(现在框架的注解配置),在 Java 1.5 之前我们只能在 Javadoc 注释中做文章,于是只能用 XDoclet 那样不伦不类的东西。Java 的注解发展到现在几乎可以使用在书写代码时的任何地方,见
java.lang.annotation.ElementType中的类型,囊括了 TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER(since 1.8), TYPE_USE(since 1.8)。Java 1.5 基本确定了注解的基本框架,包括元注解(meta-annotation); 直到 Java 8 又扩展了注解的使用范围,列举如下:
创建类实例
new@Interned MyObject();类型映射
myString = (@NonNull String) str;implements 语句中
class UnmodifiableList<T> implements@Readonly List<@Readonly T> { ... }throw exception声明
void monitorTemperature() throws@Critical TemperatureException { ... }解析前面 ElementType Java 8 增加的 TYPE_PARAMETER和 TYPE_USE 注解使用新场合。ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中。ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中(如: 声明语句、泛型和强制转换语句中的类型) Read More

本文紧承上一篇 Python 常用日期处理,因制于篇幅的大小需求才临时分立新篇,这里要简单提到 calendar 和 dateutil 模块的使用,其中 calendar 是 Python 内置的。相比于上一篇而言,此处主旨会更明确一些,只记录三个应用案例,分别是
- 用 dateutil 灵活的解析 datetime 字符串
- 给定起始日期后的连续日期
- 给定起始日期后连续的月末日期
dateutil 灵活的解析 datetime 字符串
使用 Python 内容的 date 或 datetime, 构造它们的实例时需要逐个的传入年月日或时分秒,或者要调用
fromisoformat()方法解析严格的字符串表示格式。而 dateutil.parser 的 parse() 方法就显得特别的聪明和随意,它可以智能的解析更丰富的字符串表示方式。详细的支持格式请参考官方文档的 parse examples,恐怕官方文档也未列举完全,只要觉得合理的时间字符串就可以尝试去解析。下方是一些例子 Read More
仅以此篇记录一下个人常用的 Python 处理日期的库与函数,主要涉及的类库有 Python 自带的 datetime, time 和 calendar,以及第三方的 dateutil。说到日期处理基本上要覆盖的概念有 date, time, datetime, timezone, calendar, 时间的比较与差值,解析与格式化显示等。
在 datetime 模块中类之间的继承关系如下:
object
├── date
│ └── datetime
├── time
├── timedelta
└── tzinfo
└── timezone我们着重体验一下前面粗体显示的 datetime, date, time, timedelta 对象, timezone 也不是不重要,有时候也可能只需要处理本地时间。 Read More

在 Spring 中应用 ServiceLocator 方式来获取 Spring Bean 的介绍参考了那么多,其实还是数官方的 ServiceLocatorFactoryBean JavaDoc 文档最言简意该了。Spring 的 ServiceLocator 仿佛用处不大,说到底就是类似于下方找寻某个 Spring Bean 一样:
ApplicationContext context = ...; Service service = context.getBean(ServiceImpl.class); Service service = context.getBean("myService");
只是有了 ServiceLocatorFactoryBean(它本质上就是一个 FactoryBean) 后我们不需要直接与 ApplicationContext 打交道,且多个的 Spring Bean 可以从相关的一个 FactoryBean 获得。下面用两个例子来演示(代码中刨去了 package 和 import 部分的代码)
一:实现类只有一个 Spring Bean 时
接口类 Parser(我们要定位就是它的实现类) Read More

许久没记录笔记了,这回来重新熟悉一下 Spring 中 FactoryBean 的使用,顾名思义,它是用来获得相应 Bean 的工厂的。它与另一个 Spring 中的接口 BeanFactory 的作用不一样的,不能多说了。FactoryBean 和 BeanFactory 都是在
org.springframework.beans.factory包中,谁能一看类名搞清楚它们的差别?- FactoryBean: 用于创建某个特定的 Spring bean 的工厂类
- BeanFactory: Spring 上下文的最顶层接口,如
ApplicationContext就继承了该接口,它可称之为所有 Spring bean 的工厂
这儿说的是第一个 FactoryBean, 它的接口声明是
1public interface FactoryBean<T> { 2 T getObject() throws Exception; 3 Class<?> getObjectType(); 4 boolean isSingleton(); 5}它最终的效果是,Spring 容器中注册一个名称为 abcFactoryBean 的
AbcFactoryBean实例,通后名称abcFactoryBean获得的实际上是相应AbcFactoryBean.getObject()返回的对象,类型为getObjectType(),isSingleton()是否是单例。 Read More
继续阅读 《Python Tricks: The Book》,书中说到 "Objects Can Behave Like Functions", 就是把对象当成函数来调用,在普通对象后加个括号就能调用相应的
__call__函数。下面是书中的例子class Adder:
def __init__(self, n):
self.n = n
def __call__(self, x):
return self.n + x然后是应用类
Adder的代码plus_3 = Adder(3)
plus_3(4) # 普通对象 plus_3 当成函数来用上面
plus_3是一个普能的对象,并非一个函数,但如果把它当成函数来看待,那么plus_3(4)就会去寻找相应的__call__函数。 Read More
本文为阅读 《Python Tricks: The Book》一书的 3.5 Function Argument Unpacking 的笔记与扩充理解。函数参数拆解是定义可变参数(VarArgs)*args和**kwargs的反向特性。*args和**kwars是函数可定义一个形参来接收传入的不定数量的实参。
而这里的函数参数拆解是形参定义多个,在调用时只传入一个集合类型对象(带上 * 或 ** 前缀),如list,tuple,dict, 甚至是generator, 然后函数能自动从集合对象中取得对应的值。
如果能理解下面赋值时的参数拆解和 Python 3.5 的新增***操作,那么于本文讲述的特性就好理解了。
唯一的不同时作为参数的集合传入函数时必须前面加上*或**, 以此宣告该参数将被拆解,而非一个整体作为一个函数参数。加上*或**与 Java 的@SafeVarargs有类似的功效,最接近的是 Scala 的 `foo(Array[String]("d", "e") : _*)` 写法。参见:Java 和 Scala 调用变参的方式 Read More
借鉴于其他多数语言中集合的 map/reduce 操作,也想总结一下在 Python 中如何对集合进行 map/reduce。而不是对于 Python 集合只会用简单的
for ... in遍历,处于之间的是 Python 的 Comprehension 操作,更倾向于译作推导; 在 Scala 中也有类似的for-comprehension语法。因此本文将涉及到三个方面的知识,基本的集合遍历操作,集合的推导,与 filter/map/reduce 操作。我无法写出诸如 掌握 Python 集体看这一篇就够了 的文章,但基本由本篇出发能了解到 Python 集合的基本遍历,转换操作。其余如切片,和更多能作用于 Python 集合的函数未有提及, 请查阅相关文档。
集合的基本遍历操作
这一块主要是复习功课, 希望由此熟练掌握常用的集合遍历操作方式 Read More