1. 什么是AOP
AOP(Aspect Oriented Programming)面向切面编程,首先它是一种设计思想,其次,它是对OOP面向对象编程的补充,它提供了模块化。在OOP中,关键单元是对象,AOP的关键单元是切面,或者说关注点。
可以简单的理解为,OOP是针对核心的集中业务,AOP是针对非核心的分散的切面业务,例如事务管理、权限、日志、安全等。
2. AOP的核心理念
AOP底层是基于代理机制实现功能的扩展:
1)假如目标对象(被代理对象)实现接口,则底层可以采用JDK动态代理机制为目标对象创建代理对象(目标类和代理类会实现共同接口)。
2)加入目标对象没有实现接口,则底层可以采用CGLIB代理机制为目标对象创建代理对象(默认创建的代理类会基础目标对象类型)。
个人的经验:
AOP也可以解决业务的调用问题,当业务需要多次被调用时,会出现代码耦合度高、代码冗余的情况。那么有必要针对业务的多次操作,进行业务的封装处理,降低代码的冗余。例如,针对数据的缓存操作,可以采用AOP的方式进行。
3.AOP代理方式的实现
3.1基于JDK代理方式
3.2 基于CGLIB代理方式
4. 切入点表达式
1). bean(bean的ID) 按照指定的bean名称拦截用户的请求,之后执行通知方法. 只能匹配单个bean对象;
bean表达式(重点)一般应用于类级别,实现粗粒度的切入点定义,例:
- bean(“userServiceImpl”)指定一个userServiceImpl类中所有方法。
- bean("*ServiceImpl")指定所有后缀为ServiceImpl的类中所有方法。
2).within(包名.类名) 可以按照类通配的方式去拦截用户的请求.;
within表达式(了解)应用于类级别,实现粗粒度的切入点表达式定义,例:
- within(“aop.service.UserServiceImpl”)指定当前包中这个类内部的所有方法。
- within(“aop.service.*”) 指定当前目录下的所有类的所有方法。
- within(“aop.service…*”)指定当前目录以及子目录中类的所有方法。
3).execution表达式(了解)应用于方法级别,实现细粒度的切入点表达式定义,例:
- 语法:execution(返回值类型 包名.类名.方法名(参数列表))。
- execution(void aop.service.UserServiceImpl.addUser())匹配addUser方法。
- execution(void aop.service.PersonServiceImpl.addUser(String))方法参数必须为String的addUser方法。
- execution(* aop.service….(…)) 万能配置。
4).@annotation(包名.注解名称) 按照注解的方式去拦截用户请求.
@annotaion表达式(重点)应用于方法级别,实现细粒度的切入点表达式定义,例:
- @annotation(anno.RequiredLog) 匹配有此注解描述的方法。
- @annotation(anno.RequiredCache) 匹配有此注解描述的方法。
5. 通知方法
1.前置通知(Before Advice): 主要在 目标方法执行之前执行
2.后置通知(After Advice): 在目标方法执行之后执行
3.异常通知(After Throwing Advice): 在目标方法执行的过程中报了异常之后执行.
4.返回之后通知(After Retuning Advice): 在连接点正常结束之后执行.
上述的通知方法,无法控制目标方法是否执行.所以一般"只做记录不做改变"
5.环绕通知(Around Advice): 一般采用环绕通知 实现对业务的控制.
通知执行顺序,如图:
6.连接点(Joint Point)和切入点(Point cut)是什么?
1.连接点是程序执行的一个点。一个连接点总是代表一个方法执行,例如一个方法的执行或者一个异常的处理。
2.切入点是一个匹配连接点的断言或者表达式。Advice与切入点表达式相关联,并在切入点匹配的任何连接点处运行。由切入点表达式匹配的连接点的概念是AOP的核心。Spring默认使用AspectJ切入点表达式语言。
7. 面试小知识
面试官一问:是编译时期进行织入,还是运行期进行织入?
---->运行期,生成字节码,再加载到虚拟机中,JDK是利用反射原理,CGLIB使用了ASM原理。
面试官再问:初始化时期织入还是获取对象时织入?
----》初始化的时候,已经将目标对象进行代理,放入到spring 容器中
面试官再再问:spring AOP 默认使用jdk动态代理还是cglib?
-----》要看条件,如果实现了接口的类,是使用jdk。如果没实现接口,就使用cglib。
面试官问:spring AOP 和 AspectJ的关系?
1、两者都是为了实现AOP这个目的,而出现的技术,spring aop 参考 AspectJ编程风格
—》这里有个故事就是,原本spring aop 初期的时候所用的编程风格,让人用起来,很不方便,而且让人看不懂。后来,spring aop 就开始取用了Aspectj的编程风格去进行编程