1. 简介
AOP是对面向对象编程OOP的补充和完善,用于处理系统中分布于各个模块的横切关注点,OOP适合定义纵向关系,但是不适合定义横向关系,无法解决减少出现在大多数代码中的日志管理和事务管理的代码的问题。
AOP把软件系统分为了两个部分,核心关注点和横切关注点,业务处理的主要流程是核心关注点,横切关注点发生在核心关注点的各个位置处,包括权限认证、日志、事务管理等 。AOP利用“横切”技术,将影响了多个类的公共行为封装到一个可重用模块中,减少系统的重复代码,降低模块之间的耦合度,有利于未来的可维护性和可操作性。
简易版执行过程
- 生成被代理类的代理对象
- 在代理类的方法上设置拦截器
- 通过拦截器在被拦截方法前后动态添加代码,实现AOP
2. 名词解释
2.1 名词
切点:需要应用切面的地方,即需要拦截的方法
通知:在目标方法前后执行的函数
切面:切点+通知
织入:将切面应用到目标函数的过程
连接点:可以作为切点的方法
2.2 织入方式
静态织入:在编译器织入,AspectJ使用这种方式
动态织入:在运行时动态织入,Spring AOP使用,包括基于反射机制的JDK动态代理和基于继承的CGLIB动态代理两种
2.3 通知的5种类型
before:前置通知,在目标方法执行前执行
after:后置通知,在目标方法执行后通知,一定会执行到
after returning:后置返回通知,在目标方法返回时执行
after throwing:异常通知,在目标方法抛出异常时通知
around:环绕通知,在目标方法执行中执行,可以控制目标方法是否执行
2.4 Spring AOP的通知注解
@Before
@AfterReturning
@AfterThrowing
@After
@Around
3. AOP实现原理
AOP实现的关键在于AOP框架自动创建AOP代理,包括静态代理和动态代理,Spring使用动态代理的方式 。动态代理包括JDK动态代理和CGLIB动态代理,JDK动态代理使用反射接收被代理的类,要求被代理的类必须实现一个接口;如果被代理的类没有实现接口就使用CGLIB动态代理,通过继承的方式实现 。
3.1 JDK动态代理的实现
- 被代理类必须实现已有接口
- JDK提供的Proxy类将通过目标对象的类加载器ClassLoader、Interface和Handler创建与被代理类拥有相同接口的代理对象proxy,proxy拥有所有的接口方法,并实现类似回调函数的接口并重写其invoke方法
- 调用proxy的每个方法时,invoke方法将被调用,因此可在invoke方法中对目标方法前后动态添加代码
3.2 CGLIB动态代理的实现
不需要目标对象拥有接口类,通过继承的方式实现动态代理
- 实现一个方法拦截器接口并重写intercept方法,每次调用代理对象的方法时,intercept方法都会被调用,从而在执行方法前后动态增强
- 代理对象通过Enhancer类创建
4. AOP的应用
权限认证、日志记录、事务控制、性能监控、异常处理等