整体感官
java中的继承,就像是纵向拓展,可以通过继承父类的方法,再加上子类特有的方法实现功能的增加,与代码的复用。
AOP就像是横向拓展,横向剖开,将一些影响到多个类的方法(日志输出),封装到一个可重用的对象里。
AOP的计算作用在于,将业务与系统服务分离,使得开发业务代码时不用每次都聚焦系统服务的实现。
实现方式与原理
静态织入实现AOP
引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
AspectJ是静态代理的增强,所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,他会在编译阶段将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。
如何基于AspectJ实现静态代理?
导入AspectJ的包,用@Aspect注解声明切面类,用@Before,@AfterReturning等注解声明增强方法以及方法作用的类。在配置文件里设置AspectJ自动解析,最后通过配置文件生成ApplicationContext,用IOC的方式获取到的就是增强之后的对象。
动态代理实现AOP
动态代理中(无论是jdk还是cglib),代理类对 target 对象的方法进行拦截,其实都是通过让代理类持有 target 对象的引用,当外部引用aop包围的方法时,调用的其实是代理类对应的方法,代理类持有target对象,便可以控制target方法执行时的全方位拦截。
①JDK动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。
②如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。