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工作流程

  1. Spring容器启动
  2. 读取所有切面配置中的切入点(没有用的切入点不读取)
  3. 初始化bean,判定bean的方法是否匹配切入点
    • 匹配失败创建对象
    • 匹配成功,创建代理对象
  4. 获取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 有事务报错,没有就没事
posted @   Destiny233  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示