体验 Scala 2.12 支持的 Java 8 风格(SAM) Lambda

上一次关注 Scala 新版本特性还是在将近五年前,针对的是  Scala 2.10. 后来也一直在使用 Scala,基本上是 Scala 2.11,但对 Scala 2.11 所带来的新特性基本无知,大约有个 Macro 功能,没什么机会用上,应用 sbt 时稍有接触。还是老句老话,了解新特性最可靠的文档是每个版本的的 Release Notes, 比如 Scala 2.12.0 Release Notes.

其中 Scala 2.12 带来的主要特性在于对 Java 8 的充分支持:

  1. Scala 可以有方法实现的 trait 直接编译为带默认方法的 Java 接口
  2. Lambda 表达式无需生成相应的类,而是用到 invokedynamic 字节码指令(这个是 Java 7 加进来的新指令)
  3. 最方便的功能莫过于终于支持 Java  8 风格的 Lambda,即功能性接口的 SAM(Single Abstract Method)

Scala 的 Lambda 内部实现

这儿主要是体验 Scala 2.12 如何使用 Java 8 风格的 Lambda. 在 Scala 2.12 之前,Scala 对 Lambda 的支持是为你准备了一大堆的 trait 类,有

  1. Function0, Function1, ...... Function22 (接收多个参数,返回一个值)
  2. Product1, Product2, ...... Product22 (函数返回多个值,即 TupleX 时用的)

阅读全文 >>

Spark 提交任务时 Invalid signature file digest 错误

第一次用  spark-submit 提交任务,是 Scala 的程序,命令格式是

spark-submit --class <main-class> --master local[*] --name "My first Spark Job" spark-test-fat-1.0-SNAPSHOT.jar

结果报出错误

Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
at sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:330)
at sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:263)
at java.util.jar.JarVerifier.processEntry(JarVerifier.java:318)
......
at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:119)
at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)

Google 查了下,是需要把 jar 文件中的 META-INF/*.RSA META-INF/*.DSA META-INF/*.SF 文件清理掉。我们可以执行如下命令从现有的 jar 中除去

zip -d <jar file name>.jar META-INF/*.RSA META-INF/*.DSA META-INF/*.SF

是因为 jar 包中包含有这些文件才造成提交 Spark 时验证文件签名摘要时失败。 阅读全文 >>

IntelliJ IDEA 中创建 Maven Scala 项目

Scala 项目看家的构建工具当然是 SBT, 假如我们已习惯于 Maven, 想要用 Maven 来构建 Scala 项目该如何做呢?那首先要找到一个 Maven Scala 相应的 Archetype, 然后用命令 mvn archetype:generate 或是在 IntelliJ IDEA 使用 Maven 项目创建向导来选择一个 Maven Scala Archetype。这里主要介绍 IntelliJ IDEA 中 Maven 向导创建 Scala 项目的方式。

首先确保我们已安装了 IntelliJ IDEA 的 Maven 和  Scala 插件。插件中自带了 org.scala-tools.archetypes:scala-archetype-simple:1.2 的 Maven archetype, 这是一个貌视 Scala 官方的 archetype。我们可以尝试基于它来创建一个 Maven Scala 项目。通过 IntelliJ IDEA 的菜单 File/New/Project..., 在弹出的窗口中选择 Maven/Create from archetype, 然后找到 scala-archetype-simple, 自带版本为 1.2, 当前最新版也不过 1.3, 那还是  2010 年建立,别提有多老了。 阅读全文 >>

JMockit 中被 Mocked 的对象属性及方法的默认值

前脚研究完 Mockito 中被 Mocked 的对象属性及方法的默认值, 虽然目今更多的是拥抱着 Mockito, 但总有时对 JMockit 也会挤眉弄眼,谁叫 JMockit 无所不能呢!被 Mockito 的 Mock 对象方法的默认返回值洗脑之后,进而觉察出 JMockit 应该有同样的实现方式。

经过类似的测试,这里不详细列出测试过程,只是在基于前篇的测试中加入 JMockit 的依赖,最新版是 1.36。测试类 MyClassTest 中使用

来构造 MyClass 的 mock 对象 myClass, 其余代码是一样的。相关代码请前往上篇 Mockito 中被 Mocked 的对象属性及方法的默认值 中找。 使用 JMockit 后跑出来的效果如下: 阅读全文 >>

Mockito 中被 Mocked 的对象属性及方法的默认值

在 Java 测试中使用 Mockito 有段时日了,以前只是想当然的认为 Mock 的对象属性值和方法返回值都是依据同样的规则。基本类型是 0, 0.0, 或 false, 对象类型都是 null, Mock 对象的默认返回值也应该是一样的。直到最近有一天,有一个返回 Optional<String> 类型的方法,由于忘记对该方法打桩,意外的发现它返回的不是 null, 而 Optional.empty(), 因此才意识到此处定有蹊跷。着实有必要用代码验证一下 Mockito 是怎么决定属性及方法的各种返回类型的默认值的。

此次测试所用的 Mockito 版本是 mockito-core-2.12.0.

于是创建了下面一个类 MyClass 用于生成 Mock 对象,选取了一些典型的数据类型, 包括 int, Double, String, long[], Optional<String>, Collection<String>, Map<String, String>, 同时测试 Mock 对象默认的属性值与方法默认返回值。 阅读全文 >>

记录一下 Spring 如何扫描注解的 Bean 与资源

Spring 相关代码分析

本文通过对 Spring 的源代码来理解它是如何扫描 Bean 与资源的,因为自己有一个类似的需求,想把一堆的配置文件丢到 resources 下某个目录中,在程序启动的时候能加载它们。因为文件名是不一定的,所以不能直接指定文件名来加载,通过对 Spring 扫描资源的理解后,可以在自己的代码中手工扫描那些配置文件,以后有任何新的配置文件只需要扔到相应的配置目录即可。

下面以一个最简单的 Spring Boot 项目为例,调试并观察源代码

还是直奔主题吧,不一步一步的去探寻到底是哪个实现类去扫描资源的,用 Google 找到的是 ClassPathScanningCandidateComponentProvider, 因此直接在这个类的敏感位置上打上断点,比如它的构造函数 阅读全文 >>