事务的注解实现

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;
    }
原文地址:https://www.cnblogs.com/pickKnow/p/11143486.html