1、什么是AOP
AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离------Avanade公司的高级方案构架师Adam Magee
正常的业务是具有流程的,代码的运行也是如此,从A类到B类再到C类,从方法a到b再到c,程序运行的过程就像是被穿起来的方法链。而方法本身就像链条上连接的点一样。
日常开发中,以事务处理举例,我们希望程序在调用service方法后进行事务的提交,报错后回滚,如果我们给每个service加上这样的方法,势必会带来大量的改动,这显然是程序编写过程中不希望看到的。于是我们希望产生一种方式可以定义一个切入点,而所有的切入点组合起来就是一个切面,程序就像是被切开,在切开的地方我们可以两头加入想要的额外操作。所以在诸如此类操作,事务、日志、权限认证,等等的催促下,AOP应运而生。
AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。
实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
2、AOP的使用场景
Authentication 权限
Caching 缓存
Context passing 内容传递
Error handling 错误处理
Lazy loading 懒加载
Debugging 调试
logging, tracing, profiling and monitoring 记录跟踪 优化 校准
Performance optimization 性能优化
Persistence 持久化
Resource pooling 资源池
Synchronization 同步
Transactions 事务
3、相关概念
Aspect,切面:一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的 Advisor或拦截器实现。
Joinpoint,连接点:程序执行过程中明确的点,如方法的调用或特定的异常被抛出。
Advice,通知: 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。
Pointcut,切点:指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上。
Introduction,引入:添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口。
Target Object,代理对象:包含连接点的对象。
AOP Proxy,AOP代理:AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
Weaving,织入:组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。
4、Spring AOP的组件
5、如何使用Spring AOP
可以通过配置文件或者编程的方式来使用Spring AOP。
配置可以通过xml文件来进行,大概有四种方式:
1. 配置ProxyFactoryBean,显式地设置advisors, advice, target等
2. 配置AutoProxyCreator,这种方式下,还是如以前一样使用定义的bean,但是从容器中获得的其实已经是代理对象
3. 通过<aop:config>来配置
4. 通过<aop: aspectj-autoproxy>来配置,使用AspectJ的注解来标识通知及切入点
也可以直接使用ProxyFactory来以编程的方式使用Spring AOP,通过ProxyFactory提供的方法可以设置target对象, advisor等相关配置,最终通过 getProxy()方法来获取代理对象
6、Spring AOP代理对象的生成
Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。
我们知道InvocationHandler是JDK动态代理的核心,生成的代理对象的方法调用都会委托到InvocationHandler.invoke()方法。而通过JdkDynamicAopProxy的签名我们可以看到这个类其实也实现了InvocationHandler。
7、面试题
SpringAOP的代理是什么?
Spring AOP是基于代理实现的,默认为标准的 JDK 动态代理。这使得任何接口(或者接口的集合)可以被代理。
Spring AOP 也使用 CGLIB 代理。如果业务对象没有实现任何接口那么默认使用CGLIB
Spring中有哪些通知类型(advice)?
Before(前置通知): 连接点之前执行,除非抛异常,否则没有能力中断执行流(@Before 注解)
After(后置通知): 无论连接点是通过什么方式退出的(正常返回或者抛出异常)都会在结束后执行这些Advice(@After 注解)
After Retuning(返回通知): 在连接点正常结束之后(没有抛出异常正常返回)执行的Advice(@AfterReturning 注解)
After Throwing(异常通知): 如果方法通过抛出异常来退出的话,这个Advice就会被执行(@AfterThrowing 注解)
Around(环绕通知): 围绕连接点执行的Advice,就你一个方法调用(相对于合并前置后置)( @Around 注解)
Spring动态代理是编译期还是运行期织入的?
运行期,生成字节码,再加载到虚拟机中,JDK是利用反射原理,CGLIB使用了ASM原理