spring基础

一、什么是spring,有什么用?

  Spring是一个开源框架,是一个轻量级的解决防范,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。其核心思想IOC和AOP

二、spring的结构体系(基于4.0.2)

  1、Spring框架是一个分层架构。它包含一系列的功能要素并被分类大约20个模块,这些模块分为Core Container、Data Access/Integration、Web、AOP、Instrumentation和测试部分。

  

  2、spring相关的jar包及其功能

    spring-core.jar  包含Spring 框架基本的核心工具类。Spring 其它组件要都要使用到这个包里的类,是其它组件的基本核心

    spring-beans.jar  包含访问配置文件、创建和管理bean 以及进行Inversion of Control / Dependency Injection(IoC/DI)操作相关的所有类

    spring-context.jar  为Spring 核心提供了大量扩展。可以找到使用Spring ApplicationContext特性时所需的全部类,JDNI 所需的全部类,instrumentation组件以及校验Validation 方面的相关类。

    spring-context-support  Spring context的扩展支持,用于MVC方面。

    spring-expression  对spring表达式语言的支持。

    spring-aop.jar  对spring AOP特性的支持。使用基于AOP 的Spring特性,如声明型事务管理(Declarative Transaction Management)。

    spring-aspects  Spring提供的对AspectJ框架的整合

    spring-instrument  Spring对服务器的代理接口

    spring-jdbc  包含对Spring对JDBC数据访问进行封装的所有类

    spring-jms  为简化jms api的使用而做的简单封装

    spring-messaging  spring-messaging模块为集成messaging api和消息协议提供支持

    spring-orm  整合第三方的orm实现,如hibernate,mybatis

    spring-oxm  pring 对Object/XMl的映射支持

    spring-test  对Junit等测试框架的简单封装。

    spring-tx  对spring事务的支持

    spring-web  spring开发web项目时所需的核心类,包括自动载入Web ApplicationContext 特性的类、Struts 与JSF 集成类、文件上传的支持类、Filter 类和大量工具辅助类。

    spring-webmvc  Web MVC框架,控制器和视图支持。

    spring-webmvc-portlet  对Spring MVC的增强

    spring-websocket  提供对websocket的支持

    aopalliance   AOP联盟的API包,里面包含了针对面向切面的接口。通常Spring等其它具备动态织入功能的框架依赖此包。 

    aspectjweaver-1.5.0.jar  用于在Spring 中集成AspectJ AspectJ LTW织入器 

    commons-collections-3.2.2.jar   Apache Commons包中的一个,包含了一些Apache开发的集合类,功能比java.util.*强大。 

    commons-dbcp-1.2.1.jar    DBCP数据库连接池 

    commons-pool-1.6.jar    DBCP是一个依赖commons-pool对象池机制的数据库连接池 

三、IOC

  1、IOC(Inversion of Control)容器也叫控制反转容器,其主要的作用是创建和管理对象。它改变了程序自己在代码中创建依赖对象的传统模式,通过容器来创建并管理这些对象,同时维护对象之间的关系,这样就能降低程序间的耦合程度。

  2、spring创建对象的几种方式及相关细节

    ①调用无参数构造函数, 创建对象

    ②有参构造函数,创建对象

    ③工厂创建对象

      工厂类,静态方法,创建对象

      工厂类,非静态方法,创建对象
 
public class Worker {

    private String name;
    private int age;
    
    public Worker() {
        super();
    }
    public Worker(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void work(){
        System.out.println(age+"岁的工人"+name+"在工作");
    }
    
}
public class Teacher {

    private String name;
    private int age;
    
    public Teacher() {
        super();
    }

    public Teacher(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    
    public void teach(){
        System.out.println(age+"的老师"+name+"在教书");
    }
}
public class BeanFactory {

    public static Worker getWorker(){
        return new Worker();
    }
    
    public Worker getWorker2(){
        return new Worker();
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:p="http://www.springframework.org/schema/p"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans.xsd">
     
     <!-- 
          id  唯一,不能以数字或特殊符号开头(编译报错,可以运行!)
          name 定义bean的别名, 可以有特殊符号,可以同时定义多个对象的引用,用空格、逗号或者分号隔开!不能和其他bean的别名重复。
                           其实id和name是一个意思,但是可以定义多个bean标识符,id只能定义一个标识符,id和name都可以看作别名
          alias可以定义别名
                            配置一个bean的时候,我们可以不设置id,也可以不设置name,spring默认会使用类的全限定名作为bean的标识符。
          scope  : singleton单例,prototype多例。spring默认创建单例对象,单例对象默认是服务器启动的时候创建,可以通过
            lazy-init="true"  延迟创建单例的对象; 在第一次使用的时候创建一次!
          init-method:在创建对象之后执行!
          destroy-method:在对象销毁时候执行!
      -->
     <!-- 无参构造函数创建对象 -->
     <bean id="bean1" name="bean2,bean3,bean4" class="testspring.Worker"></bean>
     <alias name="bean1" alias="worker11"/>
     
     <!-- 有参构造函数创建对象 -->
     <!-- <bean id="teacher" name="bean2" class="testspring.Teacher">
        <constructor-arg index="0" type="String" value="kyle"></constructor-arg>
        <constructor-arg index="1" type="int" value="18"></constructor-arg>
     </bean> -->
     <!-- <alias name="teacher" alias="worker11"/> -->
     
     <!-- 工厂静态方法创建对象 -->
     <!-- <bean id="worker3" class="testspring.BeanFactory" factory-method="getWorker" ></bean> -->
     
     <!-- 工厂非静态方法创建对象 -->
     <!-- <bean id="beanFactory" class="testspring.BeanFactory"></bean>
     <bean id="worker4" factory-bean="beanFactory" factory-method="getWorker2"></bean> -->
     
</beans>  

    

  3、DI(Dependency Injection)依赖注入:容器在程序运行的时候为程序提供所需对象这就是依赖注入。DI就是实现控制反转的方式。

    ①setter注入

    ②构造器注入

    ③自动装配

     

public class Dao {

    public void doSomeThing(){
        System.out.println("Dao....doSomeThing");
    }
    
}

public class Service {
    
    private Dao dao;

    //注意set方法一定要和字段匹配,如字段为abc,则方法名应该为SetAbc
    public void setDao(Dao dao){
        this.dao = dao;
    }
    
    public Service(Dao dao){
        this.dao = dao;
    }
    
    public Service(){
        
    }
    
    public void doSomeThing(){
        dao.doSomeThing();
    }
}

public class Test {

    public static void main(String[] args) {
        ApplicationContext applicationContext = (ApplicationContext) new ClassPathXmlApplicationContext("testdi/applicationContext.xml");
        Service service = (Service)applicationContext.getBean("service");
        service.doSomeThing();
    }

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:context="http://www.springframework.org/schema/context"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:p="http://www.springframework.org/schema/p"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/beans/spring-context.xsd"
      default-autowire="byType">
     
     <bean id="dao" class="testdi.Dao"></bean>
     
     <!-- setter方法注入 -->
     <!-- <bean id="service" class="testdi.Service">
        <property name="dao" ref="dao"></property>
     </bean> -->
     
     <!-- 构造器注入 -->
     <!-- <bean id="service" class="testdi.Service">
        <constructor-arg name="dao" ref="dao"></constructor-arg>
     </bean> -->
     
     <!-- 自动装配 -->
     <!-- 
        no:不设置该属性,默认不进行自动装配
        byName:根据Bean的名字进行自动装配,需要setter方法
        byType:根据Bean的类型进行自动装配,需要setter方法
        constructor:类似于byType,不过是应用于构造器的参数
        default:根据上面default-autowire的值确定
      -->
     <bean id="service" class="testdi.Service" autowire="default"></bean>
     

    ④注解自动装配

      相关注解:

        @Autowired  自动装配,其作用是为了消除代码Java代码里面的setter与bean属性中的property,默认按照byType的方式去匹配

        @Qualifier  指定注入bean的名称,使用@Autowired时如果容器中有多个对象可以匹配,这需要该注解对对象进行限定

        @Resource  和@Autowired差不多,但是其属于java自带注解,不是spring的注解。默认通过name属性去匹配bean,找不到再按type去匹配

        @Component  将对象加入到容器中,这个属于通用的注解。

          @ Repository  将数据访问(DAO)层对象加入容器中

       @Service  将Service层对象加入容器中

       @Controller  将表现层对象加入到容器中

       @Configuration  用于定义配置类,可用于替换xml配置文件。被该注解定义的类包含一个或多个@Bean注解定义的方法,这些方法会被AnnotationConfigApplicationContext或AnnotionConfigWebApplicationContext类进行扫描,并用于构建bean,初始                                                 化spring容器。

          @Bean  用来定义bean,并加入到spring容器中。

       @ComponentScan   用来定义注解扫描的范围

       @RequestMapping(value="/haha",method=RequestMethod.GET)  定义web请求的路径和方法

       @RequestBody是指方法参数应该被绑定到HTTP请求Body上

       @ResponseBody与@RequestBody类似,它的作用是将返回类型直接输入到HTTP response body中  

       @RestController :控制器实现了REST的API,只为服务于JSON,XML或其它自定义的类型内容,@RestController用来创建REST类型的控制器,与@Controller类型。@RestController就是这样一种类型,它避免了你重复的写@RequestMapping与                  @ResponseBody。

       @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)  定义事务

  开启注解扫描:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:p="http://www.springframework.org/schema/p"
     xmlns:context="http://www.springframework.org/schema/context"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 使用注解,要先开启注解扫描  -->
<context:component-scan base-package="cn.itcast.g_anno"></context:component-scan>

</beans>   

四、AOP :Aspect  orient  programming  面向切面编程!是对oop有益的补充。

  1、aop中相关的概念

    AOP技术它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为”Aspect”,即切面。所谓”切面”,简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。AOP主要是使用代理来实现相关功能的。

    横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点。个人理解为整个aop需要关注的东西就叫横切关注点。

    切面(aspect):对横切关注点的定义,也就是代码中和核心业务无关的每个模块都有的公共代码

    连接点(joinpoint):能够被拦截并切入的点,理论上代码执行的任何时候都可以被切入,但是spring只支持方法执行连接点。

    切入点(pointcut):对连接点拦截的定义,定义切面在什么连接点切入

    通知(advice):通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类

    织入(weave):将切面应用到目标对象并导致代理对象创建的过程

  

  2、使用spring-aop需要引入的jar包

    aspectjweaver-1.8.9

      aopalliance-1.0

    spring-aop-4.0.2.RELEASE

    spring-aspects-4.0.2.RELEASE

  3、 aop代码示例

public interface WorkService {

    void work();
    
    void rest();
}

public class WorkServiceImpl implements WorkService  {
    
    @Override
    public void work(){
        System.out.println("工人正在工作。。。");
    }

    @Override
    public void rest() {
        System.out.println("工人正在休息");
        int i = 1/0;
    }
}
public class AopAspect {

   public void before(JoinPoint joinPoint){
       String methodName = joinPoint.getSignature().getName();
       System.out.println(methodName+"方法准备执行:before");
   }
   
   public void after(JoinPoint joinPoint){
       String methodName = joinPoint.getSignature().getName();
       Object[] args = joinPoint.getArgs();
       System.out.println(methodName+" 方法执行完毕,after,参数为:"+args);
   }
   
   public void afterReturning(JoinPoint joinPoint, Object result){
       String methodName = joinPoint.getSignature().getName();
       System.out.println(methodName + " 方法执行返回结果:" + result);
   }
   
   public void afterThrowing(JoinPoint joinPoint, Exception ex){
       String methodName = joinPoint.getSignature().getName();
       System.out.println(methodName + " 方法执行抛出异常:" + ex);
   }
   
   public Object around(ProceedingJoinPoint pjd){
       Object result = null;
       String methodName = pjd.getSignature().getName();
       try{
           System.out.println(methodName + "方法准备执行:arround");
           result = pjd.proceed();
       } catch(Throwable e){
         //异常通知
         System.out.println("The method " + methodName + " occurs expection : " + e);
         throw new RuntimeException(e);
       }
       //后置通知
       System.out.println(methodName + "方法执行完毕:arround");
       return result;
   }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <bean id="workService" class="testaop.WorkServiceImpl"></bean>        
    <bean id="aop" class="testaop.AopAspect"></bean>
            
    <!-- Aop配置 -->
    <aop:config>
        <!-- 切面配置 -->
        <aop:aspect ref="aop">
            <!-- 切入点表达式  -->
            <aop:pointcut expression="execution(* testaop.*.*(..))" id="pointcut"/>
            <!-- 前置通知,在方法执行前执行 -->
            <aop:before method="before" pointcut-ref="pointcut"/>
            <!-- 后置通知 ,在方法执行后执行-->
            <aop:after method="after" pointcut-ref="pointcut"/>
            <!-- 返回后通知 ,在方法执行且返回一个结果后执行-->
            <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
            <!-- 异常通知,方法抛出异常后执行 -->
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="ex"/>
            <!-- 环绕通知 -->
            <aop:around method="around" pointcut-ref="pointcut"/>
        </aop:aspect>

    </aop:config>
     
</beans> 
public class Test {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("testaop/applicationContext.xml");
        WorkService workService = (WorkService)applicationContext.getBean("workService");
        workService.work();
        //workService.rest();
    }
}

执行work()结果:
work方法准备执行:before
work方法准备执行:arround
工人正在工作。。。
work方法执行完毕:arround
work 方法执行返回结果:null
work 方法执行完毕,after,参数为:[Ljava.lang.Object;@6b4a4e18

执行rest()结果:
rest方法准备执行:before
rest方法准备执行:arround
工人正在休息
The method rest occurs expection : java.lang.ArithmeticException: / by zero
rest 方法执行抛出异常:java.lang.RuntimeException: java.lang.ArithmeticException: / by zero
rest 方法执行完毕,after,参数为:[Ljava.lang.Object;@6b4a4e18
Exception in thread "main" java.lang.RuntimeException: java.lang.ArithmeticException: / by zero
    at testaop.AopAspect.arround(AopAspect.java:38)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:68)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:43)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:52)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy2.rest(Unknown Source)
    at testaop.Test.main(Test.java:12)
Caused by: java.lang.ArithmeticException: / by zero
    at testaop.WorkServiceImpl.rest(WorkServiceImpl.java:13)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
    at testaop.AopAspect.arround(AopAspect.java:34)
    ... 21 more

  注解版:执行的结果一样但是4.0.2版本会报错,4.3.6没有报错。

@Component
@Aspect
public class AnnotationAopAspect {
    
    // 定义一个切入点表达式
    @Pointcut("execution(* testaop.*.*(..))")
    public void pointCut(){}

    @Before("pointCut()")
    public void before(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println(methodName+"方法准备执行:before");
    }
    
    @After("pointCut()")
    public void after(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println(methodName+" 方法执行完毕,after,参数为:"+args);
    }
    
    @AfterReturning(value="pointCut()" ,returning="result")
    public void afterReturning(JoinPoint joinPoint, Object result){
        String methodName = joinPoint.getSignature().getName();
        System.out.println(methodName + " 方法执行返回结果:" + result);
    }
    
    @AfterThrowing(value="pointCut()",throwing="ex")
    public void afterThrowing(JoinPoint joinPoint, Exception ex){
        String methodName = joinPoint.getSignature().getName();
        System.out.println(methodName + " 方法执行抛出异常:" + ex);
    }
    
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint pjd){
        Object result = null;
        String methodName = pjd.getSignature().getName();
        try{
            System.out.println(methodName + "方法准备执行:arround");
            result = pjd.proceed();
        } catch(Throwable e){
          //异常通知
          System.out.println("The method " + methodName + " occurs expection : " + e);
          throw new RuntimeException(e);
        }
        //后置通知
        System.out.println(methodName + "方法执行完毕:arround");
        return result;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context  
        http://www.springframework.org/schema/context/spring-context.xsd  
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <bean id="workService" class="testaop.WorkServiceImpl"></bean>        
    <!-- 开启注解扫描 -->
    <context:component-scan base-package="testaop"></context:component-scan>
    <!-- 激活自动代理功能 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
            
     
</beans>  

五、事务

  什么是事务?有什么特性?
    事务是一组操作的执行单元,相对于数据库操作来讲,事务管理的是一组SQL指令,比如增加,修改,删除等,事务的一致性,要求,这个事务内的操作必须全部执行成功,如果在此过程种出现了差  错,比如有一条SQL语句没有执行成功,那么这一组操作都将全部回滚
  事务特性(ACID) 
    Atomic(原子性):要么都成功,要么都失败 
    Consistent(一致性):数据应该不被破坏 
    Isolate(隔离性):用户间操作不相混淆
    Durable(持久性):永久保存

  事务的隔离级别

    TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。

    TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。    

    TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。

    TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。

    TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

  

  事务传播行为!控制的是事务的边界!
     Never   当前方法不能再事务范围内执行!
    NOT_SUPPORTED   不支持事务
    SUPPORTS   有则支持; 没有也可以运行!    (查询时候使用)
      REQUIRED  业务方法必须在事务环境内执行;如果业务方法已经在事务环境下执行,加入当前事务!如果业务方法没有再事务内执行,则开启新的事务!
    REQUIRESNEW  不管业务方法是否在事务环境内运行,都会开启一个新的事务!
 
  

  spring事务回滚规则

     指示spring事务管理器回滚一个事务的推荐方法是在当前事务的上下文内抛出异常。spring事务管理器会捕捉任何未处理的异常,然后依据规则决定是否回滚抛出异常的事务。默认配置下,spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而抛出checked异常则不会导致事务回滚。可以明确的配置在抛出那些异常时回滚事务,包括checked异常。也可以明确定义那些异常抛出时不回滚事务。还可以编程性的通过setRollbackOnly()方法来指示一个事务必须回滚,在调用完setRollbackOnly()后你所能执行的唯一操作就是回滚。

1.xml配置事务

public class UserDao {

    private JdbcTemplate jdbcTemplate ;
    
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
        this.jdbcTemplate = jdbcTemplate;
    }
    
    public void updateUserPwd(){
        String sql = "update user set password = '987654' where account = '80074567'  "; 
        jdbcTemplate.update(sql);
    }
    
    public void updateUserName(){
        String sql = "update user set name = 'GGG' where account = '80074191'  "; 
        jdbcTemplate.update(sql);
    }
}


public class UserService {

    private UserDao userDao;
    
    public void setUserDao(UserDao userDao){
        this.userDao = userDao;
    }
    
    public void updateSth(){
        userDao.updateUserName();
        int i = 1/0;
        userDao.updateUserPwd();
    }
}


public class Test {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("testtx/applicationContext.xml");
        UserService userService = (UserService)applicationContext.getBean("userService");
        userService.updateSth();
    }

}
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/zmyproject?useUnicode=true&amp;characterEncoding=UTF-8
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.user=root
jdbc.password=root
jdbc.initialPoolSize=10
jdbc.minPoolSize=5
jdbc.maxPoolSize=30
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:c="http://www.springframework.org/schema/c"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:lang="http://www.springframework.org/schema/lang"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:task="http://www.springframework.org/schema/task"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.3.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-4.3.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
        
        <!-- 加载db.properties文件中的内容 中的key要有一定的规则 -->
        <context:property-placeholder location="testtx/db.properties"/>
        
        <!-- 配置数据源 -->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
            <property name="driverClass" value="${jdbc.driverClass}"/>
            <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
            <property name="user" value="${jdbc.user}"/>
            <property name="password" value="${jdbc.password}"/>
            <property name="initialPoolSize" value="${jdbc.initialPoolSize}"/>
            <property name="minPoolSize" value="${jdbc.minPoolSize}"/>
            <property name="maxPoolSize" value="${jdbc.maxPoolSize}"/>
        </bean>
        
        <!-- 二、创建JdbcTemplate对象,注入“数据源” -->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource"></property>
        </bean>

        <!-- 三、Spring声明式事务管理配置 -->
        <!-- 3.1 配置事务管理器类(事务切面) -->
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>

        <!-- 3.2 事务通知配置 ,对指定的方法,如何管理事务 -->
        <tx:advice id="txAdvice" transaction-manager="txManager">
            <tx:attributes>
                <tx:method name="get*" read-only="true"/>
                <tx:method name="find*" read-only="true"/>
                <tx:method name="*" read-only="false"/>
            </tx:attributes>
        </tx:advice>

        <!-- 3.3Aop配置 = 切面点表达式  + 应用事务通知 -->
        <aop:config>
            <aop:pointcut expression="execution(* testtx.*Service*.*(..))" id="pt"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
        </aop:config>

        <bean id="userDao" class="testtx.UserDao">
            <property name="jdbcTemplate" ref="jdbcTemplate"></property>
        </bean>
        <bean id="userService" class="testtx.UserService">
            <property name="userDao" ref="userDao"></property>
        </bean>
</beans>    

 2、注解版事务

@Repository
public class UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate ;
    
    public void updateUserPwd(){
        String sql = "update user set password = '987654' where account = '80074567'  "; 
        jdbcTemplate.update(sql);
    }
    
    public void updateUserName(){
        String sql = "update user set name = 'GGG' where account = '80074191'  "; 
        jdbcTemplate.update(sql);
    }
}


@Service
@Transactional(
        readOnly=false, // 读写操作;  当执行非查询时候使用!
        rollbackFor=ArithmeticException.class,  // 遇到指定的异常回滚
        //noRollbackFor=ArithmeticException.class,  // 遇到指定的异常不回滚
        timeout=-1, // 指定超时时间; -1表示不指定超时时间!
        isolation=Isolation.DEFAULT,  // 事务隔离级别!
        propagation=Propagation.REQUIRED // 事务传播行为
      )
public class UserService {

    @Autowired
    private UserDao userDao;
    
    public void updateSth(){
        userDao.updateUserName();
        int i = 1/0;
        userDao.updateUserPwd();
    }
}

public class Test {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("testtx2/applicationContext.xml");
        UserService userService = (UserService)applicationContext.getBean("userService");
        userService.updateSth();
    }

}
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/zmyproject?useUnicode=true&amp;characterEncoding=UTF-8
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.user=root
jdbc.password=root
jdbc.initialPoolSize=10
jdbc.minPoolSize=5
jdbc.maxPoolSize=30
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:c="http://www.springframework.org/schema/c"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:lang="http://www.springframework.org/schema/lang"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:task="http://www.springframework.org/schema/task"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.3.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-4.3.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
        
        <!-- 加载db.properties文件中的内容 中的key要有一定的规则 -->
        <context:property-placeholder location="testtx/db.properties"/>
        
        <!-- 配置数据源 -->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
            <property name="driverClass" value="${jdbc.driverClass}"/>
            <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
            <property name="user" value="${jdbc.user}"/>
            <property name="password" value="${jdbc.password}"/>
            <property name="initialPoolSize" value="${jdbc.initialPoolSize}"/>
            <property name="minPoolSize" value="${jdbc.minPoolSize}"/>
            <property name="maxPoolSize" value="${jdbc.maxPoolSize}"/>
        </bean>
        
        <!-- 二、创建JdbcTemplate对象,注入“数据源” -->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource"></property>
        </bean>

        <!-- 三、Spring声明式事务管理配置 -->
        <!-- 3.1 配置事务管理器类(事务切面) -->
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
        
        <!-- 开启注解扫描 -->
        <context:component-scan base-package="testtx2"></context:component-scan>
        <!-- 开启事务注解 , 指定事务切面! -->
        <tx:annotation-driven transaction-manager="txManager"/>

</beans>  

    

原文地址:https://www.cnblogs.com/kyleinjava/p/9035441.html