先了解什么是注解

注解

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

  1. @Target(value = { ElementType.METHOD })
  2. @Retention(RetentionPolicy.RUNTIME)
  3. public @interface AddAnnotation {
  4.  
  5. int userId() default 0;
  6.  
  7. String userName() default "默认名称";
  8.  
  9. String[]arrays();
  10. }
  11. 反射读取注解信息
  12. public static void main(String[] args) throws ClassNotFoundException {
  13. Class classInfo = Class.forName("com.entity.User");
  14. // 获取到所有方法
  15. Method[] methods = classInfo.getDeclaredMethods();
  16. for (Method method : methods) {
  17. System.out.println(method);
            //查看该方法是否存在注解
  18. AddAnnotation declaredAnnotation = method.getDeclaredAnnotation(AddAnnotation.class);
  19. if (declaredAnnotation == null) {
  20. // 结束本次循环
  21. continue;
  22. }
  23. // 获取userId
  24. int userId = declaredAnnotation.userId();
  25. System.out.println("userId:" + userId);
  26. // 获取userName
  27. String userName = declaredAnnotation.userName();
  28. System.out.println("userName:" + userName);
  29. // 获取arrays
  30. String[] arrays = declaredAnnotation.arrays();
  31. for (String str : arrays) {
  32. System.out.println("str:" + str);
  33. }
  34. }
  35. }

自定义事务注解

  1. //编程事务(需要手动begin 手动回滚 手都提交)
  2. @Component()
  3. @Scope("prototype") // 设置成原型解决线程安全
  4. public class TransactionUtils {
  5.  
  6. private TransactionStatus transactionStatus;
  7. // 获取事务源
  8. @Autowired
  9. private DataSourceTransactionManager dataSourceTransactionManager;
  10.  
  11. // 开启事务
  12. public TransactionStatus begin() {
  13. transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
  14. return transactionStatus;
  15. }
  16.  
  17. // 提交事务
  18. public void commit(TransactionStatus transaction) {
  19. dataSourceTransactionManager.commit(transaction);
  20. }
  21.  
  22. // 回滚事务
  23. public void rollback() {
  24. System.out.println("rollback");
  25. dataSourceTransactionManager.rollback(transactionStatus);
  26. }
  27.  
  28. }
  29.  
  30. 注解类
  31.  
  32. @Autowired
  33. private TransactionUtils transactionUtils;
  34.  
  35. @AfterThrowing("execution(* com.itmayiedu.service.*.*.*(..))")
  36. public void afterThrowing() throws NoSuchMethodException, SecurityException {
  37. // isRollback(proceedingJoinPoint);
  38. System.out.println("程序发生异常");
  39. // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  40. // TransactionStatus currentTransactionStatus =
  41. // TransactionAspectSupport.currentTransactionStatus();
  42. // System.out.println("currentTransactionStatus:" +
  43. // currentTransactionStatus);
  44. transactionUtils.rollback();
  45. }
  46.  
  47. // // 环绕通知 在方法之前和之后处理事情
  48. @Around("execution(* com.itmayiedu.service.*.*.*(..))")
  49. public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
  50.  
  51. // 调用方法之前执行
  52. TransactionStatus transactionStatus = begin(proceedingJoinPoint);
  53. proceedingJoinPoint.proceed();// 代理调用方法 注意点: 如果调用方法抛出异常不会执行后面代码
  54. // 调用方法之后执行
  55. commit(transactionStatus);
  56. }
  57.  
  58. public TransactionStatus begin(ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException {
  59.  
  60. // // 判断是否有自定义事务注解
  61. ExtTransaction declaredAnnotation = getExtTransaction(pjp);
  62. if (declaredAnnotation == null) {
  63. return null;
  64. }
  65. // 如果有自定义事务注解,开启事务
  66. System.out.println("开启事务");
  67. TransactionStatus transactionStatu = transactionUtils.begin();
  68. return transactionStatu;
  69. }
  70.  
  71. public void commit(TransactionStatus transactionStatu) {
  72. if (transactionStatu != null) {
  73. // 提交事务
  74. System.out.println("提交事务");
  75. transactionUtils.commit(transactionStatu);
  76. }
  77. }
  78.  
  79. public ExtTransaction getExtTransaction(ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException {
  80. // 获取方法名称
  81. String methodName = pjp.getSignature().getName();
  82. // 获取目标对象
  83. Class<?> classTarget = pjp.getTarget().getClass();
  84. // 获取目标对象类型
  85. Class<?>[] par = ((MethodSignature) pjp.getSignature()).getParameterTypes();
  86. // 获取目标对象方法
  87. Method objMethod = classTarget.getMethod(methodName, par);
  88. // // 判断是否有自定义事务注解
  89. ExtTransaction declaredAnnotation = objMethod.getDeclaredAnnotation(ExtTransaction.class);
  90. if (declaredAnnotation == null) {
  91. System.out.println("您的方法上,没有加入注解!");
  92. return null;
  93. }
  94. return declaredAnnotation;
  95.  
  96. }
  97.  
  98. // 回滚事务
  99. public void isRollback(ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException {
  100. // // 判断是否有自定义事务注解
  101. ExtTransaction declaredAnnotation = getExtTransaction(pjp);
  102. if (declaredAnnotation != null) {
  103. System.out.println("已经开始回滚事务");
  104. // 获取当前事务 直接回滚
  105. TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  106. return;
  107. }
  108. }
  109.  
  110. 使用自定义注解
  111.  
  112. @ExtTransaction
  113. public void add() {
  114. userDao.add("test001", 20);
  115. int i = 1 / 0;
  116. System.out.println("################");
  117. userDao.add("test002", 21);
  118. }

Spring事物传播行为

Spring中事务的定义:

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

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

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

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

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

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

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

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

默认传播行为为REQUIRED

《四 spring源码》spring的事务注解@Transactional 原理分析的更多相关文章

  1. Spring源码情操陶冶-AnnotationConfigBeanDefinitionParser注解配置解析器

    本文承接前文Spring源码情操陶冶-自定义节点的解析,分析spring中的context:annotation-config节点如何被解析 源码概览 对BeanDefinitionParser接口的 ...

  2. Spring源码情操陶冶-PropertyPlaceholderBeanDefinitionParser注解配置解析器

    本文针对spring配置的context:property-placeholder作下简单的分析,承接前文Spring源码情操陶冶-自定义节点的解析 spring配置文件应用 <context: ...

  3. Spring源码解析 - AbstractBeanFactory 实现接口与父类分析

    我们先来看类图吧: 除了BeanFactory这一支的接口,AbstractBeanFactory主要实现了AliasRegistry和SingletonBeanRegistry接口. 这边主要提供了 ...

  4. spring源码解析:元注解功能的实现

    前言 众所周知,spring 从 2.5 版本以后开始支持使用注解代替繁琐的 xml 配置,到了 springboot 更是全面拥抱了注解式配置.平时在使用的时候,点开一些常见的等注解,会发现往往在一 ...

  5. spring源码 — 五、事务

    spring提供了可配置.易扩展的事务处理框架,本文主要从一下几个方面说明spring事务的原理 基本概念 事务配置解析 事务处理过程 基本概念 事务隔离级别 在同时进行多个事务的时候,可能会出现脏读 ...

  6. spring源码学习之路---IOC实现原理(三)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章我们已经初步认识了Be ...

  7. Spring源码学习之IOC容器实现原理(一)-DefaultListableBeanFactory

    从这个继承体系结构图来看,我们可以发现DefaultListableBeanFactory是第一个非抽象类,非接口类.实际IOC容器.所以这篇博客以DefaultListableBeanFactory ...

  8. Spring源码剖析7:AOP实现原理详解

    前言 前面写了六篇文章详细地分析了Spring Bean加载流程,这部分完了之后就要进入一个比较困难的部分了,就是AOP的实现原理分析.为了探究AOP实现原理,首先定义几个类,一个Dao接口: pub ...

  9. Spring源码窥探之:注解方式的AOP原理

    AOP入口代码分析 通过注解的方式来实现AOP1. @EnableAspectJAutoProxy通过@Import注解向容器中注入了AspectJAutoProxyRegistrar这个类,而它在容 ...

随机推荐

  1. hdu-5784 How Many Triangles(计算几何+极角排序)

    题目链接: How Many Triangles Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  2. mac laravel 环境变量设置bash_profile

    mac laravel 环境变量设置bash_profile >>>vim ~/.bash_profile '''text export PATH=$PATH:~/.composer ...

  3. 1034 Head of a Gang (30)(30 分)

    One way that the police finds the head of a gang is to check people's phone calls. If there is a pho ...

  4. 2084. Asm.Def的基本算法

    2084. Asm.Def的基本算法 传送门 ★☆   输入文件:asm_algo.in   输出文件:asm_algo.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述] ...

  5. 【Lintcode】103.Linked List Cycle II

    题目: Given a linked list, return the node where the cycle begins. If there is no cycle, return null. ...

  6. cocos2d-x CCHttpRequest获取网络图片并显示

    转自:http://www.cnblogs.com/hzj730/p/3178431.html //图片结构 class imgstruct : public CCObject { public: i ...

  7. 【VS工程设置】 编译动态库,命令行添加参数,不使用预编译头,指定该项目链接 哪种 运行库

    编译动态库 注意: 动态库: [目标文件扩展] => .dll + [配置类型] => 动态库(.dll) 静态库: [目标文件扩展] => .lib + [ 配置类型]=> ...

  8. 《SpringBoot揭秘 快速构建微服务体系》读后感(四)

    再谈自动配置 基于条件的自动配置 调整自动配置的顺序

  9. dpdk学习笔记2

    一 了解dpdk准备知识 1 NAT NAT技术是为了缓解IPV4地址枯竭得问题,通过使用NAT技术,一个机构如学校可以只用单一得公网IP来范文互联网,在外界看来只有一台接入公网得设备.NAT分为两种 ...

  10. WSAStartup()函数的使用

    int WSAStartup( __in WORD wVersionRequested, __out LPWSADATA lpWSAData ); WSAStartup 格  式: int PASCA ...