zoukankan      html  css  js  c++  java
  • 《四 spring源码》spring的事务注解@Transactional 原理分析

    先了解什么是注解

    注解

    Jdk1.5新增新技术,注解。很多框架为了简化代码,都会提供有些注解。可以理解为插件,是代码级别的插件,在类的方法上写:@XXX,就是在代码上插入了一个插件。

    注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。

    注解分类:内置注解(也成为元注解 jdk 自带注解)自定义注解(Spring框架

    什么内置注解

    1) @SuppressWarnings   再程序前面加上可以在javac编译中去除警告--阶段是SOURCE
    2) @Deprecated   带有标记的包,方法,字段说明其过时----阶段是SOURCE
    3)@Overricle   打上这个标记说明该方法是将父类的方法重写--阶段是SOURCE

    实现自定义注解

    元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:
    @Target

    @Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。

    1. CONSTRUCTOR:用于描述构造器
    2. FIELD:用于描述域
    3. LOCAL_VARIABLE:用于描述局部变量
    4. METHOD:用于描述方法
    5. PACKAGE:用于描述包
    6. PARAMETER:用于描述参数
    7. TYPE:用于描述类、接口(包括注解类型) 或enum声明


    2.@Retention

    表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
    3.@Documented
    4.@interface 

    @Target(value = { ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface AddAnnotation {
    
        int userId() default 0;
    
        String userName() default "默认名称";
    
        String[]arrays();
    }
    反射读取注解信息
        public static void main(String[] args) throws ClassNotFoundException {
            Class classInfo = Class.forName("com.entity.User");
            // 获取到所有方法
            Method[] methods = classInfo.getDeclaredMethods();
            for (Method method : methods) {
                System.out.println(method);
            //查看该方法是否存在注解 AddAnnotation declaredAnnotation
    = method.getDeclaredAnnotation(AddAnnotation.class); if (declaredAnnotation == null) { // 结束本次循环 continue; } // 获取userId int userId = declaredAnnotation.userId(); System.out.println("userId:" + userId); // 获取userName String userName = declaredAnnotation.userName(); System.out.println("userName:" + userName); // 获取arrays String[] arrays = declaredAnnotation.arrays(); for (String str : arrays) { System.out.println("str:" + str); } } }

    自定义事务注解

    //编程事务(需要手动begin 手动回滚  手都提交)
    @Component()
    @Scope("prototype") // 设置成原型解决线程安全
    public class TransactionUtils {
    
        private TransactionStatus transactionStatus;
        // 获取事务源
        @Autowired
        private DataSourceTransactionManager dataSourceTransactionManager;
    
        // 开启事务
        public TransactionStatus begin() {
            transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
            return transactionStatus;
        }
    
        // 提交事务
        public void commit(TransactionStatus transaction) {
            dataSourceTransactionManager.commit(transaction);
        }
    
        // 回滚事务
        public void rollback() {
            System.out.println("rollback");
            dataSourceTransactionManager.rollback(transactionStatus);
        }
    
    }
    
    注解类
    
    @Autowired
        private TransactionUtils transactionUtils;
    
        @AfterThrowing("execution(* com.itmayiedu.service.*.*.*(..))")
        public void afterThrowing() throws NoSuchMethodException, SecurityException {
            // isRollback(proceedingJoinPoint);
            System.out.println("程序发生异常");
            // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            // TransactionStatus currentTransactionStatus =
            // TransactionAspectSupport.currentTransactionStatus();
            // System.out.println("currentTransactionStatus:" +
            // currentTransactionStatus);
            transactionUtils.rollback();
        }
    
        // // 环绕通知 在方法之前和之后处理事情
        @Around("execution(* com.itmayiedu.service.*.*.*(..))")
        public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    
            // 调用方法之前执行
            TransactionStatus transactionStatus = begin(proceedingJoinPoint);
            proceedingJoinPoint.proceed();// 代理调用方法 注意点: 如果调用方法抛出异常不会执行后面代码
            // 调用方法之后执行
            commit(transactionStatus);
        }
    
        public TransactionStatus begin(ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException {
    
            // // 判断是否有自定义事务注解
            ExtTransaction declaredAnnotation = getExtTransaction(pjp);
            if (declaredAnnotation == null) {
                return null;
            }
            // 如果有自定义事务注解,开启事务
            System.out.println("开启事务");
            TransactionStatus transactionStatu = transactionUtils.begin();
            return transactionStatu;
        }
    
        public void commit(TransactionStatus transactionStatu) {
            if (transactionStatu != null) {
                // 提交事务
                System.out.println("提交事务");
                transactionUtils.commit(transactionStatu);
            }
        }
    
        public ExtTransaction getExtTransaction(ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException {
            // 获取方法名称
            String methodName = pjp.getSignature().getName();
            // 获取目标对象
            Class<?> classTarget = pjp.getTarget().getClass();
            // 获取目标对象类型
            Class<?>[] par = ((MethodSignature) pjp.getSignature()).getParameterTypes();
            // 获取目标对象方法
            Method objMethod = classTarget.getMethod(methodName, par);
            // // 判断是否有自定义事务注解
            ExtTransaction declaredAnnotation = objMethod.getDeclaredAnnotation(ExtTransaction.class);
            if (declaredAnnotation == null) {
                System.out.println("您的方法上,没有加入注解!");
                return null;
            }
            return declaredAnnotation;
    
        }
    
        // 回滚事务
        public void isRollback(ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException {
            // // 判断是否有自定义事务注解
            ExtTransaction declaredAnnotation = getExtTransaction(pjp);
            if (declaredAnnotation != null) {
                System.out.println("已经开始回滚事务");
                // 获取当前事务 直接回滚
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return;
            }
        }
    
    使用自定义注解
    
    @ExtTransaction
    public void add() {
    userDao.add("test001", 20);
    int i = 1 / 0;
    System.out.println("################");
    userDao.add("test002", 21);
    }

    Spring事物传播行为

    Spring中事务的定义:

    Propagation(key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。)有以下选项可供使用:

    PROPAGATION_REQUIRED—如果当前有事务,就用当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

    PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。//如果外层方法没有事务,就会以非事务进行执行。

    PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。 

    PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。 

    PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

    --- 如果当前有事务,就是以非事务进行执行

    PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。

    默认传播行为为REQUIRED

  • 相关阅读:
    Mayan游戏 (codevs 1136)题解
    虫食算 (codevs 1064)题解
    靶形数独 (codevs 1174)题解
    黑白棋游戏 (codevs 2743)题解
    神经网络 (codevs 1088) 题解
    The Rotation Game (POJ 2286) 题解
    倒水问题 (codevs 1226) 题解
    银河英雄传说 (codevs 1540) 题解
    生日蛋糕 (codevs 1710) 题解
    第一章 1.11 高阶函数
  • 原文地址:https://www.cnblogs.com/a1304908180/p/10615436.html
Copyright © 2011-2022 走看看