Spring学习(三)
AOP
面向切面编程:Aspect Orient Programming:在不惊动原始设计的基础上增加新的功能
- 连接点:方法的执行,程序执行的任意位置(理解为所有的方法)
- 切入点:一个或多个方法,(这些方法需要新增额外功能
- 通知:共性功能(新的方法,需要附加给切入点
- 通知类:包含通知的类
- 切面:描述通知和切入点的东西
例子
// 1. 定义连接点
@Repository
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println(System.currentTimeMillis());
System.out.println("book dao save...");
}
@Override
public void update() {
System.out.println("book dao update...");
}
}
// 2. 定义通知类和切入点
// 注意
// - 添加Component注解,让Spring生成bean
// - 添加Aspect注解,告知这是个通知类
// - 定义切入点添加Before注解,并附加通知
// - 通知的定义为私有的无返回值无参数的空函数,添加Pointcut注解即可。
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(void zk.dao.BookDao.update())")
private void pt() {}
@Before("pt()")
public void method() {
System.out.println(System.currentTimeMillis());
}
}
AOP工作流程
- Spring容器启动
- 读取所有切面配置中的切入点(没有用的切入点不读取)
- 初始化bean,判定bean的方法是否匹配切入点
- 匹配失败创建对象
- 匹配成功,创建代理对象
- 获取bean,调用方法
AOP切入点表达式
表达式
- 动作关键字 execution,基本不会变
- 访问修饰符:public,private 可以省略
- 返回值
- 包
- 类/接口名
- 方法名
- 参数
- 异常名,可省略
通配符描述
- *单个独立的任意符号
- .. 多个任意连续的符号
- +专用于匹配子类型
技巧
- 切入点同通常描述接口,而不是实现类
- 访问控制修饰符针对接口public,通常省略
- 增删改的返回值使用精准类型加速匹配
- 包名尽量不适用..匹配,通常用*单个包做
- 接口名与模块采用*匹配 getBy*
- 不适用异常作为匹配规则
AOP通知类型
-
before
-
after
-
around
@Component @Aspect public class MyAdvice { @Pointcut("execution(void zk.dao.BookDao.select())") private void pt() {} @Around("pt()") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("1"); Object ret = pjp.proceed(); System.out.println("2"); return ret; } }
-
afterreturning return后执行
-
afterthrowing 抛出异常后执行
AOP通知获取数据
- 获取参数
- 获取返回值
- 获取异常
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(* zk.dao.BookDao.select(..))")
private void pt() {}
public void method() {
System.out.println(System.currentTimeMillis());
}
@Before(value = "pt()")
public void before(JoinPoint jp) {
Object[] args = jp.getArgs();
System.out.println(Arrays.toString(args));
}
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
pjp.getArgs();
System.out.println("1");
Object ret = pjp.proceed();
System.out.println("2");
return ret;
}
}
Spring事务
-
在业务层添加上Spring事务管理
@Transactional
-
设定事务管理器
-
在config添加注解,开启事务
事务角色
- 事务管理员,发起事务的方法
- 事务协调员,加入事务的方法
事务配置
- rollbackFor =
- timeout = -1 永不超时
事务传播行为
协调员加入管理员事务,或者新开一个事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
- REQUIRED 有加入,没有新建
- REQUIRES_NEW 直接新建
- SUPPORTS 有就加,没有就不加
- NOT_SUPPORTS 永远不加事务
- MANDATORY 有就加,没有报错
- NEVER 有事务报错,没有就没事
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通