AOP(Aspect-Oriented Programming: 面向切面编程):
将那些与业务无关,却为业务模块所共同调用的逻辑(例如事务处理、日志管理、权限控制等)封装抽取成一个可重用的模块,这个模块被命名为“切面”(Aspect),便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
Spring AOP 基于动态代理实现:
- 如果被代理的对象,已经实现某个接口,则 Spring AOP 会使用 JDK Proxy(反射),基于接口的方式,创建代理对象(JDK动态代理的核心是InvocationHandler接口和Proxy类);
- 如果被代理的对象,没有实现某个接口,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib,基于继承的方式,生成一个被代理对象的子类来作为代理(Cglib动态代理的核心是MethodInterceptor接口和Enhancer类);
AOP通知类型
AOP将抽取出来的共性功能称为通知;通知类型:以通知在上下文中的具体位置作为划分
- 前置通知(Before advice): 在连接点之前运行但无法阻止执行流程进入连接点的通知(除非它引发异常)。
- 后置返回通知(After returning advice):在连接点正常完成后执行的通知(例如,当方法没有抛出任何异常并正常返回时)。
- 后置异常通知(After throwing advice): 在方法抛出异常退出时执行的通知。
- 后置通知(总会执行)(After (finally) advice): 当连接点退出的时候执行的通知(无论是正常返回还是异常退出)。
- 环绕通知(Around Advice):环绕连接点的通知,例如方法调用。这是最强大的一种通知类型,。环绕通知可以在方法调用前后完成自定义的行为。它可以选择是否继续执行连接点或直接返回自定义的返回值又或抛出异常将执行结束。
- AOP连接点(Join point):AOP将所有的方法都视为连接点,不管是接口里面的抽象方法,还是实现类里面的重写方法,都是连接点
- AOP切点(Pointcut):AOP将可能被抽取共性功能的方法称为切入点。切入点是连接点的子集
- AOP目标对象(Target):就是挖掉功能的方法对应的类生的对象,这种对象是无法直接完成最终工作的
- AOP织入(Weaving):就是将挖掉的功能回填的动态过程
- AOP切面:切点+通知
SpringAOP+AspectJ实现步骤:
1.坐标
2.配置
<!--开启aop配置-->
<aop:config>
<!--切面-->
<aop:aspect id="main" ref="loggerUtil">
<!--切点-->
<aop:pointcut id="dian" expression="execution(* com.apesource.service.ServiceImp.*(..))"/>
<!--前置通知-->
<aop:before method="printLogger" pointcut-ref="dian"></aop:before>
</aop:aspect>
</aop:config>
<aop:config>
<aop:aspect id="main" ref="loggerUtil">
<aop:pointcut id="dian1"
expression="execution(* com.apesource.service.IServiceImp.save(..))"/>
<!--环绕通知-->
<aop:around method="arroundMethod" pointcut-ref="dian1"></aop:around>
</aop:aspect>
</aop:config>
切点表达式配置语法:
execution(修饰符 返回值 包名称.类名称.方法名称(参数列表))
eg: execution(public void com.apesource.service.ServiceImp.findAll())
1.修饰符可以省略代表任意
execution(返回值 包名称.类名称.方法名称(参数列表))
2.返回值可以使用“*”代表任意
execution(* 包名称.类名称.方法名称(参数列表))
3.包名可以使用“*”代表任意名称
execution(* *.*.*.类名称.方法名称(参数列表))
4.包名可以使用“..”代表任意个数
execution(* *...类名称.方法名称(参数列表))
5.类名与方法名可以使用“*”代表任意
execution(* *...*.*(参数列表))
6.参数列表可以使用".."代表任意个数任意类型
execution(* *...*.*(..))
如果有参数
int======>int
String===>java.lang.String
总结AOP开发过程:
开发阶段(开发者完成)===========我们自己做
- 正常的制作程序
- 将非共性功能开发到对应的目标对象类中,并制作成切入点方法
- 将共性功能独立开发出来,制作成“通知”
- 在配置文件中,声明“切入点”
- 在配置文件中,声明"切入点"与"通知"间的关系(含通知类型),即"切面"
运行阶段(AOP完成)=============spring帮我们做的
- Spring容器加载配置文件,监控所有配置的“切入点”方法的执行
- 当监控到“切入点”方法被运行,使用“代理”机制,动态创建“目标对象”的“代理对象”,根据“通知类别”,在“代理对象”的对应位置将“通知”对应的功能“织入”,完成完整的代码逻辑并运行。