小站重新装修,欢迎到访。
分类 #技术

clojure工程构建之lein篇

最近为了看storm的源码,开始了clojure的系统学习。clojure因为背负了Java这个历史大包袱,在语法上相对于其他Lisp方言,还是稍显复杂和罗嗦。JVM语言似乎都很难摆脱JAVA的身影,互操作是件很难做得优雅的事情。不过FP的魅力还是让我坚持下来,准备长期作战,不断学习和积累。本文不进一步讨论clojure,只简单介绍下使用lein进行clojure工程的构建,因为我个人对gradle很感兴趣(出于对groovy的好感)后续可能会再写一篇使用gradle的构建。

storm的源码就采用了lein构建,可以看下工程根目录下有project.clj文件。就目前看到的clojure开源项目,用lein的还是居多的。

##lein的安装##
查看lein的github主页:https://github.com/technomancy/leiningen,对于lein在*nix上的安装,比较简单的步骤是下载此脚本,放到PATH里,并执行chmod 755 /path/to/lein即可。首次执行该脚本会下载相关的文件并默认安装到~/.lein

##创建新工程##
这里我们创建一个简单的示例工程:

$ lein new app leinexample

控制台输出:

Generating a project called leinexample based on the 'app' template.

也就是说,app是工程的模板名,lein默认的模板是default。模板是插件化的,所以可以很容易扩展,这里就有很多模板。下图是我们用find .列出的lein的默认目录结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
billmac:leinexample jingege$ find .
.
./.gitignore
./doc
./doc/intro.md
./project.clj
./README.md
./src
./src/leinexample
./src/leinexample/core.clj
./test
./test/leinexample
./test/leinexample/core_test.clj

重点是project.clj

1
2
3
4
5
6
7
(defproject leinexample "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.5.1"]]
:main leinexample.core)

默认只列出了lein project的一部分属性,包括工程名以及相关元信息、license、依赖等等。这里有最全面的工程定义样例可以参考。

##导入到IDE##

起初像学习erlang一样,我使用emacs进行clj的练习,但尽管我个人对emacs很有好感,不过对于阅读代码这种事情,还是使用IDE的好。

如果需要使用eclipse或IntellijIdea等支持maven的IDE,可以使用lein pom来生成pom文件,然后直接使用IDE导入maven工程。个人感觉IntellijIdea真的是非常强悍的IDE,当然不仅仅是说对clojure的支持。

##管理依赖##

在project.clj中可以添加依赖包,比如,我们在project.clj的dependencies中添加一条:

:dependencies [[org.clojure/clojure "1.5.1"] [clj-http "0.6.5" :exclusions [crouton]]]

执行lein deps,控制台输出:

1
2
3
4
5
6
Retrieving clj-http/clj-http/0.6.5/clj-http-0.6.5.pom from clojars
Retrieving org/apache/httpcomponents/httpcore/4.2.3/httpcore-4.2.3.pom from central
……
Retrieving clj-http/clj-http/0.6.5/clj-http-0.6.5.jar from clojars
RetrievingRetrieving slingshot/slingshot/0.10.3/slingshot-0.10.3.jar cheshire/cheshire/5.0.2/cheshire-5.0.2.jarfrom from clojars
clojars

你可能发现,下载的依赖包,并不在工程目录里,其实lein是整合了maven,上述包其实已经下载到maven的本地仓库了。

##运行测试用例##

lein会默认生成一个clj和对应的测试用例文件,打开leinexample/test/leinexample/core_test.clj,修改a-test函数的返回值为true,即修改最后一行为(is (= 0 0))即可。然后执行:

lein test

控制台会打印出测试用例的运行结果:

1
2
3
4
lein test leinexample.core-test
Ran 1 tests containing 1 assertions.
0 failures, 0 errors.

##编译代码##

此时如果直接运行lein compile,你会发现,target目录里没有.class文件。这个起初也让我很不解。查阅了相关文档发现需要开启aotcompile Ahead Of Time,在project.clj的defproject函数添加metadata:

:aot [leinexample.core]

之后再执行lein compile,即可在target/classes里看到对应的.class文件了。

注意,上述大多数目录,如target、classes等,都可以在project.clj中修改。

##打包##

lein支持jar、uberjar等等打包方式,具体可以使用lein -h可以查看lein的其他子命令。应该也可以直接打出war包,这个我没有尝试过,有兴趣的充分发挥google的力量吧。

简析Java Reference

Coding了多年Java,自然早就听说过四种引用类型,不过偶尔也才浅浅的用一下,今天突然想看看这块的内部实现,读了读jdk源码,这篇文章就当做个笔记。先简单介绍下四种引用类型:

####Java的四种引用类型####

  • StrongReference

强引用。最常见的引用类型,用赋值号,即“=”来创建。GC不会回收强引用,即使内存不足,也是宁可抛OOM先。

  • SoftReference

软引用。关键看内存,在内存不足时,GC会把软引用的对象回收掉。适用于对内存敏感的缓存。

  • WeakReference

弱引用。和软引用的区别是,无论内存充足与否,GC扫描到弱引用所引用的对象不再具有强引用时,会将其回收。

  • PhantomReference

虚引用,也称幽灵引用。其get()方法固定return null,看起来似乎没有什么大的用处,但在某些场景下结合ReferenceQueue,可以有意想不到的效果。

####ReferenceQueue####
站在coder的角度看,ReferenceQueue似乎更“有用”一些。其作用是追踪被gc的Reference对象,更多的是做一些统计或清理的工作。

####Reference的四种内部状态和ReferenceHandler####

Reference依赖内部的四种状态,和GC、ReferenceHandler配合来运作,包括:Active、Pending、Enqueued和Inactive,具体可以查看下Reference类的注释,鉴于笔者理解不足够深刻,就不误导大家了。

ReferenceHandler是个高优先级的线程,用于把gc处理的Reference对象enqueue到ReferenceQueue中。

近期使用SoftReference自己做了个缓存工具,用以缓存一定size的Hive查询结果,代码在这里

1456

博主是一个不是很聪明的码农。完美主义者,强迫症中期。这里会记录一些回忆和点滴,以博为镜。

武器库:

该博客使用基于  Hexo  的  simpleblock  主题。博客内容使用  CC BY-NC-SA 3.0  授权发布。最后生成于 2017-02-20.