前段时间去面试,被问到了AOP的原理,当时回答是通过代理,还自信满满的。原来还是存在其他的一些方法的。趁这段时间,离职之际冲冲电,稍微挖一下。
package demo.aop;
public interface ActionI {
public void doSth();
}
package demo.aop;
public class ActionImpl implements ActionI {
@Override
public void doSth() {
System.out.println("doing sth");
}
}
1.通过装饰器方法
package demo.aop;
public class ActionDecorator implements ActionI {
private ActionI action;
public ActionDecorator(ActionI action) {
this.action = action;
}
@Override
public void doSth() {
System.out.println("doSth invoke start");
action.doSth();
System.out.println("doSth invoke end");
}
public static void main(String[] args) {
ActionI action = new ActionDecorator(new ActionImpl());
action.doSth();
}
}
输出:
doSth invoke start
doing sth
doSth invoke end
使用装饰器的时候,如果要切入多个方法的时候,装饰器内就需要手懂编写同样多个方法。这种方法是显然是不够动态和灵活的。
2.使用Proxy代理
package demo.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ActionInvocationHandler implements InvocationHandler {
private ActionI action;
public ActionInvocationHandler(ActionI action){
this.action = action;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Log.info(method.getName()+" start");
method.invoke(action, args);
Log.info(method.getName()+" end");
return null;
}
public static void main(String[] args){
ActionI action = (ActionI)Proxy.newProxyInstance(ActionI.class.getClassLoader(), new Class[] { ActionI.class },
new ActionInvocationHandler(new ActionImpl()));
action.doSth();
}
}
输出
doSth start
doing sth
doSth end
不足之处在于:代理是面向接口的,代理的对象必须是对一个接口的实现。代理是通过反射机制实现的,效率不高。
相较以上两种方法,改变java方法的更直接的方法是修改字节码
Java 规范详细说明了 class 文件的格式,直接编辑字节码确实可以改变 Java 类的行为。
3.hook
启动时往 Java 虚拟机中挂上一个用户定义的 hook 程序,可以在装入特定类的时候改变特定类的字节码,从而改变该类的行为。但是其缺点也是明显的:
Instrument 包是在整个虚拟机上挂了一个钩子程序,每次装入一个新类的时候,都必须执行一遍这段程序,即使这个类不需要改变。
直接改变字节码事实上类似于直接改写 class 文件,无论是调用 ClassFileTransformer. transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer),还是 Instrument.redefineClasses(ClassDefinition[] definitions),都必须提供新 Java 类的字节码。也就是说,同直接改写 class 文件一样,使用 Instrument 也必须了解想改造的方法相对类首部的偏移量,才能在适当的位置上插入新的代码。
尽管 Instrument 可以改造类,但事实上,Instrument 更适用于监控和控制虚拟机的行为。
4.asm
Java 字节码操控框架,能动态生成类或者增强既有类的功能。
分享到:
相关推荐
【Spring AOP实现方法大全】 在Spring框架中,面向切面编程(Aspect-Oriented Programming,简称AOP)是一种强大的设计模式,它允许我们在不修改业务代码的情况下,插入额外的功能,比如日志记录、事务管理等。在...
7. **示例中的`boot-aspect`项目**:这个文件名可能指的是项目的一个模块或目录,它包含了SpringBoot应用的AOP实现。在这个模块中,我们可以找到配置文件(如`application.yml`或`application.properties`)、Spring...
在使用反射实现AOP动态代理时,我们也需要注意一些问题。例如,由于代理类是在运行时动态创建的,这可能会影响程序的性能,特别是在频繁调用代理方法的情况下。因此,在实际开发中,需要根据应用场景的性能要求和...
在C#中,实现AOP的方法多种多样,以下将详细介绍几种常见的实现方式。 1. **静态织入**: 静态织入是在编译时完成的,它通过编译器或者编译插件(如PostSharp)在目标类的代码中插入拦截逻辑。这种方式的优点是...
二、AOP实现方式 1. 静态代理:通过Java反射API或者自定义接口实现,缺点是需要为每个目标类手动创建代理类。 2. 动态代理:Java提供两种动态代理方式,JDK动态代理和CGLIB代理。 - JDK动态代理:基于接口实现,...
代码实现简单,易于维护:使用 Spring AOP 可以将耗时监测的逻辑与业务逻辑进行解耦,避免业务逻辑代码的冗余和代码维护难度的提高。 2. 安全性高:使用 Spring AOP 进行方法耗时监测,可以在不修改业务逻辑代码的...
在net core2.2时,我当时就尝试过用autofac实现aop,但这次我不想用autofac,我用了一个更轻量级的框架,AspectCore。 用起来非常非常的简单,但一开始还是走了一点弯路,主要是网上都是net core3以下的教程,3以下...
在Spring AOP中,`Proxy`类会根据目标对象的接口生成一个代理类,这个代理类会实现目标对象的所有接口,并在每个方法调用前后插入相应的通知。`InvocationHandler`接口定义了一个`invoke`方法,当调用代理对象的方法...
本篇文章将深入探讨Spring AOP的内部实现,以及如何通过源代码理解其DataSource实现和FactoryBean模式。 首先,让我们了解AOP的基本概念。AOP的核心思想是“切面”,它封装了特定的关注点,如日志记录、事务管理、...
下面我们将深入探讨.NET平台AOP的实现方法和应用。 首先,我们需要理解AOP的基本概念。AOP的核心是切面(Aspect),它封装了横切关注点,即那些影响多个类或操作的代码。切点(Join Point)是指程序执行过程中的特...
本节将详细介绍如何使用Spring AOP实现流程日志跟踪,主要关注于如何通过AOP拦截特定的类和方法来进行日志记录。 ##### 3.1 配置Spring AOP 在Spring配置文件中定义切面和切入点表达式是非常关键的一步。一般来说...
Spring AOP是Java环境中最广泛使用的AOP实现,它支持基于注解和XML配置的切面定义。通过`@Aspect`注解,我们可以创建切面类,使用`@Before`, `@After`, `@Around`等注解定义通知,并使用`@Pointcut`定义切入点。 ...
- 代理对象在调用实际方法前后,会插入相应的通知代码,从而实现AOP功能。 - **CGLIB代理**: - 如果目标对象没有实现任何接口,Spring会使用CGLIB库创建一个目标对象的子类,并在子类中插入通知代码。 - CGLIB...
AOP实现机制有多种,主要包括静态AOP、动态代理、动态字节码生成、自定义类加载器和字节码转换等。 1. 静态织入:在编译期通过修改源代码或字节码实现AOP。这种方式对系统性能无影响,但灵活性不够。 2. 动态代理...
在本项目中,我们将探讨如何通过配置文件实现Spring AOP,包括前置通知、后置通知以及拦截器的运用。 首先,我们需要理解Spring AOP的核心概念。切面(Aspect)是关注点的模块化,这些关注点定义了跨越多个对象的...
Spring的AOP代理(无论是JDK还是CGLIB)都会实现这个接口,并在intercept()方法中插入通知逻辑。 此外,Spring还提供了基于注解的AOP支持,如@Aspect、@Before、@After等,这使得AOP的使用更加便捷。在编译时,...
在提供的压缩包文件"aop实现"中,可能包含了具体的代码示例和文章,详细讲解了如何使用Attribute实现AOP。通过学习这些资料,你可以更深入地理解Attribute的高级应用,以及如何在.NET环境中实现方法调用的拦截。
Spring AOP实现方法之一:CGLIB 实现AOP功能
redis分布式锁的实现: ... 3、只需要在方法上声明@DistributedLock(可以是controller的方法也可以是service的公共方法)即可实现锁功能。 4、支持在@DistributedLock上动态传参,减少锁的颗粒度。