AspectJ AOP 简单示例2
来源:互联网 发布:德军总部新巨人 知乎 编辑:程序博客网 时间:2024/06/04 19:52
转自 http://blog.sina.com.cn/s/blog_46d0362d0100mmzy.html
有时候调试一些程序会牵涉到第三方的类库,但由于它们都是以class或者jar形式发布的,不大可能改变其行为,所以不是特别方便。这个时候唯一可以利用的就是AOP的技术,常用的就是AspectJ
首先是几个概念:
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 : trueShow all about me ...(0, 0)
定义一个aspect :由于1.5之后可以直接支持annotation,所以对于不复杂的aspect定义可以直接使用标签表示。但是目前aspectj支持的标签相对其语法来讲功能要弱些,因此可以根据实际情况选择
@Aspectpublic 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,所以使用比较方便
<taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties"> <classpath> <path refid="My Aop Example.classpath"> </path> </classpath> </taskdef> <target name="iajc"> <iajc sourceroots="${basedir}/src" inpath="${basedir}/lib/Line.jar" destdir="${basedir}/bin" classpathref="My Aop Example.classpath" source="1.5" /> </target>
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方发织入进去的?
- AspectJ AOP 简单示例2
- Spring AspectJ AOP 简单示例
- Spring AspectJ AOP 示例
- Spring AspectJ AOP 完整示例
- Spring AspectJ AOP 完整示例
- Spring AspectJ AOP 完整示例
- Spring AspectJ AOP 完整示例
- Spring AspectJ AOP 完整示例
- Spring AspectJ AOP 完整示例
- Spring AspectJ AOP 完整示例
- spring aop @aspectj的简单说明
- AOP具体实现--AspectJ(2)
- 8.4.2: AspectJ 实现AOP
- spring Aop简单示例
- Spring aop简单示例
- spring aop简单示例
- AOP的简单示例
- Spring aop简单示例
- 一个比较复杂的多次拆分字符串的存储过程
- matlab中fspecial中生成高斯模板的解释以及c语言实现
- LUA constant
- 查看 并发请求数及其TCP连接状态
- 用C#实现网络爬虫(一)
- AspectJ AOP 简单示例2
- 【ViewPager的学习】一、简单使用
- 网络编程
- 服务器TIME_WAIT和CLOSE_WAIT详解和解决办法
- 自定义ViewGroup
- 项目在eclipse运行正常,但单独部署到tomcat上出现乱码解决办法
- iOS开发者账号的类别与区别
- MySQL 实现树形的遍历(关于多级菜单栏以及多级上下部门的查询问题)
- 简单学生信息管理系统