spring-aop
即面向切面编程 在oop的基础上横切 加入一些非核心代码
对于aop中动态代理的实现形式:JDK,cglib
- JDK原生的实现方式,需要被代理的目标类必须实现接口。因为这个技术要求代理对象和目标对象实现同样的接口(兄弟两个拜把子模式)
- cglib:通过继承被代理的目标类(认干爹模式)实现代理,所以不需要目标类实现接口
使用AOP技术:在ioc容器中存放的是代理组件
如果目标类有接口,必须使用接口类型接收IoC容器中代理组件
如果目标类没有接口 ,正常使用代理类来接收IoC容器中代理组件
切面类使用步骤如下
- 定义 方法 存储增强代码 具体定义几个 由插入位置决定
- 使用注解配置 指定插入 目标方法的位置
* 前置 @Before
* 返回 @AfterReturning
* 异常 @AfterThrowing
* 后置 @After
* 环绕 @Around - 配置切点表达式 【选中插入的方法 切点 指明切入哪里】
- 补全注解
* 加入 ioc 容器 @Component
* 配置切面 @Aspect =切点 + 增强的部分 - 开启 @Aspect 注解 的支持 在配置类加入注解
//四.配置切面
@Aspect
@Component
@Order(10) //设置切面优先级 数越小 优先级越高
public class LogAdvice {
// 二.使用注解配置 指定插入 目标方法的位置 (前置增强)
@Before("execution(* com..impl.*.*(..))") //三.配置切点表达式 (声明在哪些方法中生效)
//一.定义方法
public void before(JoinPoint joinPoint) {
System.out.println("开始了");
/*
joinPoint.getSignature().getName();获取方法名
int modifiers = joinPoint.getSignature().getModifiers();访问修饰符
Modifier.toString(modifiers); 访问修饰符 数字转字符串
joinPoint.getTarget().getClass().getSimpleName(); 获得对象 -->类对象 --> 简单类名
joinPoint.getArgs(); 参数列表
*/
}
//后置增强
@AfterReturning(value = "execution(* com..impl.*.*(..))",returning ="result") //返回的结果
// 如果想要 获得 返回结果
// 1.在方法中 加参数 (Object result) 接收返回结果
// 2.在注解中加入returning 属性( returning ="result" 指定用那个形参 来接收 返回结果)
public void returnResult(Object result) {
}
//最后增强
@After("execution(* com..impl.*.*(..))")
public void after() {
System.out.println("结束了");
}
//异常增强
@AfterThrowing(value = "execution(* com..impl.*.*(..))",throwing = "throwable") //异常信息
public void err(Throwable throwable) {
System.out.println("出错了");
}
}
开启 @Aspect 注解 的支持 在配置类加入注解
@Configuration
@ComponentScan("com.wind")
@EnableAspectJAutoProxy // 5. 开启 @Aspect 注解 的支持
public class JavaConfig {
}
切点表达式注意事项
在多个方法中书写同一个 切点表达式 为了简化操作 统一管理
创建一个存储切点的类
- 单独维护切点表达式
- 其他类如何引用 : @通知/增强类型("com.wind.pointcut.PointCut.pointCut1()") 类的全限定符号.方法名()
切点表达式语法
@Component
public class PointCut {
// 任何 访问权限符和返回类型中com下的-->任意包-->任意类-->任意方法-->任意参数
@Pointcut("execution(* com..*.*(..))")
public void pointCut1(){}
}
环绕通知的使用
@Component
@Aspect
@Order(20) //设置切面优先级 数越小 优先级越高
public class AroundAdvice {
/**
* 环绕通知 需要在 通知中,定义 目标方法 的执行
* @param joinPoint 目标方法 (获取目标方法信息)
* @return 目标方法的返回值
*/
//声明 环绕通知 注解
@Around("com.wind.pointcut.PointCut.pointCut1()") //引入切点
public Object executionMethod(ProceedingJoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
Object result=null;
try {
// 填入 目标方法 执行前的操作 == @Before
System.out.println("开启事务");
result = joinPoint.proceed(args);//执行目标方法
// 填入 目标方法 执行后 的操作 == @AfterReturning
System.out.println("提交事务");
} catch (Throwable e) {
// 这里异常要抛出
System.out.println("回滚事务");
throw new RuntimeException(e);
}finally {
}
// 返回的结果
return result;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix