改进 visitMethod 方法,增加对构造函数的处理:
- public MethodVisitor visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
- MethodVisitor wrappedMv = mv;
- if (mv != null) {
- if (name.equals("operation")) {
- wrappedMv = new AddSecurityCheckMethodAdapter(mv);
- } else if (name.equals("<init>")) {
- wrappedMv = new ChangeToChildConstructorMethodAdapter(mv,
- enhancedSuperName);
- }
- }
- return wrappedMv;
- }
public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); MethodVisitor wrappedMv = mv; if (mv != null) { if (name.equals("operation")) { wrappedMv = new AddSecurityCheckMethodAdapter(mv); } else if (name.equals("<init>")) { wrappedMv = new ChangeToChildConstructorMethodAdapter(mv, enhancedSuperName); } } return wrappedMv; }
这里 ChangeToChildConstructorMethodAdapter 将负责把 Account 的构造函数改造成其子类 Account$EnhancedByASM 的构造函数:
- class ChangeToChildConstructorMethodAdapter extends MethodAdapter {
- private String superClassName;
- public ChangeToChildConstructorMethodAdapter(MethodVisitor mv,
- String superClassName) {
- super(mv);
- this.superClassName = superClassName;
- }
- public void visitMethodInsn(int opcode, String owner, String name,
- String desc) {
- //调用父类的构造函数时
- if (opcode == Opcodes.INVOKESPECIAL && name.equals("<init>")) {
- owner = superClassName;
- }
- super.visitMethodInsn(opcode, owner, name, desc);//改写父类为superClassName
- }
- }
class ChangeToChildConstructorMethodAdapter extends MethodAdapter { private String superClassName; public ChangeToChildConstructorMethodAdapter(MethodVisitor mv, String superClassName) { super(mv); this.superClassName = superClassName; } public void visitMethodInsn(int opcode, String owner, String name, String desc) { //调用父类的构造函数时 if (opcode == Opcodes.INVOKESPECIAL && name.equals("<init>")) { owner = superClassName; } super.visitMethodInsn(opcode, owner, name, desc);//改写父类为superClassName } }
最后演示一下如何在运行时产生并装入产生的 Account$EnhancedByASM。 我们定义一个 Util 类,作为一个类工厂负责产生有安全检查的 Account 类:
- public class SecureAccountGenerator {
- private static AccountGeneratorClassLoader classLoader =
- new AccountGeneratorClassLoade();
- private static Class secureAccountClass;
- public Account generateSecureAccount() throws ClassFormatError,
- InstantiationException, IllegalAccessException {
- if (null == secureAccountClass) {
- ClassReader cr = new ClassReader("Account");
- ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- ClassAdapter classAdapter = new AddSecurityCheckClassAdapter(cw);
- cr.accept(classAdapter, ClassReader.SKIP_DEBUG);
- byte[] data = cw.toByteArray();
- secureAccountClass = classLoader.defineClassFromClassFile(
- "Account$EnhancedByASM",data);
- }
- return (Account) secureAccountClass.newInstance();
- }
- private static class AccountGeneratorClassLoader extends ClassLoader {
- public Class defineClassFromClassFile(String className,
- byte[] classFile) throws ClassFormatError {
- return defineClass("Account$EnhancedByASM", classFile, 0, classFile.length());
- |-------10--------20--------30--------40--------50--------60--------70--------80--------9|
- |-------- XML error: The previous line is longer than the max of 90 characters ---------|
- }
- }
- }
public class SecureAccountGenerator { private static AccountGeneratorClassLoader classLoader = new AccountGeneratorClassLoade(); private static Class secureAccountClass; public Account generateSecureAccount() throws ClassFormatError, InstantiationException, IllegalAccessException { if (null == secureAccountClass) { ClassReader cr = new ClassReader("Account"); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); ClassAdapter classAdapter = new AddSecurityCheckClassAdapter(cw); cr.accept(classAdapter, ClassReader.SKIP_DEBUG); byte[] data = cw.toByteArray(); secureAccountClass = classLoader.defineClassFromClassFile( "Account$EnhancedByASM",data); } return (Account) secureAccountClass.newInstance(); } private static class AccountGeneratorClassLoader extends ClassLoader { public Class defineClassFromClassFile(String className, byte[] classFile) throws ClassFormatError { return defineClass("Account$EnhancedByASM", classFile, 0, classFile.length()); |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| } } }
静态方法 SecureAccountGenerator.generateSecureAccount() 在运行时动态生成一个加上了安全检查的 Account 子类。著名的 Hibernate 和 Spring 框架,就是使用这种技术实现了 AOP 的“无损注入”。
小结
最后,我们比较一下 ASM 和其他实现 AOP 的底层技术:
表 1. AOP 底层技术比较
AOP 底层技术 功能 性能 面向接口编程 编程难度
直接改写 class 文件 完全控制类 无明显性能代价 不要求 高,要求对 class 文件结构和 Java 字节码有深刻了解
JDK Instrument 完全控制类 无论是否改写,每个类装入时都要执行hook程序 不要求 高,要求对 class 文件结构和 Java 字节码有深刻了解
JDK Proxy 只能改写 method 反射引入性能代价 要求 低
ASM 几乎能完全控制类 无明显性能代价 不要求 中,能操纵需要改写部分的 Java 字节码
发表评论
-
jvm垃圾收集算法简介
2008-12-26 11:33 16051 Tracing算法 tracing算法是 ... -
jvm结构
2008-12-26 10:24 1680类文件格式 JVM使用一种硬件、操作系统无关的二进制格式来保存 ... -
JProfiler4.3.2 远程 监控 配置
2008-12-25 11:37 2138准备工作:在本地机器和远端机器上都安装好JProfiler。 ... -
Eclipse常用快捷键
2008-12-23 11:22 1042编辑相关快捷键 ... -
jvm内存
2008-12-12 16:40 1208· 堆(Heap)和非堆(Non-heap)内存 按照官方 ... -
AOP 的利器:ASM 3.0 介绍一
2008-11-24 13:24 843随着 AOP(Aspect Oriented Progra ...
相关推荐
AOP 的利器:ASM 3_0 介绍,很好的书
### AOP 的利器 ASM 3.0 #### 引言 随着面向切面编程(Aspect-Oriented Programming,简称AOP)技术的发展,代码的动态生成已成为Java领域中不可或缺的一部分。本文将详细介绍一种轻量级的Java字节码操控框架——...
AOP联盟:aopalliance.jar API包a set of AOP Java interface .
2. **注解驱动**:Spring 3.0极大地强化了注解的支持,如`@Autowired`用于自动装配依赖,`@Service`、`@Repository`和`@Controller`定义服务层、数据访问层和表现层组件,`@RequestMapping`用于映射HTTP请求,这些...
《SpringSide 3.0:Java企业开发的高效框架指南》 SpringSide 3.0 是一个基于Spring框架的开源项目,旨在为Java开发者提供一套高效、简洁的开发规范和工具集。它不仅包含了Spring的核心模块,还整合了其他优秀的...
2. **AOP(面向切面编程)**:Spring 3.0提供了更强大的AOP支持,允许开发者定义横切关注点,如日志记录、事务管理等,将这些关注点与业务逻辑解耦。 3. **JSR-303/JSR-349(Bean Validation)集成**:Spring 3.0...
2. **AOP(面向切面编程)**:Spring3.0增强了对AOP的支持,可以方便地创建和管理切面。@Aspect注解用于定义切面,@Before、@After、@Around等用于定义通知,使得代码结构更加清晰。 3. **数据访问增强**:Spring...
2. **AOP(Aspect-Oriented Programming,面向切面编程)**:Spring3.0提供了强大的AOP支持,使得开发者可以方便地定义和实现横切关注点,如日志、事务管理等,从而实现代码的解耦。 3. **IoC(Inversion of ...
2. **注解支持**:Spring 3.0 大量引入了注解,如`@Autowired`、`@Service`、`@Repository`和`@Controller`等,使得开发者可以更简洁地声明组件,减少XML配置文件的复杂性。 3. **AOP改进**:Spring 3.0 对AOP进行...
下面将详细介绍 Spring 3.0 的关键知识点。 1. **依赖注入**:Spring 3.0 对依赖注入进行了优化,使得开发者可以更加灵活地管理对象间的依赖关系。DI 允许组件声明其依赖,而不是硬编码创建和查找依赖对象。这提高...
2. **JDK动态代理与CGLIB结合**:Spring 3.0可以同时使用JDK动态代理和CGLIB,提高了AOP代理的灵活性。 三、数据访问/集成 1. **JDBC模板**:提供了JdbcTemplate,简化了JDBC的使用,避免了重复的模板代码。 2. *...
2. **AOP(面向切面编程,Aspect Oriented Programming)**:Spring 3.0提供了全面的AOP支持,包括定义、实现和管理切面。AOP可以将关注点分离,如日志、事务管理等,从而让业务逻辑更加清晰。 3. **注解驱动的开发...
这个压缩包中的"spring3.0"文件很可能包含了所有需要的Spring 3.0框架相关的jar包,包括核心库、AOP、Web、MVC等模块的jar,是搭建Spring 3.0环境所必需的。开发者可以通过这些jar包快速构建基于Spring 3.0的应用,...
3. **AOP增强**:Spring 3.0增强了面向切面编程(Aspect-Oriented Programming, AOP)的支持,新增了`@Aspect`注解来声明切面,并且支持基于注解的切点表达式,使得切面的定义更加简洁。 4. **JSR-303数据验证**:...
2. **依赖注入(Dependency Injection, DI)**:Spring3.0的DI机制使得对象之间的依赖关系可以通过配置文件或注解来管理,提高了代码的可测试性和可维护性。 3. **注解支持**:Spring3.0大幅增强了对注解的支持,如...
2. **JSR-303 Bean Validation集成**:Spring 3.0支持Java Bean Validation规范,通过JSR-303注解可以对对象属性进行验证,提供了一种声明式的方式,增强了业务逻辑的安全性。 3. **Expression Language (SpEL)**:...
2. **AOP(Aspect Oriented Programming, 面向切面编程)**:Spring 3.0对AOP进行了优化,支持更多样化的切面定义,包括基于注解的切面,使得事务管理、日志记录等横切关注点的处理更加简洁。 3. **MVC(Model-View...
2. **AOP(Aspect Oriented Programming, 面向切面编程)**:Spring 3.0提供了强大的AOP支持,用于实现如日志记录、事务管理等横切关注点。AOP允许开发者定义“切面”,将这些关注点与业务逻辑分离。 3. **MVC框架*...
2. **AOP(Aspect Oriented Programming)**:Spring 3.0支持面向切面编程,允许开发者定义“切面”来封装横切关注点,如日志、事务管理等,使业务代码更专注于核心逻辑。Spring的AOP通过代理模式实现,支持JDK动态...
2. **面向切面编程(Aspect-Oriented Programming, AOP)**:Spring 3.0的AOP支持更加强大,允许开发者定义和执行横切关注点,如日志、事务管理等。@Aspect注解用于声明切面,@Before、@After、@Around等注解用于...