一、什么是AOP?
AOP(Aspect Oriented Programming)面向切面:把程序中重复的代码抽取出来,使用动态代理的技术去执行,从而实现不修改源代码对方法进行增强
二、为什么要使用AOP?
AOP的主要优势在于它能够减少代码的重复性,提高代码的模块化和可重用性,降低模块间的耦合度,从而提高软件的整体质量和开发效率。通过将横切关注点从业务逻辑中分离出来,开发者可以更加专注于核心业务的实现,同时保持系统的灵活性和可维护性。
简单来说,AOP 可以减少代码重复,增强模块间独立性,提升代码质量和开发效率。
三、代理模式
代理模式(Proxy Pattern)是一种结构型设计模式,它允许一个对象(即代理)控制对另一个对象(即真实对象)的访问。代理模式的主要目的是提供一个中间层,通过这个中间层可以在不修改原有代码的前提下添加新的功能,如日志记录、权限检查、性能优化等。
举个例子,你是一个古代的小县官。皇帝生日的时候,你需要递上本县的祝福折子。折子不可能让你亲自交到皇帝跟前,所以皇帝会有专门的官员负责整理这些各地的折子。这里的官员就是皇帝的代理人,代理的行为(或者说方法)就是收拢折子和下发赏罚。
而代理模式一般分为静态代理和动态代理。
静态代理:
静态代理中,我们对目标对象的每个方法的增强都是手动完成的,非常不灵活)且麻烦(需要对每个目标类都单独写一个代理类)。
抽象角色(接口):定义公共对外方法。
真实角色(周杰伦):实现抽象角色,定义真实角色所要实现的业务逻辑。
代理角色(代理人):实现抽象角色,是真实角色的代理,通过调用真实角色的方法来完成业务逻辑,并可以附加自己的操作。
抽象角色:
真正角色(周杰伦):
代理角色(经纪人):
测试:
静态代理的缺点
-
代理类和实现类实现了相同的接口,这样就出现了大量的代码重复。
-
代理对象只服务于一种类型的对象。如果要服务多类型的对象,例如代码是只为UserService类的访问提供了代理,但是还要为其他类如DeptService类提供代理的话,就需要我们再次添加代理DeptService的代理类
动态代理:
动态代理允许开发者在不修改原始类的情况下,对原始类的方法进行拦截或增强,从而实现诸如日志记录、权限检查、性能监控等横切关注点的功能。
我们用动态代理来表述周杰伦的代理:
抽象角色:
真正角色(周杰伦):
代理工厂:
测试:
Cglib动态代理
cglib与动态代理最大的区别就是:
使用jdk动态代理的对象必须实现一个接口
使用cglib代理的对象则无需实现接口
真正角色:
代理角色(经纪人):
测试:
四、AOP的核心概念
aop的核心概念有下面8点:
-
连接点(joinpoint)
被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法。
-
切入点(pointcut)
切入点是指我们要对哪些连接点进行拦截的定义
-
通知(advice)
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
-
切面(aspect)
是切入点和通知的结合
-
引介(introduction)
是一种特殊的通知,在不修改代码的前提下,引介可以在运行期为类动态地添加一些方法或字段
-
目标对象(Target)
要代理的目标对象(要增强的类)
-
织入(weave)
将增强应用到目标的过程将advice应用到target的过程
-
代理(Proxy)
一个类被AOP织入增强之后,就产生一个代理类
其中,切入点,通知,切面是及其核心的点:
切点(pointcut):要增强的方法,eg:add()、update()
切点表达式:
格式:execution([修饰符] 返回值类型 包名.类名.方法名(参数))
eg:execution(* com.jy.service.UserServiceImpl.*(..))
execution(* com.jy.service.*.*(..))
换句话说:就是要做事的人!
通知/增强(advice):要搞的事情,eg:日志、事务
前置通知:aop:before
后置通知:aop:after-returning【try】
异常通知:aop:after-throwing【catch】
环绕通知:aop:around
最终通知:aop:after【finally】
try{
....
aop:after-returning
}catch(Exception e){
aop:after-throwing
}finally{
aop:after
}
换句话说,就是人要干的事。
切面(aspect):把增强应用到切点上
人完成要干的事的这一行为,就是切面。
五、基于xml的aop配置
pom.xml:
dao:
service:
web:
applicationContext.xml:
六、spring基于注解的AOP配置
-
常用注解
-
@Aspect:把当前类声明为切面类
-
@Before:前置通知,可以指定切入点表达式
-
@AfterReturning:后置【try】通知,可以指定切入点表达式
-
@AfterThrowing:异常【catch】通知,可以指定切入点表达式
-
@After:最终【finally】通知,可以指定切入点表达式
-
@Around:环绕通知,可以指定切入点表达式
-
-
注解方式实现aop