请欣赏!
Guice (发音同 ‘juice’) ,是一个 Google 开发的轻量级依赖性注入框架,适合 Java 6 以上的版本。
# Typical dependency injection public class DatabaseTransactionLogProvider implements Provider<TransactionLog> { @Inject Connection connection; public TransactionLog get() { return new DatabaseTransactionLog(connection); } }
# FactoryModuleBuilder generates factory using your interface public interface PaymentFactory { Payment create(Date startDate, Money amount); }GitHub, JavaDoc, 使用指南, FactoryModuleBuilder
HTTP是现代应用程序实现网络连接的途径,也是我们进行数据和媒体交换的工具。高效使用HTTP能使你的东西加载更快,并节省带宽。
OkHttp是一个非常高效的HTTP客户端,默认情况下:
OkHttpClient client = new OkHttpClient(); String run(String url) throws IOException { Request request = new Request.Builder() .url(url) .build(); Response response = client.newCall(request).execute(); return response.body().string(); }GitHub, Website
Retrofit 是 Square 下的类型安全的 HTTP 客户端,支持 Android 和 Java 等,它能将你的 HTTP API 转换为 Java 接口。
Retrofit 将 HTTP API 转换为 Java 接口:
public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>listRepos(@Path("user") String user); }Retrofit 类实现 GitHubService 接口:
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build(); GitHubService service = retrofit.create(GitHubService.class);来自 GitHubService 的每个 Call 都能产生为远程 Web 服务产生一个异步或同步 HTTP 请求:
Call<List<Repo>> repos = service.listRepos("octocat");GitHub, Website
与JQuery类似的Java Deferred/Promise类库
.then(…)
, .done(…)
, .fail(…)
, .progress(…)
, .always(…)
.when(p1, p2, p3, …).then(…)
wrappers.when(new Runnable() {…})
Deferred<Integer, Exception, Doubledeferred;
, deferred.resolve(10);
, deferred.reject(new Exception());
, deferred.notify(0.80);
,GitHu链接, 官方网站链接
RxJava – JVM的响应式编程扩展 – 是一个为Java虚拟机编写的使用可观察序列的构建异步的基于事件的程序的类库。
它基于 观察者模式实现对数据/事件的序列的支持,并添加了一些操作符,允许你以声明式构建序列, 使得开发者无需关心底层的线程、同步、线程安全和并发数据结构。
RxJava最常见的一个用法就是在后台线程运行一些计算和网络请求,而在UI线程显示结果(或者错误):
Flowable.fromCallable(() -{ Thread.sleep(1000); // imitate expensive computation return "Done"; }) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.single()) .subscribe(System.out::println, Throwable::printStackTrace); Thread.sleep(2000); // <--- wait for the flow to finishGitHub, Wiki
MBassador是一个实现了 发布-订阅模式的轻量级的,高性能的事件总线。它易于使用,并力求功能丰富,易于扩展,而同时又保证资源的高效利用和高性能。
MBassador的高性能的核心是一个专业的数据结构,它提供了非阻塞的读取器,并最小化写入器的锁争用,因此并发读写访问的性能衰减会是最小的。
// Define your listener class SimpleFileListener{ @Handler public void handle(File msg){ // do something with the file } } // somewhere else in your code MBassador bus = new MBassador(); Object listener = new SimpleFileListener(); bus.subscribe (listener); bus.post(new File("/tmp/smallfile.csv")).now(); bus.post(new File("/tmp/bigfile.csv")).asynchronously();GitHub, Javadoc
使用注解来减少Java中的重复代码,比如getter,setters,非空检查,生成的Builder等。
public int getFoo() {return foo;}了
。@ToString
, @EqualsAndHashCode
, @Getter注解,以及为所有非final的字段生成
@Setter
注解,以及生成 @RequiredArgsConstructor!
GitHub, Website
Java简单日志门面 (SLF4J) 为不同的日志框架(比如 java.util.logging
, logback
, log4j)提供了简单的门面或者抽象的实现,允许最终用户在部署时能够接入自己想要使用的日志框架。
简言之,类库和其他嵌入式的组件都应该考虑采用SLF4J作为他们的日志需求,因为类库无法将它们对日志框架的选择强加给最终用户。另一方面,对于独立的应用来说,就不一定需要使用SLF4J。独立应用可以直接调用他们自己选择的日志框架。而对于 logback来说,这个
问题是没有意义的,因为 logback是通过
SLF4J来暴露其日志接口的。
Website, GitHub, FAQ
对测试进行参数化,还不错
@Test @Parameters({"17, false", "22, true" }) public void personIsAdult(int age, boolean valid) throws Exception { assertThat(new Person(age).isAdult(), is(valid)); }与标准的JUnit 参数化运行器的区别如下:
官方网站, GitHub, 快速入门
Java里单元测试的非常棒(tasty)的模拟框架:
//你可以模拟具体的类,而不只是接口 LinkedList mockedList = mock(LinkedList.class); //打桩 when(mockedList.get(0)).thenReturn("first"); when(mockedList.get(1)).thenThrow(new RuntimeException()); //以下代码打印出"first"字符串 System.out.println(mockedList.get(0)); //以下代码抛出运行时异 System.out.println(mockedList.get(1)); //以下代码打印出"null",因为get(999)没有被打桩 System.out.println(mockedList.get(999)); //尽管是可以验证一个打过桩的调用,但通常是多余的 //如果你的代码关心get(0)返回值的内容,那么其他东西就会中断(往往在verify()执行之前就发生了)。 //如果你的代码不关心get(0)返回值的内容,那么它就不应该被打桩。不相信吗?看看这里。 verify(mockedList).get(0);官方网站, GitHub, 文档
它结合了JUnit、Guice和Mockito的能力。 而且它还听起来像一门很酷的武术。
标有@Inject注解的字段会被自动注入,
不需要担心会遗忘掉它们@RunWith(JukitoRunner.class) public class EmailSystemTest { @Inject EmailSystemImpl emailSystem; Email dummyEmail; @Before public void setupMocks( IncomingEmails incomingEmails, EmailFactory factory) { dummyEmail = factory.createDummy(); when(incomingEmails.count()).thenReturn(1); when(incomingEmails.get(0)).thenReturn(dummyEmail); } @Test public void shouldFetchEmailWhenStarting( EmailView emailView) { // WHEN emailSystem.start(); // THEN verify(emailView).addEmail(dummyEmail); } }GitHub, Website
Awaitility是一个小型的Java领域专用语言(DSL),用于对异步的操作进行同步。
测试异步的系统是比较困难的。不仅需要处理线程、超时和并发问题,而且测试代码的本来意图也有可能被这些细节所蒙蔽。Awaitility是一个领域专用语言,可以允许你以一种简洁且易读的方式来表达异步系统的各种期望结果。
@Test public void updatesCustomerStatus() throws Exception { // Publish an asynchronous event: publishEvent(updateCustomerStatusEvent); // Awaitility lets you wait until the asynchronous operation completes: await().atMost(5, SECONDS).until(customerStatusIsUpdated()); ... }
企业级的测试和规范框架。
class HelloSpockSpec extends spock.lang.Specification { def "length of Spock's and his friends' names"() { expect: name.size() == length where: name | length "Spock" | 5 "Kirk" | 4 "Scotty" | 6 } }GitHub, Website
用于模拟HTTP服务的工具
{ "request": { "method": "GET", "url": "/some/thing" }, "response": { "status": 200, "statusMessage": "Everything was just fine!" } }GitHub, Website