`
baihongsheng
  • 浏览: 13376 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类

AOP:ASM直接为类方法添加前拦截执行--无损方法

    博客分类:
  • ASM
阅读更多

//所谓无损即 在不改变原有类文件的情况下,为指定方法 添加前拦截,总体实现与前一个例子差不多,但是不需要生产新的类文件。

//思路:
//改变 Class Description, 将其命名为 Account$EnhancedByASM,将其父类指定为 AccountASM。
//改变构造函数,将其中对父类构造函数的调用转换为对 AccountASM构造函数的调用。

//著名的 Hibernate 和 Spring 框架,就是使用这种技术实现了 AOP 的“无损注入”。

//1、首先实现一个 实现一个 methodAdapter 类,用于 修改方法,已经存在AddSecurityCheckMethodAdapter  上例子

//2、再实现一个methodAdapter 类,用于构建新类Account$EnhancedByASM,将其父类指定为 AccountASM

package com.aop;

import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public 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
  }

}

//3、完善AddSecurityCheckClassAdapter 类,控制生产新的类和修改类方法

public class AddSecurityCheckClassAdapter extends ClassAdapter
{

 public String enhancedSuperName;
 public AddSecurityCheckClassAdapter(ClassVisitor cv) {
        //Responsechain 的下一个 ClassVisitor,这里我们将传入 ClassWriter,
        // 负责改写后代码的输出
        super(cv);
    }


 public void visit(final int version, final int access, final String name,
    final String signature, final String superName,
    final String[] interfaces) {
   String enhancedName = name + "$EnhancedByASM";  // 改变类命名
   enhancedSuperName = name; // 改变父类,这里是”Account”
   super.visit(version, access, enhancedName, signature,
   enhancedSuperName, interfaces);
  }


    // 重写 visitMethod,访问到 "operation" 方法时,
    // 给出自定义 MethodVisitor,实际改写方法内容
    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) {
            // 对于 "operation" 方法
            if (name.equals("operation")) {
                // 使用自定义 MethodVisitor,实际改写方法内容
                wrappedMv = new AddSecurityCheckMethodAdapter(mv);
            }
            else if (name.equals("<init>")) {
       wrappedMv = new ChangeToChildConstructorMethodAdapter(mv,
         enhancedSuperName);
       }

        }
        return wrappedMv;
    }

}

//4、新建Generator类,用户获取新生产的类对象

public class Generator {


 private static AccountGeneratorClassLoader classLoader =
        new AccountGeneratorClassLoader();

    private static Class secureAccountClass;

    public static AccountAsm generateSecureAccount() throws Exception {
        if (null == secureAccountClass) {
          ClassReader cr =  new ClassReader("com.aop.AccountAsm");
       ClassWriter cw = new ClassWriter(true);
       ClassAdapter classAdapter = new AddSecurityCheckClassAdapter(cw);
       cr.accept(classAdapter, true);
            byte[] data = cw.toByteArray();
            secureAccountClass = classLoader.defineClassFromClassFile(
               "com.aop.AccountAsm$EnhancedByASM",data);
        }
        return (AccountAsm) secureAccountClass.newInstance();
    }

    private static class AccountGeneratorClassLoader extends ClassLoader {
        public Class defineClassFromClassFile(String className,
            byte[] classFile) throws ClassFormatError {
            return defineClass(className, classFile, 0,
         classFile.length);
        }
    }
}

//5、调用
AccountAsm a=  Generator.generateSecureAccount();
a.operation();

分享到:
评论
3 楼 glmylove 2012-03-16  
baihongsheng 写道
import org.objectweb.asm.ClassWriter
asm-2.0.RC1.jar



我用的3.1的,看来方法已经改变了吧
2 楼 baihongsheng 2012-03-14  
import org.objectweb.asm.ClassWriter
asm-2.0.RC1.jar
1 楼 glmylove 2012-03-13  
ClassWriter cw = new ClassWriter(true);

这段代码我这里老是报错,你用的是哪个Jar包啊

org.objectweb.asm.ClassWriter???

这个类的构造方法是

Constructor Summary
ClassWriter(ClassReader classReader, int flags)
          Constructs a new ClassWriter object and enables optimizations for "mostly add" bytecode transformations.
ClassWriter(int flags)
          Constructs a new ClassWriter object.

只有这两个吧?

相关推荐

    spring aop切面拦截指定类和方法实现流程日志跟踪

    // 在方法执行前执行的操作 } @After("execution(* com.controller.web.*.*(..))") public void after(JoinPoint joinpoint) { // 在方法执行后执行的操作 } @AfterReturning(pointcut = "execution(* ...

    aop:aspect

    在这个例子中,`loggingAspect`是一个切面,引用了名为`loggingService`的bean,该bean包含了三个不同的通知方法,分别在目标方法执行前、执行后返回正常结果时以及执行过程中被调用。 `pointcut`属性定义了通知所...

    AOP 的利器:ASM 3_0 介绍

    AOP 的利器:ASM 3_0 介绍,很好的书

    springboot+aspect实现springaop拦截指定方法.zip

    SpringBoot结合AspectJ实现SpringAOP拦截指定方法的知识点涵盖了多个方面,这包括Spring AOP的基本概念、SpringBoot的应用、切点(Pointcut)与通知(Advice)的定义、自定义注解以及AspectJ的使用。以下是这些知识...

    aop切面拦截单个方法实例

    - 前置通知(Before Advice):在目标方法执行前执行。 - 后置通知(After Advice):在目标方法执行后执行,无论方法是否正常结束。 - 返回后通知(After Returning Advice):在方法正常返回时执行。 - 异常后...

    ASM函数监听实现(三)拦截注入函数的参数值 (函数执行前)

    本篇文章将深入探讨如何使用ASM库来实现函数监听,特别是如何在函数执行前拦截并改变其参数值。 首先,我们需要理解ASM库的基本用法。ASM提供了一套API,可以直接生成或修改字节码。在Java中,每个类都是以字节码...

    spring-aop-5.0.10.RELEASE-API文档-中文版.zip

    赠送jar包:spring-aop-5.0.10.RELEASE.jar; 赠送原API文档:spring-aop-5.0.10.RELEASE-javadoc.jar; 赠送源代码:spring-aop-5.0.10.RELEASE-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.0.10.RELEASE....

    spring AOP拦截方法小示例

    这个“spring AOP拦截方法小示例”是一个实际应用,展示了如何使用Spring AOP来拦截特定层的所有方法,并在调用前后以及出现异常时执行自定义逻辑。 首先,让我们了解AOP的基本概念。AOP的核心是切面(Aspect),它...

    Castle AOP 对类方法调用的拦截示例Deom(可运行)

    在这个"Castle AOP 对类方法调用的拦截示例Demo"中,我们将深入探讨如何使用Castle框架来实现AOP的拦截功能,并且这个示例是可运行的,这意味着你可以直接运行代码来理解其工作原理。 首先,让我们了解一下Castle....

    .net中attribute实现方法调用拦截(就是aop)

    动态代理可以在编译时或运行时创建代理类,这些代理类会包裹目标方法,并在调用目标方法前/后执行额外的逻辑。 描述中提到了`context`,在AOP场景下,通常指的是拦截器执行时上下文信息。这可能包括方法参数、方法...

    AOP 的利器 ASM 3.0

    它可以被用来直接修改`.class`文件,也可以在类加载到Java虚拟机(JVM)前实时改变类的行为。通过使用ASM,开发人员能够轻松地生成新的类或者对现有的类进行增强,这在很多现代框架中都有所应用,比如Hibernate和...

    在自定义spring aop中使用el获取拦截方法的变量值。

    标题中的“在自定义Spring AOP中使用EL获取拦截方法的变量值”指的是在Spring的面向切面编程(AOP)中,通过Expression Language(EL,表达式语言)来访问被拦截方法的局部变量值。这通常涉及到Spring的代理机制、...

    AOP的相关概念

    - **前置通知**:在方法调用前执行。 - **后置通知**:在方法正常返回后执行。 - **异常通知**:在方法抛出异常后执行。 - **最终通知**:无论方法正常返回还是抛出异常都会执行。 - **环绕通知**:方法调用前后都...

    springaop拦截controller日志

    "springaop拦截controller日志"这个主题旨在讲解如何使用Spring AOP来拦截Controller层的方法调用,并在方法执行前后记录相关日志。 首先,了解Spring AOP的基本概念。AOP是一种编程范式,它允许程序员定义“切面”...

    java aop拦截方法类前后添加日志

    本话题聚焦于如何使用Java AOP来在方法执行前后插入日志记录,这有助于提升代码的可读性和可维护性,同时提供运行时的调试信息。 首先,我们需要了解AOP的基本概念。AOP的核心是切面(Aspect),它封装了特定的关注...

    spring aop注解方式、xml方式示例

    Spring AOP(面向切面编程)是Spring框架的重要组成部分,它提供了一种强大的方式来实现横切关注点,如日志、事务管理、性能监控等,而无需侵入业务代码。下面将详细介绍Spring AOP的注解方式和XML配置方式。 ### ...

    spring aop 拦截实例

    - `@Before`:前置通知,在目标方法执行前运行。 - `@After`:最终通知,无论目标方法是否正常结束,都会执行。 - `@AfterReturning`:返回后通知,只有在目标方法正常结束时执行。 - `@AfterThrowing`:异常后...

    cglib-2.2.jar asm-tree.jar asm-commons.jar asm.jar

    在Spring框架中,CGlib被用作AOP(面向切面编程)的底层实现,它可以为一个类创建子类并拦截方法调用。CGlib-2.2.jar是CGlib库的一个特定版本,包含了实现动态代理所需的核心组件。 **ASM** 是一个轻量级的字节码...

    AOP入门------------------实例

    - **通知(Advice)**:在特定的连接点(join point)执行的代码,如方法调用前、后、异常时等。 - **切入点(Pointcut)**:定义了通知将在何处执行,通常是一个表达式,用于匹配连接点。 - **织入(Weaving)**...

Global site tag (gtag.js) - Google Analytics