AOP
基于注解的AOP
结构
动态代理(InvocationHandler):JDK原生的实现方式,需要被代理的目标类必须实现接口。因为这个技术要求代理对象和目标对象实现同样的接口(兄弟两个拜把子模式)
cglib:通过继承被代理的目标类(认干爹模式)实现代理,所以不需要目标类实现接口
AspectJ:本质上是静态代理,将代理逻辑“织入”被代理的目标类编译得到的字节码文件,所以最终效果是动态的。weaver就是织入器。Spring只是借用了AspectJ中的注解
准备
使用基于注解的AOP时,首先需要创建一个切面类
然后组件和切面类上都需要添加@Component等四个注解,此外,切面类上还需要添加@Aspect来将其标记为切面
在IOC配置文件中添加context:component-scan进行扫描
在配置文件中还需要添加<aop:aspectj-autoproxy>,来开启基于注解的aop功能
使用
在切面类中,编写具体的横切关注点,在切入点上添加注解来指定连接点的位置
@Before在执行前
@After相当于finally里面
@AfterReturning在正常执行后
@AfterThrowing相当于catch里面
@Around环绕通知,相当于前四个加起来
注解中必须有切入点表达式
表达式用来指定当前切入点作用于哪个类的那个函数上
@Before("execution(修饰符 返回值 全类名.方法名(参数类型))")
如:@Before("exection(public int com.darkpar.CalculatorImpl.add(int,int)))")
可以使用通配符进行代替,达到匹配多个函数或多个类的目的
如:@Before("exection(* com.darkpar.*.*(..)))")
被通知注解标记的类可以在参数列表添加JointPoint,可以返回连接点的信息
如:
@Before
public void beforeMethod(JoinPoint joinPoint){
Signature signature = joinPoint.getSignature();
Object[] args=joinPoint.getArgs();
String name=signature.getName();
}
对于AfterReturning注解来说可以设置接受返回值的参数名
如:
@AfterReturning(value="pointCut()",returning="result")
public void afterReturningMethod(JoinPoint joinpoint,Object result){
sout(result);
}
对于AfterThrowing注解来说可以设置接受异常的参数名
如:
@AfterThrowing(value="pointCut()",throwing="exception")
public void afterReturningMethod(JoinPoint joinpoint,Throwable exception){
sout(exception);
}
声明切入点表达式来进行切入点重用
@Pointcut("exection(public int com.darkpar.CalculatorImpl.add(int,int)))")
public void pointCut(){}
后面的注解中可以使用这个声明的方法作为value,就能按这个连接点定位了
@Before("pointCut()")
并且其他的切面中也可以共享使用这个切入点
注意
被代理的对象无法通过IOC进行获取,只能通过接口类型来获取代理类的对象
通知执行的顺序跟spring版本有关
5.3之前:
前置通知
目标操作
后置通知
返回或异常通知
5.3之后:
前置通知
目标操作
返回或异常通知
后置通知
环绕通知
和之前写的动态代理类似,自己进行函数的执行并返回结果
@Around("cutPoint")
public Object aroundMethod(ProceedJoinPoint joinPoint){
Object result=null;
try{
BEFORE
result=joinPoint.proceed();
AFTERRETURNING
}catch(Exception){
AFTERTHROWING
}finally{
AFTER
}
return result;
}
切面的优先级
@Order注解可以使用在切面上
注解可以设置切面的优先级,int类型,数字越小优先级越高
基于XML的AOP
不常使用,以注解为主
在切面上不使用AOP相关的注解,在IOC配置文件中配置,
首先还是扫描组件
<context:component-scan base-package="com.darkpar.aop.xml"/>
然后进行aop:config标签的配置
<aop:config>
<aop:pointcut id="pointCut" experssion="exection(* com.darkpar.*.*(..)))">
<aop:aspect ref="loggerAspect" order="1">
<aop:before method="beforeMethod" pointcut-ref="pointCut">
</aop:aspect>
</aop:config>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话