【SSM框架 二】Spring

二、Spring

1、简介

Spring是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架

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

  • 2004年3月24日,Spring框架以interface21为基础,经过重新设计发布了1.0正式版

  • 开源的免费框架

  • 轻量级非入侵式框架

  • 支持对事务的处理,对框架整合的支持

  • 官方网站:https://spring.io/

  • 5.2.23官方文档:https://docs.spring.io/spring-framework/docs/current/reference/html/

  • api文档:https://docs.spring.io/spring-framework/docs/current/javadoc-api/

  • 老版本文档:https://docs.spring.io/spring-framework/docs/5.0.10.RELEASE/spring-framework-reference/(更改地址中间的版本号访问响应版本)

  • 老版本jar包下载地址:https://repo.spring.io/ui/native/release/org/springframework/spring

  • github下载地址:https://github.com/spring-projects/spring-framework

  • maven仓库

    • <!-- 使用该库可以帮你下载其他spring的库(包含aop,beans,context,core,expression,web) -->
      <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>5.3.23</version>
      </dependency>
      
    • <!-- 和Mybatis整合时,需要的库 -->
      <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>5.3.23</version>
      </dependency>			
      

2、IOC理论思想

IOC全称是Inversion of Control,控制反转

它是一种设计思想,由容器将设计好的对象交给容器控制,而非对象内部直接new

传统的Java设计中,直接会在对象的内部通过new进行对象的创建,是程序主动创建以来对象;

对Ioc来说,有一个专门的容器专门管理这些对象的生命周期,控制对象的创建;所以在Ioc中,是通过Ioc容器控制对象,由Ioc容器控制外部资源的获取

3、Hello Spring

bean.xml

<?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">

<!-- id为bean对象的名字,可以随便取,和getbean()的参数保持一致-->
<!-- class为该bean对象的类型全限名-->
    <bean id="hello1" class="com.daban.pojo.Hello">
<!--     该对象里的属性赋值,实体类里必须有set方法,才可以-->
<!--        name为属性名-->
<!--        value为属性值(基本类型使用)-->
<!--        ref为引用另一个对象的bean的id(非基本类型使用)-->
        <property name="str" value="我是注入的字符串"/>
        <property name="t" ref="tid"/>
    </bean>
    <bean id="tid" class="com.daban.pojo.T">
        <property name="i" value="1"/>
    </bean>
</beans>

测试类

import com.daban.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Mytest {
    public static void main(String[] args) {
        // 获取spring的上下文对象
        // 参数可以有多个xml文件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        // 由上下文对象得到bean对象
        // 第一个参数为对象的名字(对应xml的bean标签中的id值)
        // 第二个参数为该bean对象的类型,避免了强制类型转换
        Hello hello = applicationContext.getBean("hello1", Hello.class);
        System.out.println(hello.toString());

    }
}

4、IOC创建对象的方式

4.1 无参构造构造器注入

​ 默认使用无参构造器

4.2 有参构造器注入

三种方式,只能使用其中之一

  • 变量索引+值的方式

    • <constructor-arg index="0" value="野山鸡">
      
  • 类型+值的方式,如果两个String就不太好分辨,不推荐

    • <constructor-arg type="java.lang.String" value="野山鸡"/>
      
  • 变量名+值的方式

    • <constructor-arg name="name" value="野山鸡"/>
      

总结:在配置文件被加载的时候,容器中管理的对象就已经被初始化了

5、Spring的配置

5.1 别名

给bean的id取一个别名。设置别名后,使用别名和原先的名字都可以

<alias name="user" alias="user2"/>

5.2 Bean的配置

属性作用备注
idbean的唯一标识,类似与对象名
classbean所对应的类全限名
name取别名,可以取多个,和alisa标签类似

5.3 import

一般用于团队开发使用,把其他多个配置文件合并到一个配置文件中,加载配置文件时,只加载一个就行

<import resource="bean2.xml"/>

6、DI依赖注入

6.1 构造方法注入

详看《IOC创建对象的方式》

6.2 set方法注入

<?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="student" class="com.daban.pojo.Student">
        <!--基本类型-->
        <property name="name" value="青山"/>
        <!--类类型-->
        <property name="address" ref="address"/>
        <!--数组类型-->
        <property name="book">
           <array>
               <value>西游记</value>
               <value>三国演义</value>
               <value>红楼梦</value>
               <value>水浒传</value>
           </array>
        </property>
        <!--列表类型-->
        <property name="hobbys">
            <list>
                <value>唱歌</value>
                <value>弹吉他</value>
                <value>骑行</value>
            </list>
        </property>
        <!--map类型-->
        <property name="card">
            <map>
                <entry key="身份证" value="12345512351512553"/>
                <entry key="银行卡" value="662522512525221"/>
            </map>
        </property>
        <!--set类型-->
        <property name="games">
            <set>
                <value>吃鸡</value>
                <value>LOL</value>
            </set>
        </property>
        <!--properties类型-->
        <property name="info">
            <props>
                <prop key="username">张三</prop>
                <prop key="password">112233</prop>
            </props>
        </property>
        <!--null类型-->
        <property name="wife">
            <null/>
        </property>

    </bean>
    <bean id="address" class="com.daban.pojo.Address">
        <property name="address" value="陕西西安"/>
    </bean>
</beans>

6.3 扩展注入

  • p命名空间注入(和set方法注入作用一样)

    • 需要加入p的命名空间
      xmlns:p=“http://www.springframework.org/schema/p”

    • <bean id="user" class="com.daban.pojo.User" p:age="12" p:name="雪山"/>
      
  • c命名空间注入(和构造器方法注入作用一样)

    • 需要加入c的命名空间
      xmlns:c=“http://www.springframework.org/schema/c”

    • <bean id="user" class="com.daban.pojo.User" c:age="12" c:name="青山"/>
      <bean id="user" class="com.daban.pojo.User"  c:_0="青山" c:_1="13" />
      

6.4、Bean的作用域

bean标签的属性中设置scope

作用域描述备注
singleton单例模式每次从容器中get,就会的到同一个对象
prototype原型模式每次从容器中get,就会的到一个新对象
request再一次请求中
session再一次会话中
application在一个应用中

7、Bean的自动装配

Spring中装配的三种方式

  • 在xml中显式的配置
  • 在java中显式的配置
  • 隐式的自动装配

7.1 正常装配

<bean id="person" class="com.daban.pojo.Person">
    <property name="name" value="川崎"/>
    <property name="cat" ref="cat"/>
    <property name="dog" ref="dog"/>
</bean>
<bean id="cat" class="com.daban.pojo.Cat"/>
<bean id="dog" class="com.daban.pojo.Dog"/>

7.2 自动装配

<!--    
		使用autowire属性来自动装配
		byName:查找该对象set方法后的值对应的beanid(保证id唯一)
        byType:查找该对象和自己属性类型相同的bean(有多个同类型,将无法装配,对应属性bean的id可以省略)
-->
    <bean id="person" class="com.daban.pojo.Person" autowire="byName">
        <property name="name" value="川崎"/>
    </bean>
    <bean id="cat" class="com.daban.pojo.Cat"/>
    <bean id="dog" class="com.daban.pojo.Dog"/>

7.3 使用注解自动装配

7.3.1 要使用注解的准备
  • 导入需要的约束context

    • xm<beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             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:annotation-config/>
      
7.3.2 注解解释
注解解释备注
@Autowired直接使用在需要装配的属性上使用后可以省去set方法
@Qualifier(value = “xxx”)匹配id为value值的bean自动装配环境复杂bean不唯一时使用
@Resourcejava的自动装配先用名字查询,查不到使用类型
@Nullable该字段可以为null

8、使用注解开发

使用注解必须保证aop包的导入

必须导入约束context

<?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: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:annotation-config/>
<!--    指定要扫描的包,这个包下的注解会生效-->
    <context:component-scan base-package="com.daban.pojo"/>
注解描述备注
@Component放在类上,说明被spring管理,将该类放在容器中就是bean
@Value(“XXX”)属性注入,属性上复杂的属性建议使用配置文件
@Repository和@Component一样,只是在dao层使用这个
@Service和@Component一样,只是在Service层使用这个
@Controller和@Component一样,只是在Controller层使用这个
@Scope(“xxx”)bean的作用域

9、使用java的方式配置spring

实体类

package com.daban.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//@Component注册一个组件,在这里可以省略
@Component
public class User {
    @Value("hhhhh")
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

配置类

package com.daban.config;

import com.daban.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

//@Configuration代表这是一个配置类,可省略
//@Bean相当于注册一个bean,id就是方法名,class就是方法返回值
@Configuration
public class MyConfig {
    @Bean
    public User getUser(){
        return new User();
    }
}

测试类

import com.daban.config.MyConfig;
import com.daban.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        User user = context.getBean("getUser", User.class);
        System.out.println(user.toString());
    }
}

10、代理模式

SpringAOP的底层就使用代理模式

10.1 静态代理

角色分析:

  • 抽象角色:一般会使用接口或抽象类来实现
  • 真是角色:被代理的对象
  • 代理角色:去代理正式角色,代理的过程中,会做一些附属操作
  • 客户:访问代理对象的人

静态代理模式的优点:

  • 可以是真是角色操作更加纯粹,不用关心一些公共业务
  • 公共业务交给代理角色,实现了业务的分工
  • 公共业务发生扩展时,方便集中管理

静态代理模式的缺点:

  • 一个真实角色就要产生一个代理角色,代码量会翻倍,开发效率变低(使用动态代理解决)

代码步骤:

1、接口

package com.daban.demo01;

public interface Rent {
    public void rent();
}

2、真实角色

package com.daban.demo01;

public class Host implements Rent {

    private int NO;

    public Host() {
    }

    public Host(int NO) {
        this.NO = NO;
    }

    @Override
    public void rent() {
        System.out.println(NO+"号房东要出租房子");
    }
}

3、代理角色

package com.daban.demo01;

public class Proxy implements Rent{
    private Host host;

    public Proxy() {
    }

    public Proxy(Host host) {
        this.host = host;
    }

    @Override
    public void rent() {
        seeHouse();
        fare();
        host.rent();
    }
    public void seeHouse(){
        System.out.println("中介带你看房");
    }
    public void fare(){
        System.out.println("收取中介费");
    }
}

4、客户端访问代理角色

package com.daban.demo01;

public class Client {
    public static void main(String[] args) {
        Proxy proxy = new Proxy(new Host(2));
        proxy.rent();
    }
}

10.2 动态代理

  • 动态代理和静态代理角色一样
  • 动态代理类是动态生成的,不是我们创建的
  • 动态代理分为两大类:
    • 基于接口的动态代理:JDK动态代理【这里使用这个】
    • 基于类的动态代理:cglib

基本示例:

接口:

package com.daban.demo02;

public interface Rent {
    public void rent();
}

实现类:

package com.daban.demo02;


public class Host implements Rent  {

    private int NO;

    public Host() {
    }
    public Host(int NO) {
        this.NO = NO;
    }

    @Override
    public void rent() {
        System.out.println(NO+"号房东要出租房子");
    }
}

动态生成类:

package com.daban.demo02;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//使用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {

    //被代理的接口
    private Rent rent;
    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成得到的代理类
    public Object getProxy(){
       return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(),this);
    }
    //处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        Object result = method.invoke(rent, args);
        fare();
        return result;
    }
    public void seeHouse(){
        System.out.println("中介带你看房");
    }
    public void fare(){
        System.out.println("收取中介费");
    }
}

测试类:

package com.daban.demo02;

public class Client {
    public static void main(String[] args) {
        //真实角色
        Host host = new Host(3);
        //用这个来生成代理类
        ProxyInvocationHandler handler = new ProxyInvocationHandler();

        handler.setRent(host);
        //生成代理类
        Rent proxy =(Rent)handler.getProxy();
        proxy.rent();
    }
}

通用示例:

接口:

package com.daban.demo03;

public interface UserService {
    void add();
    void delete();
    void update();
    void select();
}

实现类

package com.daban.demo03;

public class UserServiceImp implements UserService{
    @Override
    public void add() {
        System.out.println("增加用户");
    }

    @Override
    public void delete() {
        System.out.println("删除用户");
    }

    @Override
    public void update() {
        System.out.println("修改用户");
    }

    @Override
    public void select() {
        System.out.println("查询用户");
    }
}

动态生成类(通用了):

package com.daban.demo03;

import com.daban.demo02.Rent;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//使用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {

    //被代理的接口
    private Object target;
    public void setTarget(Object target) {
        this.target = target;
    }

    //生成得到的代理类
    public Object getProxy(){
       return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }
    //处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }
    //增加想要的附属功能,不用改变原代码
    public void log(String msg){
        System.out.println("执行了"+msg+"方法");
    }
}

测试类:

package com.daban.demo03;

public class Client {
    public static void main(String[] args) {
        UserServiceImp userServiceImp = new UserServiceImp();
        ProxyInvocationHandler handler = new ProxyInvocationHandler();
        handler.setTarget(userServiceImp);
        UserService proxy = (UserService) handler.getProxy();
        proxy.add();
    }
}

11、AOP实现方式

11.1 什么是AOP

什么是AOP:面向切面编程

11.2 Aop在Spring中的作用

名词:

  • 横切关注点:跨越应用程序多个模块的方法和功能。如日志,安全,缓存,事务
  • 切面(ASPECT):横切关注点被模块化的对象,他是一个类。(例如Log类)
  • 通知(Advice):切面必须要完成的工作,即它类中的一个方法。(例如Log类中的方法)
  • 目标(Target):被通知对象。(接口)
  • 代理(Proxy):向目标对象应用通知之后创建的对象。(生成的代理类)
  • 切入点(PointCut):切面通知执行地点的定义
  • 连接点(JointPoint):与切入点匹配的执行点

SpringAOP中,通过Advice定义横切逻辑,支持五种类型的Advice

通知类型连接点实现接口
前置通知方法方法前org.springframework.aop.MethodBeforeAdvice
后置通知方法后org.springframework.aop.AfterReturningAdvice
环绕通知方法前后org.aopalliance.intercept.MethodInterceptor
异常抛出通知方法抛出异常org.springframework.aop.ThrowsAdvice
引介通知类中增加新的方法属性org.springframework.aop.IntroductionInterceptor

即,AOP在不改变源代码的情况下,增加新功能

11.3 使用Spring实现AOP

11.3.1 使用前需要导入依赖包
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.9.1</version>
    <scope>runtime</scope>
</dependency>
11.3.2 方式一:使用原生的spring api接口
  1. 准备业务接口
package com.daban.service;

public interface UserService {
    void add();
    void delete();
    void update();
    void select();
}
  1. 准备业务实现类
package com.daban.service;

public class UserServiceImp implements UserService{
    @Override
    public void add() {
        System.out.println("增加了一个用户");
    }
    @Override
    public void delete() {
        System.out.println("删除了一个用户");
    }
    @Override
    public void update() {
        System.out.println("改变了一个用户");
    }
    @Override
    public void select() {
        System.out.println("查询了一个用户");
    }
}
  1. 准备需要切入的类
package com.daban.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
//需要切入的类需要实现相应的接口,11.2中五种接口都可以,扮演不同的方式
public class Log implements MethodBeforeAdvice {
    /**
     * method:要执行的目标对象的方法
     * args:参数
     * target:目标对象
     */
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行");
    }
}
  1. 准备配置文件
<?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
       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-->
    <bean id="userService" class="com.daban.service.UserServiceImp"/>
    <bean id="log" class="com.daban.log.Log"/>
    <bean id="afterLog" class="com.daban.log.AfterLog"/>
    <!--方式一、使用原生的spring api接口-->
    <!--配置aop,需要导入aop的约束-->
 	<aop:config>
        <!--切入点配置-->
        <!--expression表达式:execution(* com.daban.service.UserServiceImp.*(..))-->
        <!--id为切入点的名字-->
        <aop:pointcut id="pointcut" expression="execution(* com.daban.service.UserServiceImp.*(..))"/>
        <!--执行环绕增加-->
        <!--advice-ref:要切入的类-->
        <!--pointcut-ref:要切入的位置-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
     </aop:config>

  1. 测试类
import com.daban.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //动态代理类代理的是接口,所以这里使用UserService接口,而不使用实现类
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
    }
}
11.3.3 方式二:自定义类
  1. 准备业务接口,和方式一相同
  2. 准备业务接口的实现,和方式一相同
  3. 自定义一个类(切面)
package com.daban.diy;

public class DiyPointcut {
    public void before(){
        System.out.println("********方法执行前********");
    }
    public void after(){
        System.out.println("========方法执行后========");
    }
}
  1. 准备配置文件
<?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
       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-->
    <bean id="userService" class="com.daban.service.UserServiceImp"/>
    <bean id="log" class="com.daban.log.Log"/>
    <bean id="afterLog" class="com.daban.log.AfterLog"/>

    <!--方式二、自定义类-->
    <bean id="diy" class="com.daban.diy.DiyPointcut"/>
    <aop:config>
        <!-- 自定义切面,ref是要引用(切入)的类-->
        <aop:aspect ref="diy">
            <!--切入点-->
            <aop:pointcut id="pointcut" expression="execution(* com.daban.service.UserServiceImp.*(..)))"/>
            <!-- method:要切入的方法,pointcut-ref:切入点-->
            <aop:after method="after" pointcut-ref="pointcut"/>
            <aop:before method="before" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>
</beans>
  1. 测试类,和方式一相同
11.3.4 方式三:使用注解实现
  1. 准备业务接口,和方式一相同
  2. 准备业务接口的实现,和方式一相同
  3. 自定义一个类(切面)
package com.daban.diy;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect//标注这个类是一个切面
public class AnnotationPointCut {
    //设置切入点在要切入的方法上
    @Before("execution(* com.daban.service.UserServiceImp.*(..)))")
    public void before(){
        System.out.println("********注解方式方法执行前********");
    }
    @After("execution(* com.daban.service.UserServiceImp.*(..)))")
    public void after(){
        System.out.println("========注解方式方法执行后========");

    }
}
  1. 准备配置文件
<!--方式三、使用注解-->
<bean id="anntation" class="com.daban.diy.AnnotationPointCut"/>
<!-- 开启注解支持-->
<aop:aspectj-autoproxy/>
  1. 测试类,和方式一相同

12、整合Mybatis

12.1 回忆mybatis

步骤:

  1. 导入jar包

​ junit,mybatis,mysql数据库,spring相关,aop植入,mybatis-spring

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </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.11</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.23</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.9.1</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.2</version>
    </dependency>
</dependencies>
  1. 写实体类
package com.daban.pojo;

import lombok.Data;

@Data
public class User {
    private int id;
    private String name;
    private String pwd;
}
  1. 写mybatis核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="com.daban.pojo"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" 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="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>
  1. 编写接口
package com.daban.mapper;

import com.daban.pojo.User;

import java.util.List;

public interface UserMapper {
   public List<User> getUser();
}
  1. 编写接口对应的mapper文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.daban.mapper.UserMapper">
    <select id="getUser" resultType="user">
        select * from mybatis.user
    </select>
</mapper>
  1. 测试
import com.daban.mapper.UserMapper;
import com.daban.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class MyTest {
    @Test
    public void test() throws IOException {
        String resources = "mybatis-config.xml";
        InputStream resource = Resources.getResourceAsStream(resources);
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resource);
        SqlSession sqlSession = build.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> user = mapper.getUser();
        for (User user1 : user) {
            System.out.println(user1);
        }
    }
}

12.2 mybatis-spring

  1. 导入jar包
  2. 写实体类
  3. 写mybatis核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="com.daban.pojo"/>
    </typeAliases>
</configuration>
  1. 编写接口
package com.daban.mapper;

import com.daban.pojo.User;

import java.util.List;

public interface UserMapper {
   public List<User> getUser();
}
  1. 编写接口对应的mapper文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.daban.mapper.UserMapper">
    <select id="getUser" resultType="user">
        select * from mybatis.user
    </select>
</mapper
  1. 编写接口的实现类
package com.daban.mapper;

import com.daban.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

public class UserMapperImp implements UserMapper{
    private SqlSessionTemplate sqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public List<User> getUser() {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        return mapper.getUser();
    }
}
  1. 编写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">
    <!--使用DataSource数据源代理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="123456"/>
     </bean>
    <!-- 获取SqlSessionFactory对象-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 绑定mybatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!-- 代替了在mybatis配置文件中的mapper注册-->
        <property name="mapperLocations" value="classpath:UserMapper.xml"/>
    </bean>
    <!--这就是我们使用的sqlSession-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--由于没有set方法只能使用构造器注入-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>
    <bean id="userMapper" class="com.daban.mapper.UserMapperImp">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>
</beans>
  1. 测试
import com.daban.mapper.UserMapper;
import com.daban.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;
import java.util.List;

public class MyTest {
    @Test
    public void test() throws IOException {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
        UserMapper bean = context.getBean("userMapper",UserMapper.class);
        List<User> user = bean.getUser();
        for (User user1 : user) {
            System.out.println(user1);
        }
    }
}

12.3 获得SqlSession的方式二

参见官网http://mybatis.org/spring/zh/sqlsession.html#SqlSessionDaoSupport

13、声明式事务

13.1 spring中的事务管理

  • 声明式事务:aop
<!-- 配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <constructor-arg ref="dataSource"/>
</bean>
<!-- 结合aop实现事务的植入-->
<!-- 配置事务通知,需要导入tx约束-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!-- 给哪些方法配置事务-->
    <!-- 配置事务的传播特性,默认REQUIRED-->
    <tx:attributes>
        <tx:method name="add" propagation="REQUIRED"/>
        <!-- 给所有方法配置-->
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>
<!-- 配置事务的切入点-->
<aop:config>
    <aop:pointcut id="txPointCut" expression="execution(* com.daban.mapper.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
  • 编程式事务:需要在代码中进行事务管理(需要改源代码)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值