有时候调试一些程序会牵涉到第三方的类库,但由于它们都是以class或者jar形式发布的,不大可能改变其行为,所以不是特别方便。这个时候有两个选择,其一就是进行二进制class文件修改(参看链接Java Binary Translation),这个对不熟悉class格式文件的人来说门槛有点高。第二种方法相对较为简单,就是利用AOP的技术,常用的实现库就是AspectJ(如果集成spring框架的AOP,参看链接Spring

AOP)

首先是几个概念:

1.aspect(层面) 2.pointcut(切入点)

3.advice(建议)4.weave(织入)5.LTW(加载期织入 load time weave)

按照aspectj的语法规则,一个aspect就是很多pointcut和advice的集合,也就是一个*.aj的文件

一个pointcut就是对target class的切入点定义,类似Java class定义中的field

一个advice就是对target class的行为改变,类似Java class中的method

weave就是aspectj runtime库把aspect织入到target class的行为。

LTW就是指运行期间动态织入aspect的行为,它是相对静态织入行为(包括对源文件、二进制文件的修改)。

一般来讲,从运行速度上来说,静态织入比动态织入要快些。因为LTW需要使用aspectj本身的classloader,

它的效率要低于jdk的classloader,因此当需要load的class非常多时,就会很慢的。

举个例子来说明aspectj的使用:

scenario: Example工程需要使用一个类Line存在于第三方库Line.jar中,但是Line本身没有实现Serializable接口,并且其toString方法输出也不完善。因此这两点都需要修改。

Line的实现:

package bean;

public class Line {

protected int x1 = 0;

protected

int x2 = 0;

public int

getX1(){

return x1;

}

public int

getX2(){

return x2;

}

public void

setLength(int newX, int newY){

setX1(newX);

setX2(newY);

}

public void

setX1(int newX) {

x1 = newX;

}

public void

setX2(int newY) {

x2 = newY;

}

public

String toString(){

return "(" + getX1() + ", " + getX2() + ")" ;

}

}

Main entry :

public class MyExample {

private Line line = null;

public MyExample() {

line = new Line();

System.err.println("Line

implement serializable interface : "

+

(line instanceof Serializable));

}

public void showMe() {

System.out.println("Show all

about me ...");

System.out.println(line.toString());

}

public static void main(String[] args) {

MyExample demo = new

MyExample();

// i want to change the action

of show me, but i cannot get line source.

// so i will trying load-time

weaving

demo.showMe();

}

}

output :

Line implement serializable interface : true

Show all about me ...

(0, 0)

定义一个aspect :由于1.5之后可以直接支持annotation,所以对于不复杂的aspect定义可以直接使用标签表示。但是目前aspectj支持的标签相对其语法来讲功能要弱些,因此可以根据实际情况选择

@Aspect

public class DynamicPrinter {

@Pointcut("call(void

example.aop.weaver.MyExample.showMe())")

void printTitle() {}; //此处定义一个切入点--发生调用MyExample的showMe()方法的时刻

@Before("printTitle()")//此处定义了一个advice,其直接引用到前面定义的切入点

public void printStartMessage() {

System.out.println("***************************************");

}

@After("printTitle()")//此处定义了一个advice,其直接引用到前面定义的切入点

public void printOverMessage() {

printStartMessage();

}

@Around("call(String bean.Line.toString())")

//此处定义了一个替换方法的advice,由于没有已定义的切入点可以引用,因此写出切入点原始信息call(String

bean.line.toString())

public String redirectMessage() {

return "This is a hack

action!!!";

}

@DeclareParents("bean.Line")

private Serializable i;

}

编译aj和源文件

由于aspectj提供了ant的task,所以使用比较方便

注意一点是,目前iajc只支持最高1.5 level的文件编译,如果使用高于1.5的jdk的话,需要指定编译级别到1.5

sourceRoots, sourceRootsRef

(Path)

Directories containing source files

(ending with .java or .aj) to compile.

inpath, inpathRef (Path)

Read .class files for bytecode weaving

from directories or zip files (like classpath).

classpath, classpathRef (Path)

The classpath used by the sources being

compiled. When compiling aspects, include the same version of the

aspectjrt.jar.

destDir

The directory in which to place the

generated class files. Only one of destDir and

outJar may be set.

new output :

Line implement serializable interface : true

***************************************

Show all about me ...

This is a hack action!!!

***************************************

后记 :

把iajc编译后的源文件反编译之后,就可以参考静态织入的源码道理了

public class MyExample

{

private

Line line;

private static final

org.aspectj.lang.JoinPoint.StaticPart ajc$tjp_0;

public

MyExample()

{

line = null;

line = new Line();

System.err.println((new StringBuilder("Line implement serializable

interface : ")).append(line instanceof

Serializable).toString());

}

public

void showMe()

{

System.out.println("Show all about me ...");

Line line1;

System.out.println(toString_aroundBody1$advice(this,

line1 = line, DynamicPrinter.aspectOf()));

}

public

static void main(String args[])

{

MyExample demo = new MyExample();

demo;

DynamicPrinter.aspectOf().printStartMessage();

showMe();

break MISSING_BLOCK_LABEL_30;

Throwable throwable;

throwable;

DynamicPrinter.aspectOf().printOverMessage();

throw throwable;

DynamicPrinter.aspectOf().printOverMessage(); return;

}

private

static final String toString_aroundBody0(MyExample myexample, Line

line1)

{

return line1.toString();

}

private

static final String toString_aroundBody1$advice(DynamicPrinter

this, Line line1, DynamicPrinter dynamicprinter)

{

return "This is a hack

action!!!";

}

static

{

Factory factory = new Factory("MyExample.java",

Class.forName("example.aop.weaver.MyExample"));

ajc$tjp_0 = factory.makeSJP("method-call",

factory.makeMethodSig("1", "toString", "bean.Line", "", "", "",

"java.lang.String"), 26);

}

}

public class DynamicPrinter

{

private Serializable i;

private

static Throwable ajc$initFailureCause;

public

static final DynamicPrinter ajc$perSingletonInstance;

public

DynamicPrinter()

{

}

void printTitle()

{

}

public

void printStartMessage()

{

System.out.println("***************************************");

}

public

void printOverMessage()

{

printStartMessage();

}

public String redirectMessage()

{

return "This is a hack action!!!";

}

public

static DynamicPrinter aspectOf()

{

if(ajc$perSingletonInstance == null)

throw new NoAspectBoundException("example.aop.hook.DynamicPrinter",

ajc$initFailureCause);

else

return ajc$perSingletonInstance;

}

public

static boolean hasAspect()

{

return ajc$perSingletonInstance != null;

}

private

static void ajc$postClinit()

{

ajc$perSingletonInstance = new DynamicPrinter();

}

static

{

try

{

ajc$postClinit();

}

catch(Throwable throwable)

{

ajc$initFailureCause = throwable;

}

}

}

但是反编译jar中Line.class的时候,发现其结构没有变化,不知为何能够在运行时刻将serializable接口和toString方发织入进去的?

java public aspect_ASPECT Java的使用相关推荐

  1. Invalid default: public abstract java.lang.Class org.mybatis.spring.annotation.MapperScan.factoryBe

    错误信息: java.lang.annotation.AnnotationFormatError: Invalid default: public abstract java.lang.Class o ...

  2. java 读取txt,java读取大文件

    java 读取txt,java读取大文件 package com.bbcmart.util; import java.io.File; import java.io.RandomAccessFile; ...

  3. java.utilDate和java.sql.Date

    java.utilDate和java.sql.Date由广州疯狂软件教育java培训分享: java程序中的时间类型有java.util.Date和java.sql.Date两种.两者之间的关系和转化 ...

  4. java hibernate oracle,Java笔记8:Hibernate连接Oracle

     1下载hibernate-3.6.0 Final.zip到任意目录,解压缩后得到hibernate目录 2下载slf4j-1.7.13.zip到任意目录,解压缩后得到slf4j-1.7.13 3 ...

  5. java 终极超类,Java问答:终极父类(3),java问答

    Java问答:终极父类(3),java问答Java问答:终极父类(上) Java问答:终极父类(下) Java问答:终极父类(2)-上篇 Java问答:终极父类(2)-下篇 在之前关于 Object ...

  6. java.net import_import java.net.URL;是什么类?

    展开全部 java.net.URL中定义了URL相关的操作,其主要利用的是openStream();方法来返回一个InputStream,然后可以使用InputStreamReader和Buffere ...

  7. ArrayMap java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Object[]

    错误堆栈: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Object[]at android. ...

  8. 给Java初学者福利——Java语法基础

    Java代码基本格式 Java中所有程序代码都必须存在于一个类中,用class关键字定义类,在class之前可以有一些修饰符.格式如下: 修饰符 class 类名 { 程序代码 } 注: 1.Java ...

  9. cxf springmvc_拥抱模块化Java平台:Java 10上的Apache CXF

    cxf springmvc 自Java 9发布最终将Project Jigsaw交付给大众以来,已经过去了整整一年的时间. 这是一段漫长的旅程,但是在那里,所以发生了什么变化? 这是一个很好的问题,答 ...

  10. java ee_使用Java EE的ManagedExecutorService异步执行事务

    java ee 自Java EE 7规范发布以来已经过去了一年. 现在,Wildfly 8 Final已发布,现在是时候仔细看看这些新功能了. 自从Java EE时代开始以来就缺少的一件事是能够使用成 ...

最新文章

  1. [转]JAVA实现文件压缩
  2. android 获取应用的当前版本号获取当前android系统的版本号
  3. Linux学习进阶路线图
  4. php unset函数_PHP | 使用unset()函数从数组中删除元素
  5. 东软刘积仁:软件已从高科技领域变成大众消费品
  6. 华为鸿蒙系统适合机型,华为鸿蒙os2.0系统适用哪些机型
  7. 很幽默的讲解六种Socket I/O模型C++程序设计
  8. GARFIELD@10-21-2004
  9. python实现自动打电话软件_python拨打电话
  10. 毕业生必看,计算机毕设如何选题才能高分通过?
  11. 红帽linux中文系统下载iso,红帽子9.0版下载-redhat linux 9.0 iso下载 简体中文正式版-IT猫扑网...
  12. 使用iconfont阿里多色矢量图标
  13. pyodbc-操作SQLserver
  14. xshell复制粘贴快捷键
  15. 在 Coq 中形式化 100 个定理
  16. JavaRSAJS加密解密(整合版,仅供自己参考)
  17. 各种生物识别的优缺点
  18. android:使用small一步步实现插件化与热更新
  19. Bilateral attention network for RGB-D salient object detection阅读笔记
  20. 一篇文章构建你的 NodeJS 知识体系(W字长文)

热门文章

  1. 北大计算机博士毕业难度,北京大学博士毕业要求
  2. IDEA项目上传码云报错:Push rejected: Push to origin/master was rejected
  3. Peer Manager
  4. Java基础(二)public、private、protected修饰的方法
  5. 关于Dev C++等软件突然提示16位应用程序不兼容的问题
  6. golang 单元测试进阶篇
  7. acm 算法 java_有关acm算法的一道java题
  8. 网工解惑:何为二层交换机,它与三层交换机的区别在哪里?
  9. html蒙版源代码,jquery蒙版控件实现代码_jquery
  10. linux版虚拟示波器,借你一双慧眼——DSCope虚拟示波器评测