AOP的理解

面向切面编程

什么是面向切面编程?

简单的将一个方法的前中后作为可切入位置,实现在不动源代码逻辑的情况下实现增强源代码这个就叫做面向切面编程(AOP),他本身是基于面向对象(OOP)实现的,此时最符合场景的设计模式就是代理模式,通过代理去实现横向与源代码的编织,系统最终使用的是代理对象,并不是真正的原对象。

经常需要使用到AOP的场景

  1. 事务控制
  2. 日志收集
  3. 对对象状态的监控
  4. 权限控制
  5. 异常处理
    等等。。。。

AOP的底层实现

静态AOP

说到面向切面编程,其中首先是通过静态代理的方式,最初使用AspectJ来进行实现,通过切点编织以后,会通过特殊的编译器(ajc编译器),将源代码和增强代码写到一个字节码文件中,然后虚拟机可以通过读取字节码文件一样去进行加载,并且不会又任何的性能损失。
缺点:不够灵活,如果需要重新修改AspectJ文件然后编译生成字节码文件。

动态AOP

为了解决上面的缺陷,引入了动态代理(Dynamic Proxy)机制,所有动态的将增强代码编织到源代码中的动态AOP应运而生。其中Spring AOP支持JDK本身自带的动态代理,也可以使用第三方的jar包实现CJLIB动态代理的方式。
JDK动态代理:
如果被代理的类是实现了一个接口,那么Spring AOP会通过JDK的动态代理模式同样去实现同一个接口,通过反射去动态的引入被代理的类中的方法,然后实现InvocationHandler这个接口,在源代码之前,中,后加入增强代码。通过Proxy.newProxyInstance()获取代理对象,实现JDK的动态代理。被动态代理的类与代理类属于兄弟关系。
CJLIB动态代理:
CJLIB动态代理是使用继承被代理类的方式,然后对被代理类的代码进行重写,实现增强,然后让系统使用子类就可以了。但是这个时候又出现一个问题:不能像静态代理那样为每个不同类型的目标对 象都单独创建相应的扩展子类。所以需要CJLIB动态字节码生成库,在系统运行期间动态的创建想用的扩展子类。通过为enhancer指定需要生成的子类对应的父类,以及Callback实现,'enhancer最终为我们生成 了需要的代理对象实例。
具体实现:通过实现MethodInterceptor接口实现其intercept(),然后将实现类通过new Enhancer对象,将Requesttable.class和继承类扔进去,并调用creat()方法创建并强转成Requestable,调用他的request()方法

缺陷:使用CGLIB对类进行扩展的唯一限制就是无法对final方法进行覆写

应用案例

异常处理: 原来这个玩意儿还有个术语叫做Fault barrier(缺陷屏障)
Java中的异常处理: 一般情况下我们处理的异常都是java.lang.error和java.lang.RunTimeException,也就是运行期异常或错误。但是error我们一般管理不了都是Java内部的问题或者硬件的问题。所以RunTimeException是我们需要处理的异常。我们不能让这些异常都散列到系统的各个位置,需要去集中的处理这些异常,通常这些点就被称为横切点(cross-cutting concern),当我们引入ASpectJ的包,其中@AfterThrowing注解就是应用之一。

安全检查: javax.servlet.Filter是Servlet规范为我们提供的一种AOP支持。我们可以通过他在方法执行前进行安全检查。

缓存: 当我们需要将数据在特定的时间加入到缓存中,就可以通过AOP来进行实现。比如说,服务启动时。

AOP扩展

有关公开当前调用的代理对象的探讨:
当我们方法1和方法2在互相的环绕AOP的时候就会产生问题:

 当调用 method1的时候,却只有method1方法的执行拦截成功,而method1方法内部的
 method2方法执行却没 有被拦截,因为输出日志中只有PT in method [method1 ]的信息

分析问题原因:

Spring AOP采用代理 模式实现AOP, 具体的横切逻辑会被添加到动态生成的代理对象中,只要调用的是目标对象的代理对 象上的方法,通常就可以保证目标对象上的方法执行可以被拦截。就像NestableInvocationBO的method2方法执行一样,当我们调用代理对象上的method2的时候,目标对象的method2就会被成功拦 截。
————————————————
版权声明:本文为CSDN博主「xushiyu1996818」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xushiyu1996818/article/details/104088790

解决方案1:通过同开方法2的代理类,实现方法1能够走完,方法2再用代理类拿走方法1,解决循环。具体实现通过声明使用方法2的代理类,使用AopContext.currentProxy(),需要在代理类生成时就将他的ProxyConfig和exposeProxy属性设置为true。
解决方案2: 让IOC来帮我们完成代理类的注入。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值