`

利用ClassFileTransformer实现aop

    博客分类:
  • java
 
阅读更多

看了文章http://www.iteye.com/topic/1116696(这个文章非常好)中的字节码 部分,第一次接触到了java5新特性 instrumentation的ClassFileTransformer类,Instrumentation 的最大作用,就是类定义动态改变和操作。在 Java SE 5 及其后续版本当中,开发者可以在一个普通 Java 程序(带有 main 函数的 Java 类)运行时,通过 –javaagent 参数指定一个特定的 jar 文件(包含 Instrumentation 代理)来启动 Instrumentation 的代理程序。在类的字节码载入jvm前会调用ClassFileTransformer的transform方法,从而实现修改原类方法的功能,实现aop,这个的好处是不会像动态代理或者cglib技术实现aop那样会产生一个新类,也不需要原类要有接口。详细如下:

1.原类Business.java:

 

 

package model;

 

public class Business  {

 

 public boolean doSomeThing() {

        System.out.println("执行业务逻辑");

        return true;

    }

 

 public void doSomeThing2() {

        String s = "执行业务逻辑2";

        System.out.println(s);

    }

}

2.创建MyClassFileTransformer.java:

package bci;

import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

import test.MyClassloader;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import model.Business;

/**
 * 字节码转换器
 * 
 * 
 */
public class MyClassFileTransformer implements ClassFileTransformer {

    /**
     * 字节码加载到虚拟机前会进入这个方法
     */
    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
                            ProtectionDomain protectionDomain, byte[] classfileBuffer)
            throws IllegalClassFormatException {
        System.out.println(className);
        //如果加载Business类才拦截
        if (!"model/Business".equals(className)) {
            return null;
        }

        //javassist的包名是用点分割的,需要转换下
        if (className != null && className.indexOf("/") != -1) {
            className = className.replaceAll("/", ".");
        }
        try {
            //通过包名获取类文件
            CtClass cc = ClassPool.getDefault().get(className);
            //获得指定方法名的方法
            CtMethod m = cc.getDeclaredMethod("doSomeThing");
            //在方法执行前插入代码
            m.insertBefore("{ System.out.println(\"记录日志\"); }");
            return cc.toBytecode();
        } catch (NotFoundException e) {
        } catch (CannotCompileException e) {
        } catch (IOException e) {
            //忽略异常处理
        }
        return null;
    }

    /**
     * 在main函数执行前,执行的函数
     * 
     * @param options
     * @param ins
     */
    public static void premain(String options, Instrumentation ins) {
        //注册我自己的字节码转换器
        ins.addTransformer(new MyClassFileTransformer());
    }
}
3.测试类Test.java:
package bci;

import model.Business;

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        new Business().doSomeThing();   
        new Business().doSomeThing2();   

    }
}
4.将bci.MyClassFileTransformer类打成jar包,名为aop.jar,同时修改改jar中的META-INF/MANIFEST.MF内容为:
Manifest-Version: 1.0
Premain-Class: bci.MyClassFileTransformer
Can-Redefine-Classes: true  
Can-Retransform-Classes: true  
Can-Set-Native-Method-Prefix: true   
说明:Premain-Class用来允许 JAR 文件作为一个 Java 代理运行
5.运行Test.java,添加jvm启动参数:-javaagent:D:\aop.jar


 点击run运行结果如下:


 

也可将bci.MyClassFileTransformer及bci.Test同时打到aop.jar包中,且将aop.jar放在d:\下,由于MyClassFileTransformer需要依赖misc.javassist-3.9.0.GA.jar包,所以同时将该包也放在d:\下,

修改aop.jar包的manifest.mf文件如下:

 

Manifest-Version: 1.0

Premain-Class: bci.MyClassFileTransformer

Class-Path: misc.javassist-3.9.0.GA.jar

Main-Class: bci.Test

注意格式(这些规则当时调式了好久。。真怪异):

1.每个属性都是回车结尾;

2.class-path当前路径是jar包所在的路径,由于aop.jar的路径是d:\aop.jar,所以其所引用的路径是d:\misc.javassist-3.9.0.GA.jar;如果依赖多个jar包,则以空格分隔;

3.如果Class-Path需要分行写,那么要注意,第一行的最后要留一个空格,下一行的开头要留一个空格,如果第三行不是Class-Path的内容了,则第二行末尾不用留空格。 

4.将Main-Class放在Class-Path后定义。

5.属性名:(空格)属性值,注意加上空格。

在d:\下运行命令:

java -javaagent:aop.jar -jar aop.jar(作为可执行jar运行)

或者:java -javaagent:aop.jar bci.Test(运行bci.Test类)

结果如下:


 

如果在manifest.mf文件中不设置class-parh属性,也可以利用-cp参数(依赖包)运行aop.jar:

java -javaagent:aop.jar -cp  misc.javassist-3.9.0.GA.jar bci.Test(运行bci.Test类)

注意此时不可java -javaagent:aop.jar -cp misc.javassist-3.9.0.GA.jar -jar aop.jar(作为可执行jar运行)这样运行,因为-jar 和-cp不可同时使用,-cp会被忽略,最终报misc.javassist-3.9.0.GA.jar中的类找不到错误。

  • 大小: 56.1 KB
  • 大小: 18.2 KB
  • 大小: 14.7 KB
分享到:
评论
2 楼 zxjlwt 2015-11-18  
学习了。
http://surenpi.com
1 楼 幽蓝阿狸 2015-09-07  
但是,这个在javaweb项目中只能执行一次,一旦类已经被载入了jvm后,页面再次后续访问这个类的时候,便不会生效了,请问楼主如何解决的

相关推荐

    Java.lang.Instrument 代理Agent使用

    在 类的字节码载入JVM前 会调用ClassFileTransformer的transform方法,从而实现修改原类方法的功能,实现AOP,这个的好处是 不会像动态代理或者CGLIB技术实现AOP那样会产生一个新类,也不需要原类要有接口 。...

    性能测试工具TProfile代码简析

    其实现的核心原理就是利用javaAgent,在premain函数中使用java.lang.instrument.ClassFileTransformer,对允许  对TProfile&#40;https://github.com/taobao/TProfiler&#41;产生了兴趣,于是就下下来研究了一下:  ...

    agent-tools:一组用于将代理程序本地和远程地加载到JVM的工具的集合

    加载(ClassFileTransformer ctf)-&gt;加载ClassFileTransformer 删除(ClassFileTransformer ctf)-&gt;删除ClassFileTransformer reset(String ... classNames)-&gt;加载类的原始版本(无任何字节码修改) 重新转换...

    node-v11.6.0-sunos-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    node-v12.12.0-linux-s390x.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    基于统计分析的葡萄酒评价指标建立以及方案设计.doc

    本文档是课题研究的研究报告内含调研以及源码设计以及结果分析

    node-v12.9.1-linux-ppc64le.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    多线程应用程序设计.pdf

    多线程应用程序设计.pdf

    什么是蚁群算法路径规划matlab以及学习蚁群算法路径规划matlab的意义

    蚁群算法路径规划matlab

    IEC 60695-11-3:2012.pdf

    IEC 60695-11-3:2012.pdf

    仿eplie触屏版html5响应式手机wap网站模板下载.zip

    触屏版自适应手机wap软件网站模板 触屏版自适应手机wap软件网站模板

    node-v12.1.0-linux-ppc64le.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    node-v12.16.0-darwin-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    买花网微信鲜花网触屏版手机wap购物网站模板下载.zip

    触屏版自适应手机wap软件网站模板 触屏版自适应手机wap软件网站模板

    node-v10.22.1-linux-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    python实现的基于蒙特卡洛树搜索的AI黑白棋源码带详细注释.zip

    python实现的基于蒙特卡洛树搜索的AI黑白棋源码带详细注释.zip python实现的基于蒙特卡洛树搜索的AI黑白棋源码带详细注释.zip python实现的基于蒙特卡洛树搜索的AI黑白棋源码带详细注释.zip python实现的基于蒙特卡洛树搜索的AI黑白棋源码带详细注释.zip python实现的基于蒙特卡洛树搜索的AI黑白棋源码带详细注释.zip python实现的基于蒙特卡洛树搜索的AI黑白棋源码带详细注释.zip python实现的基于蒙特卡洛树搜索的AI黑白棋源码带详细注释.zip

    node-v11.8.0-sunos-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    孪生神经网络-python源码.zip

    孪生神经网络-python源码.zip

    仿GoMobile触屏版html5响应式手机app网站模板下载-懒人模板.zip

    触屏版自适应手机wap软件网站模板 触屏版自适应手机wap软件网站模板

    仿云贝饰品批发网触屏版手机wap购物网站模板.zip

    触屏版自适应手机wap软件网站模板 触屏版自适应手机wap软件网站模板

Global site tag (gtag.js) - Google Analytics