Spring框架

Posted littleskinny

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring框架相关的知识,希望对你有一定的参考价值。

Spring框架

1、学习地址

学习文档

官方学习文档

官方下载地址

下载地址

Github

Github

 

2、Spring基本介绍

起源

  • 作者

    Rod Johnson,为了解决企业应用开发的复杂性而创建的。

  • 发展历程

    • 2002年,首次推出了Spring框架的雏形,interface21

    • 2004年3月24日,正式发布了1.0版

 

概念、模块组成

  • Spring是一个轻量级的、非入侵的控制反转(IOC)面向切面(AOP)的容器(框架)

  • Spring是一个分层架构,由7个定义良好的模块组成

    • Spring AOP

      通过配置管理特性,Spring AOP模块直接将面向切面的编程功能,集成到了Spring框架中,Spring AOP模块为基于Spring应用程序中的对象提供了事务管理服务,通过使用Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。

    • Spring ORM

      Spring插入了若干个ORM框架,从而提供了ORM的对象管理工具,其中包括JDO,hibernate,ibatis SQL Map,所有这些都遵从Spring的事务管理和DAO的异常层次结构。

    • Spring DAO

      JDBC DAO抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商提供的错误信息,异常层次结构简化了错误处理,并且极大地降低了需要编写的异常处理代码数量(例如打开和关闭连接),Spring DAO面向JDBC的异常层次结构遵守了普通DAO的异常处理层次结构。

    • Spring Context

      Spring上下文是一个配置文件,向Spring框架提供上下文信息,Spring上下文包括企业服务,例如JNDI、EJB、电子邮件、国际化、校验和调度功能。

    • Spring Web

      Web上下文模块建立在应用程序上下文模块上,为基于Web应用程序提供可上下文,所以Spring框架支持与Jakarta Struts的集成 ,Web模块还简化了处理多部分请求和将请求参数绑定到域对象的工作。

    • Spring Web MVC

      Spring MVC框架是一个全功能的构建Web应用程序的MVC实现,通过策略接口,MVC框架成为高度可配置的,MVC容纳了大量视图技术,其中包括jsp,Velocity,Tiles,iText和POI。

    • Spring Core

      核心容器提供Spring框架的基本功能,核心容器的主要组件是Bean Factory,它是工厂模式的实现,BeanFactory使用控制反转(IOC)模式将应用程序的配置和依赖性规范与实际的应用代码分开。

 

3、IOC(Inversion Of Control)

  • 定义

    一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。

  • IOC理解

    • 控制:谁来控制对象的创建?

      传统应用程序的对象是由程序本身创建的,使用Spring后,对象是由Spring创建的。

    • 反转:程序本身不创建对象,而变成被动地接收对象。

  • 示例

    • 新建一个maven项目,在pom.xml中导入Spring依赖

      <dependencies>
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-webmvc</artifactId>
             <version>5.2.4.RELEASE</version>
         </dependency>
      </dependencies>

      导入了spring-webmvc之后,项目中多了以下几个依赖

     技术图片

    • 编写实体类

      package com.hmx.pojo;
      ?
      public class Hello {
      ?
      }

     

    • 传统方式创建对象

      Hello hello = new Hello();

     

    • 使用Spring创建对象

      1、在resources目录下新建beans.xml文件

          右键点击resources ---》 new ---》 XML Configuration File ---》Spring Config,可以创建spring的配置文件

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

       

      2、创建对象

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
             https://www.springframework.org/schema/beans/spring-beans.xsd">
      ?
         <!--语法:
             <bean id="对象变量名" class="new的对象所在的位置"></bean>      
      -->      
         <bean id="hello" class="com.hmx.pojo.Hello"></bean>
      ?
      </beans>

       

3、测试注入是否成功

    /*
   语法:
       获取Spring的上下文对象
       ApplicationContext context = new ClassPathXmlApplicationContext("创建的Spring配置xml文件名");
   
       取对象
       Hello hello = (Hello) context.getBean("xml文件中对应bean的id");
   */
   
   public static void main(String[] args) {
       
       ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
     
       Hello hello = (Hello) context.getBean("hello");
       
       //输出结果:com.hmx.pojo.Hello@3abbfa04,说明创建对象成功。
       System.out.println(hello);
  }

 

4、bean的作用域

  • singleton

    • 单例模式(默认机制)

    • 在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象

  • prototype

    • 原型模式

    • 在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象

以下4个只在Web开发中使用

  • request

  • session

  • application

  • websocket

 

5、DI( Dependency Injection )

  • 依赖注入理解

    • 依赖:对象的创建要依赖于spring容器

    • 注入:对象中的属性由容器来注入

  • 注入方式

    • 1、构造器注入

      • 1.1 、默认无参构造

        • 实体类

        package com.hmx.pojo;
        ?
        public class User {
        ?
           private String name;
           private int age;
        ?
           @Override
           public String toString() {
               return "User{" +
                       "name=‘" + name + ‘‘‘ +
                       ", age=" + age +
                       ‘}‘;
          }
        }
        • 注入

        <?xml version="1.0" encoding="UTF-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation=
                      "http://www.springframework.org/schema/beans
                       http://www.springframework.org/schema/beans/spring-beans.xsd">
        ?
           <bean id="user" class="com.hmx.pojo.User"></bean>
        </beans>
        • 测试

        public static void main(String[] args) {
           
           ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
           
           User user = (User) context.getBean("user");
           
           //输出结果:User{name=‘null‘, age=0}
           System.out.println(user.toString());
        ?
        }

       

      • 有参构造

        • 实体类

        package com.hmx.pojo;
        ?
        public class User {
        ?
           private String name;
           private int age;
        ?
           public User(String name,int age) {
               this.name = name;
               this.age = age;
          }
        ?
           @Override
           public String toString() {
               return "User{" +
                       "name=‘" + name + ‘‘‘ +
                       ", age=" + age +
                       ‘}‘;
          }
        }
        • 1.2 、通过下标创建

        <bean id="user" class="com.hmx.pojo.User">
           <constructor-arg index="0" value="Andy"/>
           <constructor-arg index="1" value="12"/>
        </bean>
        • 1.3 、通过类型创建

        <bean id="user" class="com.hmx.pojo.User">
           <constructor-arg type="java.lang.String" value="Andy"/>
           <constructor-arg type="int" value="12"/>
        </bean>
        • 1.4 、有参构造方法通过参数名创建

        <bean id="user" class="com.hmx.pojo.User">
               <constructor-arg name="name" value="Andy"/>
               <constructor-arg name="age" value="12"/>
        </bean>

     

    • 2、setter注入

      • 实体类

        • Address类

        public class Address {
           private String address;
        ?
           //此处省略setter和getter方法
        ?
           //此处省略toString方法
        }
        • Student类

        public class Student {
        ?
           private String name;
           private Address address;
           private String[] books;
           private List<String> hobbys;
           private Map<String, String> cards;
           private Set<String> games;
           private String wife;
           private Properties info;
        ?
           //此处省略setter和getter方法
        ?
           //此处省略toString方法
        }
      • 注入

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
             https://www.springframework.org/schema/beans/spring-beans.xsd">
      ?
         <!--Address类-->
         <bean id="address" class="com.hmx.Address" scope="prototype">
             <property name="address" value="火星"/>
         </bean>
      ?
         <!--Student类-->
         <bean id="student" class="com.hmx.Student">
             
             <!--普通值注入-->
             <property name="name" value="Andy"/>
             
             <!--Bean对象注入-->
             <property name="address" ref="address"/>
             
             <!--数组注入-->
             <property name="books">
                 <array>
                     <value>红楼梦</value>
                     <value>三国演义</value>
                     <value>西游记</value>
                     <value>水浒传</value>
                 </array>
             </property>
             
             <!--列表注入-->
             <property name="hobbys">
                 <list>
                     <value>读书</value>
                     <value>健身</value>
                 </list>
             </property>
             
             <!--Map注入-->
             <property name="cards">
                 <map>
                     <entry key="身份证号" value="111111222222223333"></entry>
                     <entry key="银行卡号" value="11848979283974982748"></entry>
                 </map>
             </property>
             
             <!--Set注入-->
             <property name="games">
                 <set>
                     <value>英雄联盟</value>
                     <value>和平精英</value>
                     <value>王者荣耀</value>
                 </set>
             </property>
             
             <!--Null注入-->
             <property name="wife">
                 <null/>
             </property>
             
             <!--Properties注入-->
             <property name="info">
                 <props>
                     <prop key="学号">20142375</prop>
                     <prop key="性别">男</prop>
                 </props>
             </property>
      ?
         </bean>
      </beans>
      • 测试

      public static void main(String[] args) {
         
         ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
         
         Student student = (Student) context.getBean("student");
         
         /*
         输出结果:
         Student{
        name=‘Andy‘,
        address=Address{address=‘火星‘},
        books=[红楼梦, 三国演义, 西游记, 水浒传],
        hobbys=[读书, 健身],
        cards={
        身份证号=111111222222223333,
        银行卡号=11848979283974982748
        },
        games=[英雄联盟, 和平精英, 王者荣耀],
        wife=‘null‘,
        info={学号=20142375, 性别=男}}
         */
         System.out.println(student.toString());
      }

       

    • 3、c命名和p命名空间注入

      • p命名空间注入,对应setter方式注入

        1、编写实体类

        public class User {
        ?
           private String name;
           private int age;
        ?
           //此处省略getter和setter方法
        ?
           //此处省略toString方法
        }

        2、在配置文件中导入p命名空间

        xmlns:p="http://www.springframework.org/schema/p"

        3、注入

        <bean id="user" class="com.hmx.pojo.User" p:name="安迪" p:age="26"></bean>

        4、测试

        public class Test {
           public static void main(String[] args) {
        ?
               ApplicationContext context = new ClassPathXmlApplicationContext("User.xml");
               User user = context.getBean("user", User.class);
               
               //输出结果:User{name=‘安迪‘, age=26}
               System.out.println(user.toString());
          }
        }
      • c命名空间注入,对应构造器方式注入

        1、编写实体类

        public class User {
        ?
           private String name;
           private int age;
           
           //此处省略无参构造
           
           public User(String name, int age) {
               this.name = name;
               this.age = age;
          }
        ?
           //此处省略getter和setter方法
        ?
           //此处省略toString方法
        }

        2、在配置文件中导入c命名空间

        xmlns:c="http://www.springframework.org/schema/c"

        3、注入

        <bean id="user" class="com.hmx.pojo.User" c:name="贝拉" c:age="18"></bean>

        4、测试

        public class Test {
           public static void main(String[] args) {
        ?
               ApplicationContext context = new ClassPathXmlApplicationContext("User.xml");
               User user = context.getBean("user", User.class);
               
               //输出结果:User{name=‘贝拉‘, age=18}
               System.out.println(user.toString());
          }
        }

 

6、Spring的自动装配

  • ByName

    本质是在容器中找到与需要注入的属性变量名相同的bean id的对象,并将该对象作为set方法的实参,通过执行set方法去为属性装配

    public class People {
    ?
       private Cat cat;
       
       public Cat getCat() {
           return cat;
      }
    ?
       public void setCat(Cat cat) {
           this.cat = cat;
      }
    }
    //自动在spring容器中找bean的id为Cat的类,然后将其注入进来,id="cat"

 

  • ByType

    会自动地在容器上下文中寻找和自己属性类型相对应的bean  id

    public class People {
       private Cat cat;
    }
    ?
    //自动在spring容器中找类型为Cat的类,然后将其注入进来,class="com.hmx.pojo.Cat"

 

7、注解实现自动注入

  • 实现自动注入的前提条件

<!--在Spring配置文件中添加 注解 的支持-->
<context:annotation-config/>
  • 实现方式

    • @AutoWired

      • @Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired;

      • @Autowired 等同于 @Autowired(required = true),表示注入的时候,该bean必须存在,否则就会注入失败。@Autowired(required = false),表示如果当前有bean直接注入,没有则跳过,不会报错。

      • 可以写在字段和setter方法上,写在字段上,那么就不需要再写setter方法

      • @Autowired采取的策略为ByType

      • 按照类型注入会产生一个问题,当一个类型有多个bean值的时候,会产生混乱,不知道具体注入哪一个

        <bean id="cat1" class="com.hmx.pojo.Cat"></bean>
        <bean id="cat2" class="com.hmx.pojo.Cat"></bean>
        public class People {
           @Autowired
           private Cat cat;
           //Could not autowire. There is more than one bean of ‘Cat‘ type.
        }

        此时需要和@Qualifier(value = "")一起使用,‘value =’ 可以省略,实现唯一的注入

        public class People {
        ?
           @Qualifier("cat1")
           @Autowired
           private Cat cat;
        }

     

    • @Resource

      • @Resource注解由J2EE提供,需要导入包

        javax.annotation.Resource

      • @Resource(name = "",type = 类名.class)

      • 可以写在字段和setter方法上,写在字段上,那么就不需要再写setter方法

      • @Resource默认按照ByName自动注入

        <bean id="cat1" class="com.hmx.pojo.Cat">
           <property name="name" value="布偶"/>
        </bean>
        ?
        <bean id="cat2" class="com.hmx.pojo.Cat">
           <property name="name" value="英短"/>
        </bean>
        //既没有指定name,又没有指定type,则自动按照byName方式进行装配
        public class People {
           @Resource
           private Cat cat1;
        }
        //指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
        public class People {
           @Resource(name = "cat1")
           private Cat cat1;
        }
        //指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常
        public class People {
           @Resource(type = Dog.class)
           private Cat cat1;
        }
        //同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
        public class People {
        ?
           @Resource(name = "cat1",type = Dog.class)
           private Cat cat1;
        }

 

8、Spring注解总结

  • 使用注解开发的前提条件

<!--在Spring配置文件中添加 扫描包 的支持-->
<context:component-scan base-package="包名"/>
  • @Component

    把普通pojo实例化到spring容器中,相当于配置文件中的<bean></bean>

    @Component的衍生注解

    • @Repository,用于标注数据访问层

    • @Service,用于标注服务层

    • @Controller,用于标注控制层

  • @Value("")

    放在属性上,给属性赋值,必须是String类型的属性

  • @AutoWired

    自动装配

  • @Resource

    自动装配

  • @Scope("")

    @Scope("prototype"),原型模式,每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例

    @Scope("singleton"),单例模式,在整个应用中,只创建bean的一个实例

 

9、AOP(Aspect Oriented Programming)

技术图片技术图片

 

  • 作用:

    通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术

    在Spring中提供声明式事务:允许用户自定义切面

  • 名词解释:

    • 横切关注点:

      • 跨越应用程序多个模块的方法或功能

      • 与我们业务逻辑无关的,但是我们要关注的功能,如日志、安全、缓存、事务等等

    • 切面(Aspect):

      • 横切关注点被模块化的特殊对象

      • 就是一个类

    • 通知(Advice):

      • 切面必须要完成的方法

      • 类中的一个方法

    • 目标(Target):

      • 被通知对象

    • 代理(Proxy):

      • 向目标对象应用通知之后创建的对象

    • 切入点(PointCut):

      • 切面通知执行的地点

    • 连接点(JointPoint):

      • 与切入点匹配的执行点

技术图片

 

  • 在Spring中实现AOP

    • 前提条件:导入织入依赖

      <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjweaver</artifactId>
         <version>1.9.4</version>
      </dependency>
    • 实现方式

      //抽象类
      public interface UserService {
      ?
         public void add();
         public void delete();
         public void update();
         public void query();
      }
      //抽象类的具体实现类
      public class UserServiceImpl implements UserService {
         
         public void add() {
             System.out.println("实现了add方法");
        }
      ?
         public void delete() {
             System.out.println("实现了delete方法");
        }
      ?
         public void update() {
             System.out.println("实现了update方法");
        }
      ?
         public void query() {
             System.out.println("实现了query方法");
        }
      }
      • 1 、原生态Spring API接口

        • 切面:log日志

          通知,前方法

          public class BeforeAdvice implements MethodBeforeAdvice {
             
             //method:要执行的目标对象的方法
             //args:参数
             //target:目标对象
             public void before(Method method, Object[] args, Object target) throws Throwable {
                 System.out.println(target.getClass().getName() + "类的" + method.getName() + "被执行了!");
            }
          }

          通知,后方法

          public class AfterAdvice implements AfterReturningAdvice {
             
             public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
                 System.out.println(target.getClass().getName() + "类的" + method.getName() + "被执行了!返回结果为" + returnValue);
            }
          }
        • Spring配置文件配置

          <?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"
                xsi:schemaLocation="http://www.springframework.org/schema/beans
                 https://www.springframework.org/schema/beans/spring-beans.xsd
                 http://www.springframework.org/schema/aop
                 https://www.springframework.org/schema/aop/spring-aop.xsd">
          ?
             <!--配置bean-->
             <bean id="userService" class="com.hmx.service.UserServiceImpl"/>
             <bean id="afterAdvice" class="com.hmx.log.AfterAdvice"/>
             <bean id="beforeAdvice" class="com.hmx.log.BeforeAdvice"/>
          ?
             <!--配置AOP-->
             <!--使用原生Spring API接口-->
             <aop:config>
                 <!--切入点-->
                 <aop:pointcut id="pointCut" expression="execution(* com.hmx.service.UserServiceImpl.*(..))"/>
                 <!--执行环绕-->
                 <aop:advisor advice-ref="beforeAdvice" pointcut-ref="pointCut"/>
                 <aop:advisor advice-ref="afterAdvice" pointcut-ref="pointCut"/>
             </aop:config>
          ?
          </beans>
        • 测试

          public class Test {
             public static void main(String[] args) {
                 
                 ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
                 //动态代理的是一类接口
                 UserService userService = context.getBean("userService", UserService.class);
                 
                 /*
                 输出结果:
                com.hmx.service.UserServiceImpl类的add被执行了!
          实现了add方法
          com.hmx.service.UserServiceImpl类的add被执行了!返回结果为null
                 */
                 userService.add();
            }
          }

       

      • 2 、自定义类

        • 自定义日志类

          public class DiyLog {
          ?
             public void before(){
                 System.out.println("------方法执行前------");
            }
          ?
             public void after(){
                 System.out.println("------方法执行后------");
            }
          }
        • Spring配置文件配置

          <?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"
                xsi:schemaLocation="http://www.springframework.org/schema/beans
                 https://www.springframework.org/schema/beans/spring-beans.xsd
                 http://www.springframework.org/schema/aop
                 https://www.springframework.org/schema/aop/spring-aop.xsd">
          ?
             <bean id="userService" class="com.hmx.service.UserServiceImpl"/>
             <bean id="divLog" class="com.hmx.log.DiyLog"/>
          ?
             <aop:config>
                 <!--自定义切面-->
                 <aop:aspect ref="divLog">
                     <!--切入点-->
                     <aop:pointcut id="pointCut" expression="execution(* com.hmx.service.UserServiceImpl.*(..))"/>
                     <!--通知-->
                     <aop:before method="before" pointcut-ref="pointCut"/>
                     <aop:after method="after" pointcut-ref="pointCut"/>
                 </aop:aspect>
             </aop:config>
          ?
          </beans>
        • 测试

          public class Test {
             public static void main(String[] args) {
                 
                 ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
                 //动态代理的是一类接口
                 UserService userService = context.getBean("userService", UserService.class);
                 
                 /*
                 输出结果:
                ------方法执行前------
          实现了add方法
          ------方法执行后------
                 */
                 userService.add();
            }
          }

       

      • 3 、注解

        • 前提

          <!--
          开启注解支持
          <aop:aspectj-autoproxy proxy-target-class="false"/>,默认jdk方式
          <aop:aspectj-autoproxy proxy-target-class="true"/>,表明为cglib方式
          -->
          <aop:aspectj-autoproxy/>
        • 注解实现

          //@Aspect表明这是个切面
          @Aspect
          public class DiyLog {
          ?
             @Before("execution(* com.hmx.service.UserServiceImpl.*(..))")
             public void before() {
                 System.out.println("------方法执行前------");
            }
          ?
             @After("execution(* com.hmx.service.UserServiceImpl.*(..))")
             public void after() {
                 System.out.println("------方法执行后------");
            }
          ?
             //在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
             @Around("execution(* com.hmx.service.UserServiceImpl.*(..))")
             public void round(ProceedingJoinPoint pjp) throws Throwable {
                 System.out.println("环绕执行前");
                 pjp.proceed();
                 System.out.println("环绕执行后");
            }
          }
        • 测试

          public class Test {
             public static void main(String[] args) {
                 
                 ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
                 //动态代理的是一类接口
                 UserService userService = context.getBean("userService", UserService.class);
                 
                 /*
                 输出结果:
                环绕执行前
          ------方法执行前------
          实现了add方法
          环绕执行后
          ------方法执行后------
                 */
                 userService.add();
            }
          }

 

10、Spring整合Mybatis

  • 学习文档

    学习文档

  • 所需依赖

    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.13</version>
       <scope>test</scope>
    </dependency>
    ?
    <dependency>
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
       <version>5.1.47</version>
    </dependency>
    ?
    <dependency>
       <groupId>org.mybatis</groupId>
       <artifactId>mybatis</artifactId>
       <version>3.5.2</version>
    </dependency>
    ?
    <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-webmvc</artifactId>
       <version>5.1.9.RELEASE</version>
    </dependency>
    ?
    <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-jdbc</artifactId>
       <version>5.1.9.RELEASE</version>
    </dependency>
    ?
    <dependency>
       <groupId>org.aspectj</groupId>
       <artifactId>aspectjweaver</artifactId>
       <version>1.9.5</version>
    </dependency>
    ?
    <dependency>
       <groupId>org.mybatis</groupId>
       <artifactId>mybatis-spring</artifactId>
       <version>2.0.2</version>
    </dependency>
    ?
    <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
       <version>1.16.10</version>
    </dependency>
  • 配置文件

    • spring-dao.xml

      <!--
      DataSource数据源配置
      sqlSessionFactory
      sqlSession
      -->
      ?
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
             https://www.springframework.org/schema/beans/spring-beans.xsd">
      ?
         <!--DataSource数据源配置:使用Spring的数据源来替换Mybatis的配置-->
         <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
             <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
             <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
             <property name="username" value="root"/>
             <property name="password" value="root"/>
         </bean>
      ?
         <!--sqlSessionFactory-->
         <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
             <property name="dataSource" ref="dataSource"/>
      ?
             <!--绑定Mybatis配置文件-->
             <property name="configLocation" value="classpath:mybatis-config.xml"/>
             <property name="mapperLocations" value="classpath:com/hmx/mapper/*.xml"/>
         </bean>
      ?
         <!--sqlSession-->
         <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
             <constructor-arg index="0" ref="sqlSessionFactory"/>
         </bean>
      ?
      </beans>
    • mybatis-config.xml

      <!--
      别名
      设置
      -->
      ?
      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE configuration
             PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
             "http://mybatis.org/dtd/mybatis-3-config.dtd">
      <!--configuration核心配置文件-->
      <configuration>
      ?
         <typeAliases>
             <typeAlias type="com.hmx.pojo.User"/>
         </typeAliases>
      ?
         <settings></settings>
      ?
      </configuration>
  • 方式一

    • applicationContext.xml

      <!--配置bean以及使用-->
      ?
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
             https://www.springframework.org/schema/beans/spring-beans.xsd">
      ?
         <import resource="spring.xml"/>
      ?
         <bean id="userMapper" class="com.hmx.mapper.UserMapperImpl">
             <property name="sqlSessionTemplate" ref="sqlSession"></property>
         </bean>
      ?
      </beans>
    • 实体类:User

      @Data
      public class User {
      ?
         private int id;
         private String name;
         private String pwd;
      }
    • 接口类:UserMapper.java

      public interface UserMapper {
         public List<User> selectUser();
      }
    • Mybatis的xml文件:UserMapper.xml

      <mapper namespace="com.hmx.mapper.UserMapper">
         <select id="selectUser" resultType="user">
            select * from mybatistest
         </select>
      </mapper>
    • 接口类的实现类:UserMapperImpl.java

      public class UserMapperImpl implements UserMapper {
      ?
         //和之前不同,我们现在所有操作都使用SqlSessionTemplate来执行
         private SqlSessionTemplate sqlSessionTemplate;
      ?
         public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
             this.sqlSessionTemplate = sqlSessionTemplate;
        }
      ?
         public List<User> selectUser() {
             UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class);
             return mapper.selectUser();
        }
      }
    • 测试

      public static void selectTest() {
      ?
         ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
         UserMapper sqlSession = context.getBean("userMapper", UserMapper.class);
         for (User user : sqlSession.selectUser()) {
             System.out.println(user);
        }
      }
  • 方式二

    • applicationContext.xml

      <?xml version="1.0" encoding="UTF8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
             https://www.springframework.org/schema/beans/spring-beans.xsd">
      ?
         <import resource="spring-dao.xml"/>
      ?
         <bean id="userMapper" class="com.hmx.mapper.UserMapperImpl">
             <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
         </bean>
      ?
      </beans>
    • 接口类的实现类:UserMapperImpl.java

      public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
         public List<User> selectUser() {
             return getSqlSession().getMapper(UserMapper.class).selectUser();
        }
      }

 

11、声明式事务

  • 事务的ACID原则

    • 原子性(Atomicity)

    • 一致性(Consistency)

    • 隔离性(Isolation)

    • 持久性(Persistence)

  • 为什么使用声明式事务?

    • 不使用事务,可能存在数据提交不一致的情况

    • 如果不在spring中配置声明式事务,我们就要在代码中手动编写事务

  • spring中的事务配置

    <!--配置声明式事务-->
       <bean id="transactionManage" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
           <property name="dataSource" ref="dataSource"/>
       </bean>
    ?
       <!--结合AOP实现事务的织入-->
       <!--配置事务通知-->
       <tx:advice id="txAdvice" transaction-manager="transactionManage">
           <!--给哪些方法配置事务-->
           <!--propagation:事务的传播特性-->
           <tx:attributes>
               <tx:method name="add" propagation="REQUIRED"/>
               <tx:method name="delete" propagation="REQUIRED"/>
               <tx:method name="update" propagation="REQUIRED"/>
               <tx:method name="select"/>
               <tx:method name="*" propagation="REQUIRED"/>
           </tx:attributes>
       </tx:advice>
    ?
       <!--配置事务切入-->
       <aop:config>
           <aop:pointcut id="pointCut" expression="execution(* com.hmx.mapper.*.*(..))"/>
           <aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/>
       </aop:config>

以上是关于Spring框架的主要内容,如果未能解决你的问题,请参考以下文章

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段

使用实体框架迁移时 SQL Server 连接抛出异常 - 添加代码片段

Spring boot:thymeleaf 没有正确渲染片段

What's the difference between @Component, @Repository & @Service annotations in Spring?(代码片段

spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象(代码片段