zoukankan      html  css  js  c++  java
  • 事务的注解实现

    https://www.cnblogs.com/pickKnow/p/11138118.html

    在这一篇博客中,已经通过AOP 思想了事务的功能,通过环绕通知,以及异常通知,实现能够在指定的方法前后调用开启事务,提交事务,回滚事务的功能。

    在Spring中,已经通过注解@Transactional 实现了这一功能,具体spring.xml如下:

    <!-- 配置事务 -->
        <bean id="dataSourceTransactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
       
    <!-- 开启事务 -->
    <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>

    代码上只需在方法上加上:@Transactional

        @Transactional
        public void addUser() {
            // 添加到数据库
            System.out.println("开始添加");
            userDao.add(1, "tom", "12");
            int i = 1 / 0;
        }

    2,注解

    分类:内置注解(也成为元注解 jdk 自带注解)、自定义注解(Spring框架)
    什么是内置注解
    (1) @SuppressWarnings   再程序前面加上可以在javac编译中去除警告--阶段是SOURCE
    (2) @Deprecated   带有标记的包,方法,字段说明其过时----阶段是SOURCE
    (3)@Overricle   打上这个标记说明该方法是将父类的方法重写--阶段是SOURCE
    @Overricle 案例演示
    @Override
    public String toString() {
    return null;
    }
    @Deprecated案例演示
    new Date().parse("");

    @SuppressWarnings  案例演示
    @SuppressWarnings({ "all" })
    public void save() {
    java.util.List list = new ArrayList();
    }


    实现自定义注解
    元注解的作用就是负责注解其他注解。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.@Inherited

    实现一个注解:

    @Target({ElementType.METHOD})   //范围
    @Retention(RetentionPolicy.RUNTIME)  //运行时候   要加 反射需要用到
    @Inherited
    @Documented
    public @interface User {
        String username() default "tom";
    
        int age() default 18;
    
        String[] arrays();
    }
    public class App {
    
        @User(username = "Jim", arrays = { "basketball" }, age = 20)
        public void addUser() {
            System.out.println("Annotation");
        }
    
        public static void main(String[] args) throws ClassNotFoundException {
            // 获取到class信息
            Class<?> clazz = Class.forName("com.hella.thread.annotation.App");
            // 获取方法
            Method[] methods = clazz.getDeclaredMethods();
            // 循环遍历每个方法上@User 的注解
            for (Method method : methods) {
                User annotation = method.getDeclaredAnnotation(User.class);
                if (annotation != null) {
                    System.out.println(annotation.age());
                    System.out.println(annotation.username());
                }
            }
        }
    
    }

    3,通过自定义注解来实现@Transactional 的功能

    1,自定义注解

    @Target({ ElementType.METHOD }) // 范围
    @Retention(RetentionPolicy.RUNTIME) // 运行时候 要加 反射需要用到
    @Inherited
    @Documented
    public @interface DefTransactional {
    
    }

    2,通过AOP 在每个方法调用前通过反射区获取方法上是否有指定的自定义注解,如果有开启事务,异常回滚事务

    Component
    @Aspect // 这是一个切面类,用来监测方法的调用,调用前判断是有@DefTransactional 注解
    @Scope("prototype") // 保证事务的隔离性,让每个对象都是一个新的对象,保证线程安全
    public class AopDefTransactional {
    
        @Autowired
        private TransactionUtils transactionUtils;
    
        // 环绕通知
        @Around("execution (* com.hella.thread.aoptransaction.service.UserService.*(..) )")
        public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            // 1 找到对应的方法,通过方法名和参数类型 因为会有重载
            TransactionStatus transactionStatus = begin(proceedingJoinPoint);
            proceedingJoinPoint.proceed();
            // 4 提交事务
            commit(transactionStatus);
        }
    
        // 异常通知
        @AfterThrowing("execution (* com.hella.thread.aoptransaction.service.UserService.addUser(..) )")
        public void afterThrowing() {
            System.out.println("####自定义注解事务回滚");
            transactionUtils.rollback();
        }
    
        private void commit(TransactionStatus transactionStatus) {
            if (transactionStatus != null) {
                // 提交事务
                System.out.println("####自定义注解事务提交");
                transactionUtils.commit(transactionStatus);
            }
        }
    
        private TransactionStatus begin(ProceedingJoinPoint proceedingJoinPoint)
                throws NoSuchMethodException, SecurityException {
            DefTransactional annotation = findMethodByProceedingJoinPoint(proceedingJoinPoint);
            if (annotation == null) {
                // 开启事务
                System.out.println("方法上没有注解");
                return null;
            }
            System.out.println("####自定义注解事务开启");
            TransactionStatus transactionStatus = transactionUtils.begin();
            return transactionStatus;
        }
    
        private DefTransactional findMethodByProceedingJoinPoint(ProceedingJoinPoint proceedingJoinPoint)
                throws NoSuchMethodException, SecurityException {
            // 获取到字节码信息
            Class<?> clazz = proceedingJoinPoint.getTarget().getClass();
            // 获取到方法名称
            String methodName = proceedingJoinPoint.getSignature().getName();
            // 获取参数
            Class<?>[] par = ((MethodSignature) proceedingJoinPoint.getSignature()).getParameterTypes();
            // 获取到正在执行的方法
            Method method = clazz.getDeclaredMethod(methodName, par);
    
            DefTransactional annotation = method.getDeclaredAnnotation(DefTransactional.class);
    
            if (annotation == null) {
                System.out.println("没有注解");
                return null;
            }
    
            return annotation;
        }
    
    }

    最后在方法上添加事务

    @DefTransactional
        public void addUser() {
            // 添加到数据库
            System.out.println("开始添加");
            userDao.add(1, "tom", "12");
            int i = 1/0;
        }
  • 相关阅读:
    Leetcode 50.Pow(x,n) By Python
    Leetcode 347.前K个高频元素 By Python
    Leetcode 414.Fizz Buzz By Python
    Leetcode 237.删除链表中的节点 By Python
    Leetcode 20.有效的括号 By Python
    Leetcode 70.爬楼梯 By Python
    Leetcode 190.颠倒二进制位 By Python
    团体程序设计天梯赛 L1-034. 点赞
    Wannafly挑战赛9 C-列一列
    TZOJ Start
  • 原文地址:https://www.cnblogs.com/pickKnow/p/11143486.html
Copyright © 2011-2022 走看看