[关闭]
@lzb1096101803 2016-03-18T20:48:48.000000Z 字数 2618 阅读 469

AOP概念,原理

电话面试


AOP

aop是思想层面的
AOP也是为了解耦所诞生。
AOP是一种可以通过预编译和运行期动态代理实现而不用修改源代码的情况下给程序动态添加功能的一种技术。
定义一个切面,在切面的纵向定义处理方法,处理完成之后,回到横向业务流
最常见的就是事务控制。
AOP 主要是利用动态代理模式的技术来实现的。
AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

区别

反射没有用第三方类库。而ASM是第三方类库。
反射最主要的用法是在已有的类上,以动态的方式执行动作。
CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑
反射是读取持久堆上存储的类信息。而 ASM 是直接处理 .class 字节码的小工具(工具虽小,但是功能非常强大!)
反射只能读取类信息,而 ASM 除了读还能写。
反射读取类信息时需要进行类加载处理,而 ASM 则不需要将类加载到内存中。
反射相对于 ASM 来说使用方便,想直接操纵 ASM 的话需要有 JVM 指令基础

ASM

ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类
ASM只不过是通过 “Visitor” 模式将 “.class” 类文件的内容从头到尾扫描一遍。
http://my.oschina.net/u/1166271/blog/162796
联系栈帧的局部变量表和指令
在 Java 中每一个方法在执行的时候 JVM 都会为其分配一个“帧”,帧是用来存储方法中计算所需要的所有数据。其中第 0 个元素就是 “this”,如果方法有参数传入会排在它的后面
ASM 就是让我们直接面对底层字节码。要追求最快的 AOP 执行效率也要从字节码入手。

CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。

java.reflect.InvocationHandler

为什么要实现接口?
动态代理是通过反射来实现的,而且接口不依赖实现,才能体现动态代理的优点啊
当你调用代理类的方法时与你调用被代理类的方法时在写法上是没有任何区别的,只有接口才能保证这种一致性。

一个典型的动态代理创建对象过程可分为以下四个步骤:
1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...);
2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});
3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
为了简化对象创建过程,Proxy类中的newInstance方法封装了2~4,只需两步即可完成代理对象的创建。
生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))

net.sf.cglib.proxy.MethodInterceptor

  1. public class CglibProxy implements MethodInterceptor{
  2. private Enhancer enhancer = new Enhancer();
  3. public Object getProxy(Class clazz){
  4. //设置需要创建子类的类
  5. enhancer.setSuperclass(clazz);
  6. enhancer.setCallback(this);
  7. //通过字节码技术动态创建子类实例
  8. return enhancer.create();
  9. }
  10. //实现MethodInterceptor接口方法
  11. public Object intercept(Object obj, Method method, Object[] args,
  12. MethodProxy proxy) throws Throwable {
  13. System.out.println("前置代理");
  14. //通过代理类调用父类中的方法
  15. Object result = proxy.invokeSuper(obj, args);
  16. System.out.println("后置代理");
  17. return result;
  18. }
  19. }
  1. public class DoCGLib {
  2. public static void main(String[] args) {
  3. CglibProxy proxy = new CglibProxy();
  4. //通过生成子类的方式创建代理类
  5. SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class);
  6. proxyImp.say();
  7. }
  8. }
  1. public class SayHello {
  2. public void say(){
  3. System.out.println("hello everyone");
  4. }
  5. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注