sbt 项目通过 sbt-aspectj-plugin 使用 AspectJ
Java 在运用面向方向编程时,依照 AspectJ 的语法自己书写 *.aj 文件可以得到尽可能大的控制能力。如果是一个 sbt 的项目,有一个 sbt-aspectj-plugin 插件可以帮上我们的忙。那么如何应用这个插件呢? 该插件首页面告诉我们要在 其他就是参考例子 runnable sample projects,然而这几个例子并非那么直白。所以还是自己做一个最简单的例子来体验 sbt 项目如何使用 AspectJ.
这是一个默认的 sbt+AspectJ 的项目布局
各文件的内容分别如下:
build.sbt
上面的配置是把属性用 project.setting() 方法来设置,也可以不依赖于 (project in file(".")),下面的配置是一样的
和 .settings(aspectjSetting:_*) 一样,上面的 aspectjSetting 同样是关键,否则会报如下错误:
build.properties (只放了一行)
plugins.sbt (加载 sbt-aspectj 依赖)
src/main/java/sample/Sample.java (Java 代码在 sbt 项目中默认位置)
src/main/aspectj/SampleAspect.aj (方面定义文件默认放在 src/main/aspectj 目录中)
用 aspect 定义方面,文件名是 *.aj,它也可以用 Java 一样用
现在来看执行效果
进到 sbt-aspectj-sample 目录中,然后执行 sbt 命令,接着执行 sbt 的 run 任务就会看到下面的输出
从上面可看出在执行 sample.Sample.main() 方法之前执行了方面 SampleAspect 中 before() 指定的方法,说明拦截成功。
这里只是一个最简单的例子实现了方面的正确切入,更多 AspectJ 的语法如 after(), around() 或捕获异常等,请参考其他相关资料。
比如可以把 src/main/aspectj/SampleAspect.aj 改为
同时把 build.sbt 中的
verbose in Aspectj := true
改为
verbose in Aspectj := false
再进到 sbt 控制台执行下 run param1 param2 看下输出是
这样拦截了整个方法的前前后后的执行,借此可以修改目标方法原有的参数值。 永久链接 https://yanbin.blog/sbt-project-sbt-aspectj-plugin-use-aspectj/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
project/plugins.sbt 中加上下面这句话1addSbtPlugin("com.typesafe.sbt" % "sbt-aspectj" % "0.10.4")这是一个默认的 sbt+AspectJ 的项目布局
1sbt-aspectj-sample/
2├── build.sbt
3├── project
4│ ├── build.properties
5│ └── plugins.sbt
6└── src
7 └── main
8 ├── aspectj
9 │ └── SampleAspect.aj
10 └── java
11 └── sample
12 └── Sample.javabuild.sbt
1import com.typesafe.sbt.SbtAspectj._
2import com.typesafe.sbt.SbtAspectj.AspectjKeys._
3
4name := "sbt-aspectj-sample"
5
6val main = (project in file("."))
7 .settings(aspectjSettings: _*)
8 .settings(
9 inputs in Aspectj <+= compiledClasses,
10 products in Compile <<= products in Aspectj,
11 products in Runtime <<= products in Compile,
12 verbose in Aspectj := true
13 )上面的配置是把属性用 project.setting() 方法来设置,也可以不依赖于 (project in file(".")),下面的配置是一样的
1import com.typesafe.sbt.SbtAspectj._
2import com.typesafe.sbt.SbtAspectj.AspectjKeys._
3
4name := "sbt-aspectj-sample"
5
6aspectjSettings
7
8inputs in Aspectj <+= compiledClasses
9
10products in Compile <<= products in Aspectj
11
12products in Runtime <<= products in Compile和 .settings(aspectjSetting:_*) 一样,上面的 aspectjSetting 同样是关键,否则会报如下错误:
1[error] References to undefined settings:
2[error]
3[error] aspectj:inputs from aspectj:inputs (/Users/yanbin/Desktop/sbt-aspectj-sample/build.sbt:8)
4[error]
5[error] aspectj:products from compile:products (/Users/yanbin/Desktop/sbt-aspectj-sample/build.sbt:10)build.properties (只放了一行)
1sbt.version=0.13.5plugins.sbt (加载 sbt-aspectj 依赖)
1addSbtPlugin("com.typesafe.sbt" % "sbt-aspectj" % "0.10.4")src/main/java/sample/Sample.java (Java 代码在 sbt 项目中默认位置)
1package sample;
2
3public class Sample {
4 public static void main(String[] args) {
5 System.out.println("Print from Sample class");
6 }
7}src/main/aspectj/SampleAspect.aj (方面定义文件默认放在 src/main/aspectj 目录中)
1public aspect SampleAspect {
2
3 before(): execution(* sample.Sample.main(..)) {
4 System.out.println("Weaved content from SampleAspect");
5 }
6}用 aspect 定义方面,文件名是 *.aj,它也可以用 Java 一样用
package sample 来定义包名,但没要求包名与目录层次一致。上面方面定义的是在招待 sample.Sample.main() 方法前打印 "Wearved content from SampleAspect".现在来看执行效果
进到 sbt-aspectj-sample 目录中,然后执行 sbt 命令,接着执行 sbt 的 run 任务就会看到下面的输出
1[I] ➜ sbt-aspectj-sample git:(master) ✗ sbt
2[info] Loading project definition from /Users/yanbin/Desktop/sbt-aspectj-sample/project
3[info] Set current project to sbt-aspectj-sample (in build file:/Users/yanbin/Desktop/sbt-aspectj-sample/)
4> run
5[info] Weaving 1 input with 1 AspectJ source to /Users/yanbin/Desktop/sbt-aspectj-sample/target/scala-2.10/aspectj/classes...
6[info] info directory classpath entry does not exist: /Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre/lib/sunrsasign.jar
7[info] info zipfile classpath entry does not exist: /Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre/classes
8[info] info Pipelining compilation
9[info] info compiling /Users/yanbin/Desktop/sbt-aspectj-sample/src/main/aspectj/SampleAspect.aj
10[info] info weaver operating in reweavable mode. Need to verify any required types exist.
11[info] info woven aspect SampleAspect (from /Users/yanbin/Desktop/sbt-aspectj-sample/src/main/aspectj/SampleAspect.aj)
12[info] info woven class sample.Sample (from /Users/yanbin/Desktop/sbt-aspectj-sample/target/scala-2.10/classes/sample/Sample.class)
13[info] info Compiler took 768ms
14[info] Running sample.Sample
15Weaved content from SampleAspect
16Print from Sample class
17[success] Total time: 1 s, completed Nov 17, 2015 11:15:09 PM从上面可看出在执行 sample.Sample.main() 方法之前执行了方面 SampleAspect 中 before() 指定的方法,说明拦截成功。
这里只是一个最简单的例子实现了方面的正确切入,更多 AspectJ 的语法如 after(), around() 或捕获异常等,请参考其他相关资料。
比如可以把 src/main/aspectj/SampleAspect.aj 改为
1package sample;<br/><br/>
2privileged public aspect SampleAspect {
3
4 pointcut aroundMain(String[] args) : execution(* sample.Sample.main(..)) && args(args);
5
6 void around(String[] args): aroundMain(args) {
7 System.out.println("inputs: " + java.util.Arrays.asList(args));
8 proceed(args);
9 System.out.println("after method");
10 }
11}同时把 build.sbt 中的
verbose in Aspectj := true
改为
verbose in Aspectj := false
再进到 sbt 控制台执行下 run param1 param2 看下输出是
1[I] ➜ sbt-aspectj-sample git:(master) ✗ sbt
2[info] Loading project definition from /Users/yanbin/Desktop/sbt-aspectj-sample/project
3[info] Set current project to sbt-aspectj-sample (in build file:/Users/yanbin/Desktop/sbt-aspectj-sample/)
4> run param1 param2
5[info] Running sample.Sample param1 param2
6inputs: [param1, param2]
7Print from Sample class
8after method
9[success] Total time: 0 s, completed Nov 17, 2015 11:45:00 PM
10>这样拦截了整个方法的前前后后的执行,借此可以修改目标方法原有的参数值。 永久链接 https://yanbin.blog/sbt-project-sbt-aspectj-plugin-use-aspectj/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。