spring源码---事务01

1、什么情况下回滚

        查看源码 只有RuntimeException【unchecked Exception】和Error spring事务才会回滚,对于checked Exception可以通过@Transactional(rollbackFor=Exception.class) 来实现回滚。见Throwable类图

 2、同一个类中 方法调用事务不起作用

      原因:spring事务 基于aop的 环绕增强实现,通过getBean拿到的是代理对象,执行事务切面,事务切面通过TransactionInterceptor环绕增强进行事务管理,真正执行被增强方法的时候 是被代理对象,也就是下图中this是OrderTestService而不是代理对象。

      解决方法:A: 直接在当前类@Autowire 或者@Resource 注入自己,然后用注入的bean 调用方法

  

    B:通过ThreadLocal暴露Aop代理对象

实现原理参考:https://blog.csdn.net/JustForSS/article/details/83008824  

具体参考:https://blog.csdn.net/JIESA/article/details/53438342 

3、事务的传播

@Transactional(value=TxType.REQUIRES_NEW) //暂停当前事务,创建一个新的事务
//    @Transactional(value = TxType.SUPPORTS)//有事务再当前事务中进行 没有事务 以非事务方式继续运行
//    @Transactional(value =TxType.NEVER)//非事务的方式运行,存在事务就抛出异常//org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'
//    @Transactional(value=TxType.NOT_SUPPORTED)//非事务方式运行,存在事务就暂停当前事务,
//    @Transactional(value = TxType.MANDATORY)//以事务方式进行,当前有事务加入当前事务,当前没有事务 抛出异常 no existing transaction found for transaction marked with propagation mandatory
    @Transactional(value = TxType.REQUIRED)//当前存在事务加入该事务,不存在事务 创建一个新的事务

04、spring的bean的作用域

  • singleton : bean在每个Spring ioc 容器中只有一个实例。可以通过获取bean比较。缺省值。
  • prototype:一个bean的定义可以有多个实例。
  • request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。
  • session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
  • global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

 

5、spring中bean的声明周期

  • Spring容器 从XML 文件中读取bean的定义,并实例化bean。
  • Spring根据bean的定义填充所有的属性。
  • 如果bean实现了BeanNameAware 接口,Spring 传递bean 的ID 到 setBeanName方法。
  • 如果Bean 实现了 BeanFactoryAware 接口, Spring传递beanfactory 给setBeanFactory 方法。
  • 如果有任何与bean相关联的BeanPostProcessors,Spring会在postProcesserBeforeInitialization()方法内调用它们。
  • 如果bean实现InitializingBean了,调用它的afterPropertiesSet方法,如果bean声明了初始化方法,调用此初始化方法。
  • 如果有BeanPostProcessors 和bean 关联,这些bean的postProcessAfterInitialization() 方法将被调用。
  • 如果bean实现了 DisposableBean,它将调用destroy()方法。

The bean 标签有两个重要的属性(init-method和destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct和@PreDestroy)。

 

6、有五种自动装配的方式,可以用来指导Spring容器用自动装配方式来进行依赖注入。

  • no:默认的方式是不进行自动装配,通过显式设置ref 属性来进行装配。
  • byName:通过参数名 自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byname,之后容器试图匹配、装配和该bean的属性具有相同名字的bean。
  • byType::通过参数类型自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byType,之后容器试图匹配、装配和该bean的属性具有相同类型的bean。如果有多个bean符合条件,则抛出错误。
  • constructor:这个方式类似于byType, 但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
  • autodetect:首先尝试使用constructor来自动装配,如果无法工作,则使用byType方式。

 

7、Spring如何处理线程并发问题?

Spring使用ThreadLocal解决线程安全问题。

我们知道在一般情况下,只有有状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域。就是因为Spring对一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非线程安全状态采用ThreadLocal进行处理,让它们也成为线程安全的状态,因为有状态的Bean就可以在多线程中共享了。

ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。

(1)在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。

(2)而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。

(3)概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
 

8、通知有哪些类型?

(1)前置通知(Before advice):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。

(2)返回后通知(After returning advice):在某连接点(join point)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。 
(3)抛出异常后通知(After throwing advice):在方法抛出异常退出时执行的通知。 
(4)后通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。 
(5)环绕通知(Around Advice):包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。 
环绕通知是最常用的一种通知类型。大部分基于拦截的AOP框架,例如Nanning和JBoss4,都只提供环绕通知。
around before 方法执行 around after afterReturing

around before 方法执行 after afterThrowing