Spring框架详解


spring全家桶:spring , springmvc ,spring boot , spring cloud 

  spring: 出现是在2002左右,解决企业开发的难度。减轻对项目模块之间的管理,
          类和类之间的管理, 帮助开发人员创建对象,管理对象之间的关系。
             spring核心技术 ioc , aop 。能实现模块之间,类之间的解耦合。


  依赖:classa中使用classb的属性或者方法, 叫做classa依赖classb
  

------------------------------------------------------------------------------

框架怎么学: 框架是一个软件,其它人写好的软件。
 1)知道框架能做什么, mybatis--访问数据库, 对表中的数据执行增删改查。
 2)框架的语法, 框架要完成一个功能,需要一定的步骤支持的, 
 3)框架的内部实现, 框架内部怎么做。 原理是什么。
 4)通过学习,可以实现一个框架。


 
spring的第一个核心功能 ioc

IoC (Inversion of Control) : 控制反转, 是一个理论,概念,思想。
 描述的:把对象的创建,赋值,管理工作都交给代码之外的容器实现, 也就是对象的创建是有其它外部资源完成。

控制: 创建对象,对象的属性赋值,对象之间的关系管理。
反转: 把原来的由开发人员管理,创建对象的权限(任务)转移给代码之外的容器实现。 由容器代替开发人员管理对象。创建对象,
        给属性赋值。

正转:由开发人员在代码中,使用new 构造方法创建对象, 开发人员主动管理对象。
       public static void main(String args[]){
            Student student = new Student(); // 在代码中, 创建对象。--正转。

         }

容器:是一个服务器软件, 一个框架(spring)

为什么要使用 ioc : 目的就是减少对代码的改动, 也能实现不同的功能。 实现解耦合。 

java中创建对象有哪些方式:
  1. 构造方法 , new Student()
  2. 反射
  3. 序列化
  4. 克隆
  5. ioc :容器创建对象
  6. 动态代理


ioc的体现: 
   servlet  1: 创建类继承HttpServelt 
            2:  在web.xml 注册servlet , 使用<servlet-name> myservlet </servlet-name>
                                                 <servelt-class>com.bjpwernode.controller.MyServlet1</servlet-class>

            3. 没有创建 Servlet对象, 没有 MyServlet myservlet = new MyServlet()

            4. Servlet(类似) 是Tomcat服务器它能你创建的。 Tomcat也称为容器
                   Tomcat作为容器:里面存放的有Servlet对象, Listener(监听器) , Filter对象(过滤器)

 
  DI(依赖注入) 是ioc的技术实现,  
  DI(Dependency Injection) :依赖注入, 只需要在程序中提供要使用的对象名称就可以, 至于对象如何在容器中创建,
                              赋值,查找都由容器内部实现。

spring是使用的di实现了ioc的功能, spring底层创建对象,使用的是反射机制。

spring是一个容器,管理对象,给属性赋值, 底层是反射创建对象。

spring创建对象:默认调用的是无参数构造方法。

spring把java对象称为bean,所以我们也常常把创建一个bean,说是创建一个对象。
spring-beans.xsd是约束文件,和mybatis指定 dtd是一样的


    声明bean,就是告诉spring要创建某个类的对象
    id:对象的自定义名称,唯一值。spring通过这个名称找对象
    class:类的全限定名称(不能是接口,因为Spring是反射机制创建的对象,必须使用类)
    

    spring就完成 Someservice someservice = new SomeserviceImpl();
    spring是把创建好的对象放入到map中, spring框架有一个map存放对象的。
    springMap.put(id的值,对象);  例如springMap.put( "someservice" , new SomeserviceImpl());
    
    一个bean标签声明一个对象:
    <bean id="someService" class="com.bjpowernode.service.impl. SomeServiceImpl"/>

    初步使用spring容器创建对象:

    //使用spring容器创建的对象
    //1.指定spring配置文件的名称
    
    string config="beans.xml";
     
    //2.创建表示spring容器的对象,Applicationcontext
    // Applicationcontext就是表示Spring容器,通过容器获取对象了
    //classPathxmlApplicationcontext:表示从类路径中加载spring的配置文件
    
    Applicationcontext ac = new ClassPathxmlApplicationcontext(config);
    
    //从容器中获取某个对象,你要调用对象的方法
    ac.getBean( s: "someservice");
    
    di:依赖注入,表示创建对象,给属性赋值。  
     
    di的实现有两种:
        1.在spring的配置文件中,使用标签和属性完成,叫做基于XML的di实现
        2.使用spring中的注解,完成属性赋值,叫做基于注解的id实现
 
     
    
     注入:就是赋值的意思
        简单类型: spring中规定java的基本数据类型和string都是简单类型。
        di:给属性赋值
        1. set注入(设置注入) : spring调用类的set方法,你可以在set方法中完成属性赋值
        
        1)简单类型的set注入
        <bean id="xx" class="yyy">
            <property name="属性名字" value="此属性的值"/>
            <property. . . .>
            一个property只能给一个属性赋值
        </bean>


        2)引用类型的set注入 : spring调用类的set方法
        <bean id="xxx" class="yyy">
        <property name="属性名称” ref="bean的id(对象的名称)”/>
        </bean>
        
        例子:
        <bean id="mystudent" class="com.bjpowernode.ba02.student" >
            <property name="name" value="李四”/>
            <property name="age" value="26”/>
            <!--引用类型-->

        <!--引用类型-->
        <property name="school" ref="myschool"/> 
        <! --setschool(myschool)-->
        </bean>
        
        <!--声明school对象-->
        <bean id="myschool" class="com.bjpowernode.ba02.School">
            <property name="name" value="北京大学"/>
            <property name="address" value="北京的海淀区”/>
        </bean>


        
        
    2构造注入:spring调用类有参数构造方法,在创建对象的同时,在构造方法中给属性赋值。
        构造注入使用<constructor-arg>标签
        <constructor-arg>标签:一个<constructor-arg>表示构造方法一个参数。
        <constructor-arg>标签属性:
            name:表示构造方法的形参名
            index:表示构造方法的参数的位置,参数从左往右位置是0, 1 ,2的顺序value :构造方法的形参类型是简单类型的,使用value
            ref:构造方法的形参类型是引用类型的,使用ref
    
    <!--使用name属性实现构造注入--!>
        <bean id="mystudent" class="com.bjpowernode.ba03.student" >
        <constructor-arg name="myname" value="张三"/>
        <constructor-arg name="myage" value="20"/>
        <constructor-arg name="mySchool" ref="myschool"/>
        </bean>

    <! --
    引用类型的自动注入: 
    spring框架根据某些规则可以给引用类型赋值。·不用你在给引用类型赋值了,使用的规则常用的是byName,byType.
    
    1.byName(按名称注入) :
    java类中引用类型的属性名和spring容器中(配置文件)<bean>的id名称一样,
    且数据类型是一致的,这样的容器中的bean , spring能够赋值给引用类型。
    
    语法:
    <bean id="xx" class="yyy" autowire="byName ">
        简单类型属性赋值
    </bean>
    
    < ! --byName-->
            <bean id="mystudent" class="com.bjpowernode.ba04.student" autowire="byName">
            <property name="name" value="李四”/>
            <property name="age" value="26”/>
            <! --引用类型-->
            <!--<property name="school" ref="myschool"/>--></bean>
            
            
            <! --声明school对象-->
            <bean id="school" class="com.bjpowernode.ba04.school">
            <property name="name" value="清华大学"/>
            <property name="address" value="北京的海淀区”/>
            </bean>

    
    

    2.byType(按类型注入) : 
    java类中引用类型的数据类型和spring容器中(配置文件)<bean>的class属性
        是同源关系的,这样的bean能够赋值给引用类型
        
        同源就是一类的意思:
        1.java类中引用类型的数据类型和bean的class的值是一样的。
        2.java类中引用类型的数据类型和bean的class的值父子类关系的。
        3.java类中引用类型的数据类型和bean的class的值接口和实现类关系的
        语法:
        
        <bean id="xx" class="yyy" autowire="byTypet”>
        
            简单类型属性赋值
        </bean>

    

spring-conetxt 和 spring-webmvc是spring中的两个模块

spring-context:是ioc功能的,创建对象的。
spring-webmvc做web开发使用的, 是servlet的升级。 
spring-webmvc中也会用到spring-context中创建对象的功能的。


junit : 单元测试, 一个工具类库,做测试方法使用的。
单元:指定的是方法, 一个类中有很多方法,一个方法称为单元。

  使用单元测试
   1.需要加入junit依赖。
      <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

  2.创建测试作用的类:叫做测试类
    src/test/java目录中创建类

  3.创建测试方法

    1)public 方法
     2)没有返回值 void 
     3)方法名称自定义,建议名称是test + 你要测试方法名称
     4)方法没有参数
     5)方法的上面加入 @Test ,这样的方法是可以单独执行的。 不用使用main方法。

---------------------------------------------------------------------------------------------

1. 多个配置优势
  1.每个文件的大小比一个文件要小很多。效率高
  2.避免多人竞争带来的冲突。

  如果你的项目有多个模块(相关的功能在一起) ,一个模块一个配置文件。
  学生考勤模块一个配置文件,  张三
  学生成绩一个配置文件,      李四

  多文件的分配方式:
  1. 按功能模块,一个模块一个配置文件
  2. 按类的功能,数据库相关的配置一个文件配置文件, 做事务的功能一个配置文件, 做service功能的一个配置文件等


2.基于注解的di: 通过注解完成java对象创建,属性赋值。
  使用注解的步骤:
   1.加入maven的依赖 spring-context ,在你加入spring-context的同时, 间接加入spring-aop的依赖。
     使用注解必须使用spring-aop依赖
    
    2.在类中加入spring的注解(多个不同功能的注解)

    3.在spring的配置文件中,加入一个组件扫描器的标签,说明注解在你的项目中的位置

   学习的注解:
   
   
   
    <!--声明组件扫描器(component-scan),组件就是java对象
        base-package:指定注解在你的项目中的包名。
        component-scan工作方式: spring会扫描遍历base-package指定的包,
            把包中和子包中的所有类,找到类中的注解,按照注解的功能创建对象,或给属性赋值。
    
    
        
     1.@Component:
    
        icomponent:创建对象的,等同于<bean>的功能
        属性:value就是对象的名称,也就是bean的id值,
             value的值是唯一的,创建的对象在整个spring容器中就一个
        
        位置:在类的上面
        @component(value ="mystudent")等同于
    //<bean id="mystudent" cLass="com.bjpowernode.ba01.student"/>  
    //不指定对象名称,由spring提供默认名称:类名的首字母小写
    
    
    spring中和@component功能一致,创建对象的注解还有:
        1.@Repository (用在持久层类的上面):放在dao的实现类上面,表示创建dao对象,dao对象是能访问数据库的。
        2.@Service(用在业务层类的上面):放在service的实现类上面,创建service对象,service对象是做业务处理,可以有事务等功能的。
        3.@ControlLer(用在控制器的上面):放在控制器(处理器)类的上面,创建控制器对象的,控制器对象,能够接受用户提交的参数,显示请求的处理结果。
        以上三个注解的使用语法和CComponent一样的。都能创建对象,但是这三个注解还有额外的功能。@Repository , @service , @controller是给项目的对象分层的。I

    
    
        
     2.@Respotory
     3.@Service
     4.@Controller
     5.@Value
        例子:@value(value =“张飞”
        @vaLue:简单类型的属性赋值
        属性: value是string类型的,表示简单类型的属性值
        位置:1.在属性定义的上面,无需set方法,推荐使用。
             2.在set方法的上面

     
        
     6.@Autowired
        @Autowrired :spring框架提供的注解,实现的引用类型的赋值
        spring中通过注解给引用类型赋值,使用的是自动注入原理,支持byName,bytype
        @Autowired默认使用的是byType自动注入。
        
        位置:1.在属性定义的上面,无需set方法,推荐使用。
              2.在set方法的上面
              
        不用默认的:    @Qualifier(" mySchool")
                    @Autowired
      
              
        属性:required ,是一个boolean类型的,默认true
             required=true :表示引用类型赋值失败,程序报错,并终止执行。
             required=false :引用类型如果赋值失败,程序正常执行,引用类型是null
    
              
     7.@Resource
         
        引用类型Resource:
            来自jdk中的注解,spring框架提供了对这个注解的功能支持,可以使用它给引用类型赋值使用的也是自动注入原理,支持byName , byType .默认是byName
        位置:
             1.在属性定义的上面,无需set方法,推荐使用。
             2.在set方法的上面

        //默认是bvName :先使用byName自动注入,如果byName赋值失败再使用byType

    ioc能实现解耦合————-ioc能够实现业务对象之间的解耦合,例如service和dao对象之间的解耦合。

用户处理请求:
   用户form ,参数name ,age-----Servlet(接收请求name,age)---Service类(处理name,age操作)---dao类(访问数据库的)---mysql


==============================================================================================
第三章 aop

1.动态代理
  实现方式:jdk动态代理,使用jdk中的Proxy,Method,InvocaitonHanderl创建代理对象。
             jdk动态代理要求目标类必须实现接口

  cglib动态代理:第三方的工具库,创建代理对象,原理是继承。 通过继承目标类,创建子类。
             子类就是代理对象。 要求目标类不能是final的, 方法也不能是final的

2.aop动态代理的作用:
   1)在目标类源代码不改变的情况下,增加功能。
    2)减少代码的重复
    3)专注业务逻辑代码
    4)解耦合,让你的业务功能和日志,事务非业务功能分离。

3.Aop:面向切面编程, 基于动态代理的,可以使用jdk,cglib两种代理方式。
  Aop就是动态代理的规范化, 把动态代理的实现步骤,方式都定义好了, 
  让开发人员用一种统一的方式,使用动态代理。

4. AOP(Aspect Orient Programming)面向切面编程
  Aspect: 切面,给你的目标类增加的功能,就是切面。 像上面用的日志,事务都是切面。
          切面的特点: 一般都是非业务方法,独立使用的。
  Orient:面向, 对着。
  Programming:编程

  oop: 面向对象编程

  怎么理解面向切面编程 ? 
   1)需要在分析项目功能时,找出切面。
    2)合理的安排切面的执行时间(在目标方法前, 还是目标方法后)
    3)合理的安全切面执行的位置,在哪个类,哪个方法增加增强功能

  术语:
   1)Aspect:切面,表示增强的功能, 就是一堆代码,完成某个一个功能。非业务功能,
              常见的切面功能有日志, 事务, 统计信息, 参数检查, 权限验证。

   2)JoinPoint:连接点 ,连接业务方法和切面的位置。 就某类中的业务方法
    3)Pointcut : 切入点 ,指多个连接点方法的集合。多个方法
    4)目标对象: 给哪个类的方法增加功能, 这个类就是目标对象
    5)Advice:通知,通知表示切面功能执行的时间。

    说一个切面有三个关键的要素:
    1)切面的功能代码,切面干什么
    2)切面的执行位置,使用Pointcut表示切面执行的位置
    3)切面的执行时间,使用Advice表示时间,在目标方法之前,还是目标方法之后。

 5.aop的实现
   aop是一个规范,是动态的一个规范化,一个标准
    aop的技术实现框架:
    1.spring:spring在内部实现了aop规范,能做aop的工作。
              spring主要在事务处理时使用aop。
                 我们项目开发中很少使用spring的aop实现。 因为spring的aop比较笨重。


   2.aspectJ: 一个开源的专门做aop的框架。spring框架中集成了aspectj框架,通过spring就能使用aspectj的功能。
      aspectJ框架实现aop有两种方式:
       1.使用xml的配置文件 : 配置全局事务
        2.使用注解,我们在项目中要做aop功能,一般都使用注解, aspectj有5个注解。


 6.学习aspectj框架的使用。 
   1)切面的执行时间, 这个执行时间在规范中叫做Advice(通知,增强)
       在aspectj框架中使用注解表示的。也可以使用xml配置文件中的标签
        1)@Before
        2)@AfterReturning
        3)@Around
        4)@AfterThrowing
        5)@After

   2)表示切面执行的位置,使用的是切入点表达式。

        com.service.impl
        com.bjpowrnode.service.impl
        cn.crm.bjpowernode.service

  
    AspectJ定义了专门的表达式用于指定切入点。表达式的原型是:
    execution(modifiers-pattern? ret-type-pattern
    declaring-type-pattern?name-pattern(param-pattern)throws-pattern?)
    
    
    符号          意义
      *            0至多个任意字符
      ..           用在方法参数中。表示任意多个参数用在包名后,示当前包及其子包路径用在类名后。
      +           表示当前类及其子类用在接口后.表示情接口及其实现类

    
    解释:
    modifiers-pattern]访问权限类型
    ret-type-pattern返回值类型declaring-type-pattern包名类名
    name-pattern(param-pattern)方法名(参数类型和参数个数)
    throws-pattern抛出异常类型
    ﹖表示可选的部分

    
    execution(访问权限方法返回值 方法声明(参数) 异常类型)
    

    execution(* *..service.*.*(..))
      指定切入点为:任意公共方法。
    
    xecution(* set*(..))
    指定切入点为:任何一个以“set"开始的方法。
    
    
    execution(* com.xyz.service.*.*(..))
    指定切入点为:定义在service包里的任意类的任意方法。
 
    execution(* com.xyz.service..*.*(..))
    指定切入点为:定义在.service包或者子包里的任意类的任意方法。“.."出现在类名中时,后面必须跟“*”,表示包、子包下的所有类。
    
    execution(** ..service.*.*(..))
    指定所有包下的serivce子包下所有类(接口)中所有方法为切入点


    
    @Before:前置通知注解
    
        属性: value ,是切入点表达式,表示切面的功能执行的位置。
        位置;在方法的上面
        特点:
        1.在目标方法之前先执行的
        2.不会改变目标方法的执行结果
        3.不会影响目标方法的执行。
        
        
        
        @Before(value = "execution(public void com.bjpowernode.ba1.SomeServiceImpl.dosome(String,Integer))")
        public void myBefore(){
            //就是你切面要执行的功能代码
            System.out. println("前置通知,切面功能:在目标方法之前输出执行时间: "+ new Date());
                    }
            }

        <!--声明自动代理生成器:使用aspectj框架内部的功能,创建目标对象的代理对象。
        创建代理对象是在内存中实现的,修改目标对象的内存中的结构。创建为代理对象所以目标对象就是被修改后的代理对象.
        
        aspectj-autoproxy;会把spring容器中的所有的目标对象,一次性都生成代理对象。
        <aop :aspectj-autoproxy />

    使用aspectj实现aop的基本步骤:
    
    1.新建maven项目
    
    2.加入依赖
    1 ) spring依赖
    2 ) aspectj依赖
    3 ) junit单元测试
    
    3.创建目标类:接口和他的实现类。要做的是给类中的方法增加功能
    
    4.创建切面类:普通类
    1)在类的上面加入@Aspect
    2)在类中定义方法,方法就是切面要执行的功能代码在方法的上面加入aspectj中的通知注解,例如@Before有需要指定切入点表达式execution()
    
    5.创建sprinrtg的配置文件:声明对象,把对象交给容器统―管理声明对象你可以使用注解或者xml配置文件<bean>
    1)声明目标对象
    2)声明切面类对象
    3)声明aspectj框架中的自动代理生成器标签。
    自动代理生成器:用来完成代理对象的自动创建功能的。
    
    6.创建测试类,从spring容器中获取目标对象(实际就是代理对象)。
    通过代理执行方法,实现aop的功能增强。

    什么时候考虑使用aop技术
        1.当你要给一个系统中存在的类修改功能,但是原有类的功能不完善,但是你还有源代码,使用aop就增加功能

        2.你要给项目中的多个类,增加一个相同的功能,使用aop
        
        3.给业务方法增加事务,日志输出

    aop的实现框架
    
    1.spring实现了aop,实现方式是接口
    2.aspectj框架
        1.使用注解可以实现aop的功能

        2.使用xml配置文件中的标签实现aop功能


    aop中概念
    
        1.aspect:切面,表示给业务方法增加的功能,一般日志输出,事务,权限检查等是切面
        2.pointcut切入点,是一个或多个JoinPoint的集合,表示切面功能执行的位置
        3.advice :通知,也叫增强,表示切面执行的时间,在方法前,方法后等等
    
    
    JoinPoint:
        Joinpoint:业务方法,要加入切面功能的业务方法
        作用是:可以在通知方法中获取方法执行时的信息,例如方法名称,方法的实参。
        如果你的切面功能中需要用到方法的信息,就加入JoinPoint.
        这个JoinPoint参数的值是由框架赋予,必须是第一个位置的参数


    后置通知定义方法,方法是实现切面功能的。方法的定义要求:
        1.公共方法 public
        2.方法没有返回值
        3.方法名称自定义
        4.方法有参数的,推荐是object,参数名自定义
        
        @AfterReturning:后置通知
        属性:
            1.value切人点表达式
            2.returning自定义的变量,表示目标方法的返回值的。自定义变量名必须和通知方法的形参名一样。|


    
    @AfterReturning(value = "execution(* *..SomeserviceImpl.doother(..))",returning = "res")
        public void myAfterReturing(object res){
        
        // object res:是目标方法执行后的返回值,根据返回值做你的切面的功能处理
        
        system.out.println ("后置通知:在目标方法之后执行的,获取的返回值是:"+res);
        }
    
    
    环绕通知方法的定义格式
        1.public
        2.必须有一个返回值,推荐使用object
        3.方法名称自定义
        4.方法有参数,固定的参数 ProceedingJoinPoint
        

    @Around:环绕通知
        属性: value切入点表达式位置:在方法的定义什么特点:
        1.它是功能最强的通知
        2.在目标方法的前和后都能增强功能。
        3.控制目标方法是否被调用执行
        4.修改原来的目标方法的执行结果。影响最后的调用结果
        
        环绕通知,等同于jdk动态代理的,InvocationHandler接口

        
        
        参数: ProceedingJoinPoint就等同于Method
            作用:执行目标方法的
        返回值:就是目标方法的执行结果,可以被修改。
        
        
        
    目标类有接口,默认使用Jdk动态代理
    目标类没有接口,使用cglib动态代理,spring框架会自动应用cglib
    如果你期望目标类有接口,使用cglib动态代理,proxy-target-class="true":告诉框架要使用cglib动态代理
    <aop:aspectj-autoproxy proxy-target-class "true"/>
    
    
    
    
    
    sprtingde qiangda用处,具有强大的集合能力,tongguospring的ioc控制对象整合
    
    
    
====================================================================
    第四章: 把mybatis框架和spring集成在一起,向一个框架一样使用。

    用的技术是:ioc 。
    为什么ioc:能把mybatis和spring集成在一起,像一个框架, 是因为ioc能创建对象。
     可以把mybatis框架中的对象交给spring统一创建, 开发人员从spring中获取对象。
     开发人员就不用同时面对两个或多个框架了, 就面对一个spring


    mybatis使用步骤,对象
    1.定义dao接口 ,StudentDao
    2.定义mapper文件 StudentDao.xml
    3.定义mybatis的主配置文件 mybatis.xml
    4.创建dao的代理对象, StudentDao dao = SqlSession.getMapper(StudentDao.class);

       List<Student> students  = dao.selectStudents();


    要使用dao对象,需要使用getMapper()方法,
    怎么能使用getMapper()方法,需要哪些条件
    1.获取SqlSession对象, 需要使用SqlSessionFactory的openSession()方法。
    2.创建SqlSessionFactory对象。 通过读取mybatis的主配置文件,能创建SqlSessionFactory对象

    需要SqlSessionFactory对象, 使用Factory能获取SqlSession ,有了SqlSession就能有dao , 目的就是获取dao对象
    Factory创建需要读取主配置文件

    我们会使用独立的连接池类替换mybatis默认自己带的, 把连接池类也交给spring创建。


    主配置文件:
     1.数据库信息
     <environment id="mydev">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <!--数据库的驱动类名-->
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <!--连接数据库的url字符串-->
                    <property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
                    <!--访问数据库的用户名-->
                    <property name="username" value="root"/>
                    <!--密码-->
                    <property name="password" value="123456"/>
                </dataSource>
    2. mapper文件的位置
       <mappers>
            <mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
            <!--<mapper resource="com/bjpowernode/dao/SchoolDao.xml" />-->
        </mappers>


    步骤:
        1.新建maven项目
        2.加入maven的依赖
            1 ) spring依赖
            2) mybatis依赖
            3 ) mysql驱动
            4 ) spring的事务的依赖
            5 ) mybatis和spring集成的依赖:mybatis官方体用的,用来在spring项目中创建mybatis
            的SqlsesissonFactory , dao对象的
        3.创建实体类
        4.创建dao接口和mapper文件
        5.创建mybatis主配置文件
        6.创建spring的配置文件:声明mybatis的对象交给spring创建
        7.创建spring的配置文件:声明mybatis的对象交给spring创建
            1)数据源
            2 )sqlsessionFactory
            3) Dao对象
            4)声明自定义的service
        8.创建测试类,获取service对象,通过service调用dao完成数据库的访问

==============================================================
通过以上的说明,我们需要让spring创建以下对象
1.独立的连接池类的对象, 使用阿里的druid连接池
2.SqlSessionFactory对象
3.创建出dao对象

需要学习就是上面三个对象的创建语法,使用xml的bean标签。


连接池:多个连接Connection对象的集合, List<Connection>  connlist : connList就是连接池

通常使用Connection访问数据库
Connection conn =DriverManger.getConnection(url,username,password);
Statemenet stmt = conn.createStatement(sql);
stmt.executeQuery();
conn.close();


使用连接池
在程序启动的时候,先创建一些Connection
Connection c1 = ...
Connection c2 = ...
Connection c3 = ...
List<Connection>  connlist = new ArrayLits();
connList.add(c1);
connList.add(c2);
connList.add(c3);

Connection conn = connList.get(0);
Statemenet stmt = conn.createStatement(sql);
stmt.executeQuery();
把使用过的connection放回到连接池
connList.add(conn);


Connection conn1 = connList.get(1);
Statemenet stmt = conn1.createStatement(sql);
stmt.executeQuery();
把使用过的connection放回到连接池
connList.add(conn1);

==================================================================
spring的事务处理
回答问题
1.什么是事务
  讲mysql的时候,提出了事务。 事务是指一组sql语句的集合, 集合中有多条sql语句
  可能是insert , update ,select ,delete, 我们希望这些多个sql语句都能成功,
  或者都失败, 这些sql语句的执行是一致的,作为一个整体执行。


2.在什么时候想到使用事务
  当我的操作,涉及得到多个表,或者是多个sql语句的insert,update,delete。需要保证
  这些语句都是成功才能完成我的功能,或者都失败,保证操作是符合要求的。


  在java代码中写程序,控制事务,此时事务应该放在那里呢? 
     service类的业务方法上,因为业务方法会调用多个dao方法,执行多个sql语句

3.通常使用JDBC访问数据库, 还是mybatis访问数据库怎么处理事务
   jdbc访问数据库,处理事务  Connection conn ; conn.commit(); conn.rollback();
    mybatis访问数据库,处理事务, SqlSession.commit();  SqlSession.rollback();
    hibernate访问数据库,处理事务, Session.commit(); Session.rollback();


4.3问题中事务的处理方式,有什么不足
  1)不同的数据库访问技术,处理事务的对象,方法不同,
    需要了解不同数据库访问技术使用事务的原理
  2)掌握多种数据库中事务的处理逻辑。什么时候提交事务,什么时候回顾事务
  3)处理事务的多种方法。

  总结: 就是多种数据库的访问技术,有不同的事务处理的机制,对象,方法。

5.怎么解决不足
  spring提供一种处理事务的统一模型, 能使用统一步骤,方式完成多种不同数据库访问技术的事务处理。

  使用spring的事务处理机制,可以完成mybatis访问数据库的事务处理
  使用spring的事务处理机制,可以完成hibernate访问数据库的事务处理。

6.处理事务,需要怎么做,做什么
  spring处理事务的模型,使用的步骤都是固定的。把事务使用的信息提供给spring就可以了

  1)事务内部提交,回滚事务,使用的事务管理器对象,代替你完成commit,rollback
     事务管理器是一个接口和他的众多实现类。
      接口:PlatformTransactionManager ,定义了事务重要方法 commit ,rollback
      实现类:spring把每一种数据库访问技术对应的事务处理类都创建好了。
               mybatis访问数据库---spring创建好的是DataSourceTransactionManager
                  hibernate访问数据库----spring创建的是HibernateTransactionManager

     怎么使用:你需要告诉spring 你用是那种数据库的访问技术,怎么告诉spring呢?
      声明数据库访问技术对于的事务管理器实现类, 在spring的配置文件中使用<bean>声明就可以了
      例如,你要使用mybatis访问数据库,你应该在xml配置文件中
      <bean id=“xxx" class="...DataSourceTransactionManager"> 


  2)你的业务方法需要什么样的事务,说明需要事务的类型。
     说明方法需要的事务:
        1)事务的隔离级别:有4个值。
        DEFAULT:采用 DB 默认的事务隔离级别。MySql 的默认为 REPEATABLE_READ; Oracle默认为 READ_COMMITTED。
        ➢ READ_UNCOMMITTED:读未提交。未解决任何并发问题。
        ➢ READ_COMMITTED:读已提交。解决脏读,存在不可重复读与幻读。
        ➢ REPEATABLE_READ:可重复读。解决脏读、不可重复读,存在幻读
        ➢ SERIALIZABLE:串行化。不存在并发问题。

      2) 事务的超时时间: 表示一个方法最长的执行时间,如果方法执行时超过了时间,事务就回滚。
          单位是秒, 整数值, 默认是 -1. 

       3)事务的传播行为 : 控制业务方法是不是有事务的, 是什么样的事务的。
            7个传播行为,表示你的业务方法调用时,事务在方法之间是如果使用的。

            PROPAGATION_REQUIRED
            PROPAGATION_REQUIRES_NEW
            PROPAGATION_SUPPORTS
            以上三个需要掌握的

            PROPAGATION_MANDATORY
            PROPAGATION_NESTED
            PROPAGATION_NEVER
            PROPAGATION_NOT_SUPPORTED

  3)事务提交事务,回滚事务的时机
     1)当你的业务方法,执行成功,没有异常抛出,当方法执行完毕,spring在方法执行后提交事务。事务管理器commit
     
      2)当你的业务方法抛出运行时异常或ERROR, spring执行回滚,调用事务管理器的rollback
         运行时异常的定义: RuntimeException  和他的子类都是运行时异常, 例如NullPointException , NumberFormatException
      
      3) 当你的业务方法抛出非运行时异常, 主要是受查异常时,提交事务
        受查异常:在你写代码中,必须处理的异常。例如IOException, SQLException


总结spring的事务
  1.管理事务的是 事务管理和他的实现类
  2.spring的事务是一个统一模型
     1)指定要使用的事务管理器实现类,使用<bean>
      2)指定哪些类,哪些方法需要加入事务的功能
      3)指定方法需要的隔离级别,传播行为,超时


      你需要告诉spring,你的项目中类信息,方法的名称,方法的事务传播行为。


spring框架中提供的事务处理方案
1.适合中小项目使用的, 注解方案。
  spring框架自己用aop实现给业务方法增加事务的功能, 使用@Transactional注解增加事务。
  @Transactional注解是spring框架自己注解,放在public方法的上面,表示当前方法具有事务。
  可以给注解的属性赋值,表示具体的隔离级别,传播行为,异常信息等等

  使用@Transactional的步骤:
  1.需要声明事务管理器对象
    <bean id="xx" class="DataSourceTransactionManager">

  2.开启事务注解驱动, 告诉spring框架,我要使用注解的方式管理事务。
    spring使用aop机制,创建@Transactional所在的类代理对象,给方法加入事务的功能。
    spring给业务方法加入事务:
        在你的业务方法执行之前,先开启事务,在业务方法之后提交或回滚事务,使用aop的环绕通知
       
         @Around("你要增加的事务功能的业务方法名称")
         Object myAround(){
           开启事务,spring给你开启
              try{
                 buy(1001,10);
                  spring的事务管理器.commit();
              }catch(Exception e){
             spring的事务管理器.rollback();
              }
             
         }

  3.在你的方法的上面加入@Trancational


2.适合大型项目,有很多的类,方法,需要大量的配置事务,使用aspectj框架功能,在spring配置文件中
  声明类,方法需要的事务。这种方式业务方法和事务配置完全分离。

  实现步骤: 都是在xml配置文件中实现。 
   1)要使用的是aspectj框架,需要加入依赖
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.2.5.RELEASE</version>
    </dependency>

    2)声明事务管理器对象
     
    <bean id="xx" class="DataSourceTransactionManager">

    
    3) 声明方法需要的事务类型(配置方法的事务属性【隔离级别,传播行为,超时】)

    4) 配置aop:指定哪些哪类要创建代理。


================================================================================
第六章: web项目中怎么使用容器对象。

1.做的是javase项目有main方法的,执行代码是执行main方法的,
  在main里面创建的容器对象 
  ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

2.web项目是在tomcat服务器上运行的。 tomcat一起动,项目一直运行的。


需求:
web项目中容器对象只需要创建一次,  把容器对象放入到全局作用域ServletContext中。

怎么实现:
   使用监听器 当全局作用域对象被创建时 创建容器 存入ServletContext

    监听器作用:
    1)创建容器对象,执行 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    2)把容器对象放入到ServletContext, ServletContext.setAttribute(key,ctx)

    监听器可以自己创建,也可以使用框架中提供好的ContextLoaderListener


     private WebApplicationContext context;
     public interface WebApplicationContext extends ApplicationContext


    ApplicationContext:javase项目中使用的容器对象
    WebApplicationContext:web项目中的使用的容器对象

    把创建的容器对象,放入到全局作用域
     key: WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
           WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
     value:this.context

     servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值