配置spring事务管理的几种方式(声明式事务)

概要:

  Spring对编程式事务的支持与EJB有很大的区别。不像EJB和Java事务API(Java Transaction API, JTA)耦合在一起那样,Spring通过回调机制将实际的事务实现从事务性的代码中抽象出来。实际上,Spring对事务的支持甚至不需要JTA的实现。如果你的应用程序只使用一种持久化资源,Spring可以使用持久化本事所提供的事务性支持,这包括了JDBC,Hibernate以及Java持久化API(Java Persistence API,JPA)。但是如果应用程序的事务跨多个资源,那么Spring会使用第三方的JTA实现来支持分布式(XA)事务。

  编码式事务允许用户在代码中精确定义事务的边界,而声明式事务(基于AOP)有助于用户将操作与事务规则经行解耦。无论选择将事务编码到Bean中还是将选择其定义为切面,我们都需要使用Spring事务管理器与平台相关的事务经行交互。(也就是无论选择编码式还会声明式,都需要在XML中定义事务管理器)。

Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。

DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。

具体如下图:

根据4种代理机制的不同,总结了五种Spring事务的配置方式。

目录:

  1. Bean和代理
  2. 使用拦截器
  3. 使用Tx标签配置的拦截器
  4. 全注解配置

声明式事务

 

公共配置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  8. http://www.springframework.org/schema/context
  9. http://www.springframework.org/schema/context/spring-context-2.5.xsd
  10. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
  11. <bean id="sessionFactory"
  12. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  13. <property name="configLocation" value="classpath:hibernate.cfg.xml" />
  14. <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
  15. </bean>
  16.  
  17. <!-- 定义事务管理器(声明式的事务) -->
  18. <bean id="hibernateTransactionManager"
  19. class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  20. <property name="sessionFactory" ref="sessionFactory"/>
  21. </bean>
  22. <!-- 配置DAO -->
  23. <bean id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl">
  24. <property name="sessionFactory" ref="sessionFactory" />
  25. </bean>

第一种,使用tx标签方式

  1. <!-- 第一种配置事务的方式 ,tx-->
  2. <tx:advice id="txadvice" transaction-manager="transactionManager">
  3. <tx:attributes>
  4. <tx:method name="add*" propagation="REQUIRED" rollback-for="Exception" />
  5. <tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception" />
  6. <tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/>
  7. <tx:method name="*" propagation="REQUIRED" read-only="true"/>
  8. </tx:attributes>
  9. </tx:advice>
  10.  
  11. <aop:config>
  12. <aop:pointcut id="daoMethod" expression="execution(* com.dao.*.*(..))"/>
  13. <aop:advisor pointcut-ref="daoMethod" advice-ref="txadvice"/>
  14. </aop:config>

expression="execution(* com.dao.*.*(..))"
其中第一个*代表返回值,第二*代表dao下子包,第三个*代表方法名,“(..)”代表方法参数。

第二种,使用代理方式

  1. <!-- 第二种配置事务的方式 ,代理-->
  2. <bean id="transactionProxy"
  3. class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
  4. <property name="transactionManager" ref="transactionManager"></property>
  5. <property name="transactionAttributes">
  6. <props>
  7. <prop key="add*">PROPAGATION_REQUIRED, -Exception</prop>
  8. <prop key="modify*">PROPAGATION_REQUIRED, -Exception</prop>
  9. <prop key="del*">PROPAGATION_REQUIRED, -Exception</prop>
  10. <prop key="*">PROPAGATION_REQUIRED, readOnly</prop>
  11. </props>
  12. </property>
  13. </bean>
  14. <bean id="userDao" parent="transactionProxy">
  15. <property name="target">
  16. <!-- 用bean代替ref的方式-->
  17. <bean class="com.dao.UserDaoImpl">
  18. <property name="sessionFactory" ref="sessionFactory"></property>
  19. </bean>
  20. </property>
  21. </bean>

将transactionProxy的abstract属性设置为"true",然后将具体的Dao的parent属性设置为"transactionProxy",可以精简代码。

第三种,使用拦截器

  1. <!-- 第三种配置事务的方式,拦截器 (不常用)-->
  2. <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
  3. <property name="transactionManager" ref="transactionManager"></property>
  4. <property name="transactionAttributes">
  5. <props>
  6. <prop key="add*">PROPAGATION_REQUIRED, -Exception</prop>
  7. <prop key="modify*">PROPAGATION_REQUIRED, -Exception</prop>
  8. <prop key="del*">PROPAGATION_REQUIRED, -Exception</prop>
  9. <prop key="*">PROPAGATION_REQUIRED, readOnly</prop>
  10. </props>
  11. </property>
  12. </bean>
  13. <bean id="proxyFactory" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
  14. <property name="interceptorNames">
  15. <list>
  16. <value>transactionInterceptor</value>
  17. </list>
  18. </property>
  19. <property name="beanNames">
  20. <list>
  21. <value>*Dao</value>
  22. </list>
  23. </property>
  24. </bean>

Bean和代理

第一种方式:每个Bean都有一个代理

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  8. http://www.springframework.org/schema/context
  9. http://www.springframework.org/schema/context/spring-context-2.5.xsd
  10. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
  11.  
  12. <bean id="sessionFactory"
  13. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  14. <property name="configLocation" value="classpath:hibernate.cfg.xml" />
  15. <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
  16. </bean>
  17.  
  18. <!-- 定义事务管理器(声明式的事务) -->
  19. <bean id="transactionManager"
  20. class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  21. <property name="sessionFactory" ref="sessionFactory" />
  22. </bean>
  23.  
  24. <!-- 配置DAO -->
  25. <bean id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl">
  26. <property name="sessionFactory" ref="sessionFactory" />
  27. </bean>
  28.  
  29. <bean id="userDao"
  30. class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
  31. <!-- 配置事务管理器 -->
  32. <property name="transactionManager" ref="transactionManager" />
  33. <property name="target" ref="userDaoTarget" />
  34. <property name="proxyInterfaces" value="com.bluesky.spring.dao.GeneratorDao" />
  35. <!-- 配置事务属性 -->
  36. <property name="transactionAttributes">
  37. <props>
  38. <prop key="*">PROPAGATION_REQUIRED</prop>
  39. </props>
  40. </property>
  41. </bean>
  42. </beans>

总结:

  1. 定义数据源  
  2. 定义事务管理器(将数据源加入)
  3. 定义Dao Bean(将数据源加入)
  4. 定义TransactionProxyFactoryBean代理Bean,将事务管理器,Dao Bean加入。
    1.  

第二种方式:所有Bean共享一个代理基类

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  8. http://www.springframework.org/schema/context
  9. http://www.springframework.org/schema/context/spring-context-2.5.xsd
  10. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
  11. <bean id="sessionFactory"
  12. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  13. <property name="configLocation" value="classpath:hibernate.cfg.xml" />
  14. <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
  15. </bean>
  16.  
  17. <!-- 定义事务管理器(声明式的事务) -->
  18. <bean id="hibernateTransactionManager"
  19. class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  20. <property name="sessionFactory" ref="sessionFactory"/>
  21. </bean>
  22.  
  23. <bean id="HibernateProxyTemplate"
  24. abstract="true"
  25. class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
  26. <!-- 配置事务管理器 -->
  27. <property name="transactionManager">
  28. <ref bean="hibernateTransactionManager"/>
  29. </property>
  30. <!-- 配置事务属性 -->
  31. <property name="transactionAttributes">
  32. <props>
  33. <prop key="create*">
  34. PROPAGATION_REQUIRED,-java.lang.Exception
  35. </prop>
  36. <prop key="reg*">
  37. PROPAGATION_REQUIRED,-java.lang.Exception
  38. </prop>
  39. <prop key="apply*">
  40. PROPAGATION_REQUIRED,-java.lang.Exception
  41. </prop>
  42. <prop key="add*">
  43. PROPAGATION_REQUIRED,-java.lang.Exception
  44. </prop>
  45. <prop key="remove*">
  46. PROPAGATION_REQUIRED,-java.lang.Exception
  47. </prop>
  48. <prop key="update*">
  49. PROPAGATION_REQUIRED,-java.lang.Exception
  50. </prop>
  51. <prop key="delete*">
  52. PROPAGATION_REQUIRED,-java.lang.Exception
  53. </prop>
  54. <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
  55. </props>
  56. </property>
  57. </bean>
  1. <bean id="userDao" class="edu.fjnu.hotelsys.dao.UserDaoHibernateImpl">
  2. <property name="sessionFactory" ref="sessionFactory"></property>
  3. </bean>
  4.  
  5. <bean id="userServiceTarget" class="edu.fjnu.hotelsys.service.UserServiceImpl">
  6. <property name="userDao" ref="userDao"></property>
  7. </bean>
  8.  
  9. <bean id="userService" parent="HibernateProxyTemplate">
  10. <property name="target">
  11. <ref bean="userServiceTarget"/>
  12. </property>
  13. </bean>

只要指明它的parent(父类)就可以了。父类一般把abstract="true",因为在容器加载的时候不需要初始化,等到用的时候再有它的子类调用的时候,再去初始化。

总结:

  1. 定义数据源  
  2. 定义事务管理器(将数据源加入),且将事务管理器声明为abstract="true"
  3. 定义Dao Bean(将数据源加入)
  4. 定义TransactionProxyFactoryBean代理Bean,将事务管理器,Dao Bean加入。

使用拦截器

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  8. http://www.springframework.org/schema/context
  9. http://www.springframework.org/schema/context/spring-context-2.5.xsd
  10. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
  11.  
  12. <bean id="sessionFactory"
  13. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  14. <property name="configLocation" value="classpath:hibernate.cfg.xml" />
  15. <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
  16. </bean>
  17.  
  18. <!-- 定义事务管理器(声明式的事务) -->
  19. <bean id="transactionManager"
  20. class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  21. <property name="sessionFactory" ref="sessionFactory" />
  22. </bean>
  23.  
  24. <bean id="transactionInterceptor"
  25. class="org.springframework.transaction.interceptor.TransactionInterceptor">
  26. <property name="transactionManager" ref="transactionManager" />
  27. <!-- 配置事务属性 -->
  28. <property name="transactionAttributes">
  29. <props>
  30. <prop key="*">PROPAGATION_REQUIRED</prop>
  31. </props>
  32. </property>
  33. </bean>
  34.  
  35. <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
  36. <property name="beanNames">
  37. <list>
  38. <value>*Dao</value>
  39. </list>
  40. </property>
  41. <property name="interceptorNames">
  42. <list>
  43. <value>transactionInterceptor</value>
  44. </list>
  45. </property>
  46. </bean>
  47.  
  48. <!-- 配置DAO -->
  49. <bean id="userDao" class="com.bluesky.spring.dao.UserDaoImpl">
  50. <property name="sessionFactory" ref="sessionFactory" />
  51. </bean>
  52. </beans>

使用tx标签配置的拦截器

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xmlns:tx="http://www.springframework.org/schema/tx"
  7. xsi:schemaLocation="http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  9. http://www.springframework.org/schema/context
  10. http://www.springframework.org/schema/context/spring-context-2.5.xsd
  11. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
  12. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
  13.  
  14. <context:annotation-config />
  15. <context:component-scan base-package="com.bluesky" />
  16.  
  17. <bean id="sessionFactory"
  18. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  19. <property name="configLocation" value="classpath:hibernate.cfg.xml" />
  20. <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
  21. </bean>
  22.  
  23. <!-- 定义事务管理器(声明式的事务) -->
  24. <bean id="transactionManager"
  25. class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  26. <property name="sessionFactory" ref="sessionFactory" />
  27. </bean>
  28.  
  29. <tx:advice id="txAdvice" transaction-manager="transactionManager">
  30. <tx:attributes>
  31. <tx:method name="*" propagation="REQUIRED" />
  32. </tx:attributes>
  33. </tx:advice>
  34.  
  35. <aop:config>
  36. <aop:pointcut id="interceptorPointCuts"
  37. expression="execution(* com.bluesky.spring.dao.*.*(..))" />
  38. <aop:advisor advice-ref="txAdvice"
  39. pointcut-ref="interceptorPointCuts" />
  40. </aop:config>
  41. </beans>

全注解

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xmlns:tx="http://www.springframework.org/schema/tx"
  7. xsi:schemaLocation="http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  9. http://www.springframework.org/schema/context
  10. http://www.springframework.org/schema/context/spring-context-2.5.xsd
  11. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
  12. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
  13.  
  14. <context:annotation-config />
  15. <context:component-scan base-package="com.bluesky" />
  16.  
  17. <tx:annotation-driven transaction-manager="transactionManager"/>
  18.  
  19. <bean id="sessionFactory"
  20. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  21. <property name="configLocation" value="classpath:hibernate.cfg.xml" />
  22. <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
  23. </bean>
  24.  
  25. <!-- 定义事务管理器(声明式的事务) -->
  26. <bean id="transactionManager"
  27. class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  28. <property name="sessionFactory" ref="sessionFactory" />
  29. </bean>
  30.  
  31. </beans>

此时在DAO上需加上@Transactional注解,如下:

  1. package com.bluesky.spring.dao;
  2.  
  3. import java.util.List;
  4.  
  5. import org.hibernate.SessionFactory;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
  8. import org.springframework.stereotype.Component;
  9.  
  10. import com.bluesky.spring.domain.User;
  11.  
  12. @Transactional
  13. @Component("userDao")
  14. public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
  15.  
  16. public List<User> listUsers() {
  17. return this.getSession().createQuery("from User").list();
  18. }
  19.  
  20. }

文章出自:http://www.cnblogs.com/longshiyVip/p/5061547.html

事务管理(下) 配置spring事务管理的几种方式(声明式事务)的更多相关文章

  1. 配置spring事务管理的几种方式(声明式事务)

    Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分. DataSo ...

  2. spring整合mybatis,ioc容器及声明式事务配置

    步骤: 1.创建jdbc.properties文件,用来管理存放连接数据库的相关信息 jdbc.properties:jdbc.user=root jdbc.password=123456 jdbc. ...

  3. Spring框架(三) JDBCTemplate,声明式事务,自动装载(注解)

    JDBCTemplate 按照标准正常项目的结构 结构图: model层 dao层 实现  dao:(DateBase Access Object) 数据访问对象,dao层只用来访问数据库和模型层 s ...

  4. Spring注解驱动开发(四)-----aop、声明式事务

    AOP 概念 指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式:-----基于动态代理 一个aop示例 1.导入aop模块:Spring AOP:(spring-aspects ...

  5. 第一课:Centos下配置java环境变量的两种方式(jdk1.8)

    配置java环境(yum安装) 1.查出java1.8的全部版本 yum list java-1.8* 2.安装你需要的java1.8 版本(安装的名字根据查询出来的结果输入这里只是举例) yum i ...

  6. 全面分析 Spring 的编程式事务管理及声明式事务管理

    开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本 ...

  7. 全面分析 Spring 的编程式事务管理及声明式事务管理--转

    开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本 ...

  8. spring事务管理——编程式事务、声明式事务

    本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本教程假定您已经掌握了 ...

  9. Spring编程式事务管理及声明式事务管理

    本文将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. Spring 事务属性分析 事务管理 ...

随机推荐

  1. 2.2 C#的注释

    注释,是代码中的一些“说明文档”,注释注释本身不会参与程序代码的编译和运行,仅仅是为了方便程序员阅读. C#的注释分为:单行注释.多行注释.文档注释. 单行注释的符号是2条斜杠线(斜线的方向是左下到右 ...

  2. android手机和ios手机的分辨率

    Android手机目前常见的分辨率 1.1 手机常见分辨率: 4:3 VGA     640*480 (Video Graphics Array) QVGA  320*240 (Quarter VGA ...

  3. linux通过ntp设置系统时间

    1.查看本机时间 date 2.安装ntp并且设置开机启动 sudo yum -y install ntp chkconfig ntp on 3.立即更新系统时间 sudo ntpdate time. ...

  4. Python字符串格式化

    一.使用格式化符来格式化字符串: Python支持的所有格式化符 格式化符 意义 'd' 返回要格式化对象的十进制表示,如果可以 'i' 返回要格式化对象的十进制表示,如果可以 'o' 返回要格式化对 ...

  5. linux hadoop安装

    linux hadoop安装 本文介绍如何在Linux下安装伪分布式的hadoop开发环境. 在一开始想利用cgywin在 windows下在哪, 但是一直卡在ssh的安装上.所以最后换位虚拟机+ub ...

  6. The constructor BASE64Encoder() is not accessible due to restriction on required library

    在Eclipse中编写Java代码时,用到了BASE64Decoder,import sun.misc.BASE64Decoder;可是Eclipse提示:Access restriction : T ...

  7. Qt qml treeview 树控件

    qml并没有提供树控件,只能自己写了.model仍然用ListModel对象,弄成层级的就行.delegate必须用loader动态的增加子控件,如此而已. [先看效果] [下载] http://do ...

  8. django 其他地址访问不了问题

    启动的时候 使用 python manage.py runserver 0.0.0.0:8000  即可接收所有IP访问

  9. Xcode Build Settings Architectures

    http://foggry.com/blog/2014/05/09/xcodeshe-zhi-xiang-zhi-architectureshe-valid-architectures/ https: ...

  10. HashMap与ConcurrentHashMap的区别

    从JDK1.2起,就有了HashMap,正如前一篇文章所说,HashMap不是线程安全的,因此多线程操作时需要格外小心. 在JDK1.5中,伟大的Doug Lea给我们带来了concurrent包,从 ...