你真的懂AOP吗?

1 AOP概念
spring

AOP(Aspect Oriented Programming) 面向切面编程,是OOP(Object Oriented Programming,面向对象编程)的补充和完善。AOP技术利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,即切面。所谓"切面"可减小系统的重复代码,下降模块之间的耦合度 ,并有利于将来的可操做性和可维护性。横切关注点常常发生在核心关注点的多处,且各处基本类似,好比权限认证、日志、事物。编程


2 代理设计模式设计模式

要想明白aop实现原理,必定要掌握代理模式,其中代理模式的定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用。下面是代理模式的简单类图与调用过程。bash


3 代理实现技术
app

Java编程中的实现代理模式分为静态代理、动态代理两种,静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就肯定了,而动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪个对象,这就须要代码具有能动态建立一个类的能力。首先,咱们先温习下Java从编译到运行的整个过程,编译Java文件以后产生.class 文件在磁盘中, JVM虚拟机读取字节码文件,取出二进制数据加载到内存中,解析.class 文件内的信息,生成对应的 Class对象,而后再实例化的过程的例子。那么,若是咱们在运行期系统中遵循Java1编译系统组织.class文件的格式和结构,生成相应的二进制数据,而后再把这个二进制数据加载转换成对应的类,这样就具备了在代码中动态建立一个类的能力。

采用JDK自带的Proxy类方法,其基本流程为:主函数-->代理-->目标对象。对于Proxy类(被代理类)有一个使用前提:目标对象必需要实现接口,利用Proxy实现AOP的主要步骤以下:建立接口->建立接口实现类->建立代理工厂类。经过查看生成的代理类的字节码文件能够看到,生成的代理类是继承了Proxy主类和实现了指定的Dao接口,在初始化的时候将会加载被代理类的方法生成Method对象,Proxy父类中保存了实际处理的invoke方法, 因此外部调用代理类定义的方法时,Method元数据与方法参数都将会转发到方法代理类的定义好的invoke方法中。
// 1.首先实现一个InvocationHandler,方法调用会被转发到该类的invoke()方法
public class DaoInvocationHandler implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)  {
       return method.invoke(object, args);
    }
}
//2.而后在须要使用Dao的时候,经过JDK动态代理获取Dao的代理对象
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); //开启debug模式,保存动态生成的代理类字节码文件
Dao dao = new DaoImpl();
Dao proxyDao = (Dao) Proxy.newProxyInstance(
getClass().getClassLoader(),// 1. 类加载器
        new Class[]{Dao.class}, // 2. 代理须要实现的接口,能够有多个
        new DaoInvocationHandler(dao));// 3. 方法调用的实际处理者
复制代码



Cglib(Code Generation Library)是一个优秀的动态代理框架,是一个强大的,高性能的,高质量的Code生成类库,能够在运行期扩展Java类与实现Java接口。它的底层使用ASM在内存中动态的生成被代理类的子类,使用CGLIB即便代理类没有实现任何接口也能够实现动态代理功能。CGLIB具备简单易用的特色,它的运行速度要远远快于JDK的Proxy动态代理。asm.jar–CGLIB的底层实现,cglib.jar – CGLIB的核心jar包。CGLIB的核心类:
net.sf.cglib.proxy.Enhancer–主要的加强类
net.sf.cglib.proxy.MethodIntercepto –主要的方法拦截类,它是Callback接口的子接口,须要用户实现
net.sf.cglib.proxy.MethodProxy–JDK的Java.lang.reflect.Method类的代理类,能够方便的实现对源对象方法的调用;
实现AOP功能步骤以下所示:引入相关jar文件->建立实体类->建立CGLib代理类->建立入口类进行测试。
// 1. 首先实现一个MethodInterceptor,方法调用会被转发到该类的intercept()方法。
class DaoMethodInterceptor implements MethodInterceptor{
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy).{
        return proxy.invokeSuper(obj, args);
    }
}
// 2. 而后在须要使用HelloConcrete的时候,经过CGLIB动态代理获取代理对象。
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./$DaoProxy.class");
Enhancer enhancer = new Enhancer(); //1.新建代理加强对象
enhancer.setSuperclass(DaoImpl.class); //2.设置被代理类
enhancer.setCallback(new DaoMethodInterceptor());  //3.插入方法拦截对象
Dao dao = (DaoImpl)enhancer.create(); //4.获取被代理对象
复制代码

经过查看生成的代理类的字节码文件能够看到,cglib生成了三个类,有兴趣的能够自行了解一下cglib的机制。生成的代理类是经过继承被代理类实现的,因此须要指定父类。在初始化的时候也同样会加载被代理类的方法生成Method对象,因此外部调用代理类定义方法时,会先去执行拦截方法而后才是真正的被代理类的方法。框架

4.总结
ide

本篇介绍了AOP的概念,代理的设计模式与实现技术,使用了jdk proxy与cglib的接口用来作些简单的代理实现并分析了原理,格物而致知,积小步而致千里。函数

下一期咱们将模拟spring-aop的实现,手撸个小型的aop框架出来。敬请期待!性能






相关文章
相关标签/搜索