Spring笔记

Spring

  • 官方网址:https://docs.spring.io/

  • 官方下载地址:https://repo.spring.io/ui/native/release/org/springframework/spring

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

  • 配置:https://mvnrepository.com/artifact/org.springframework/spring-webmvc/5.3.18

1、概述

  • Spring一个开源的免费的框架
  • Spring是一个轻量级的、非入侵式的框架
  • 控制反转(IOC)、面向切面编程(AOP)
  • 支持事务的处理,对框架整合的支持

2、IOC理论推导

  • 控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。
  • 在Spring中实现控制反转的是 IOC 容器,其实现方法是依赖注入

3、HelloSpring

  1. 配置pom.xml

    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.18</version>
    </dependency>
    
  2. 创建实体类

    public class Hello {
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Hello!"  + name ;
        }
    }
    
    
  3. 写beans.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">
    
        <bean id="hello" class="com.wjh.pojo.Hello">
            <property name="name" value="Spring"/>
        </bean>
    
    </beans>
    
  4. 测试类

    //获取Spring的上下文对象
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    //调用Spring中的数据
    Hello hello = (Hello) context.getBean("hello");
    System.out.println(hello.getName());
    
    Hello Spring
    

综上可得:

对象是由Spring创建的

依赖注入就是通过set方法注入的

要实现不同的操作,只需要改变xml即可

4、IOC创建对象方式

  1. 默认的创建方式为 无参构造 【在xml文件被加载的时候,全部对象就已经被初始化了】

  2. 有参构造

    • 通过传入属性索引创建

      <bean id="user" class="com.wjh.pojo.User">
          <constructor-arg index="0" value="王佳慧"/>
          <constructor-arg index="1" value="20"/>
      </bean>
      
    • 通过属性名、值创建

      <bean id="user" class="com.wjh.pojo.User">
          <constructor-arg name="name" value="王二"/>
          <constructor-arg name="age" value="21"/>
      </bean>
      
    • 通过数据类型创建 不推荐!!!

      <bean id="user" class="com.wjh.pojo.User">
          <constructor-arg type="java.lang.String" value="王二"/>
      </bean>
      

5、Spring配置

5.1 别名

在之后测试类中调用的时候,可以使用别名,当然也可以仍然使用原来的名字

<bean id="user" class="com.wjh.pojo.User">
    <constructor-arg name="name" value="王二"/>
    <constructor-arg name="age" value="21"/>
</bean>

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

5.2 Bean配置

<bean id="hello" class="com.wjh.pojo.Hello" name="otherName,otherName2">
    <property name="name" value="Spring"/>
</bean>
  • bean

    • id 就是自己起的名字,之后在测试类中调用
    • class写出具体的实体类地址
    • name 就是别名,并且可以起多个
  • property

    • name就是实体类的属性名,必须和属性名一模一样
    • value就是属性的值
    • ref 得到的是Spring创建好的对象

5.3 import

就是将别的xml文件导入到这个xml文件中,形成一个大的xml文件,可以通过调用这个文件调用别的文件

<import resource="bean.xml"/>

6、依赖注入

6.1 构造器注入

<bean id="user" class="com.wjh.pojo.User">
    <constructor-arg name="name" value="王二"/>
    <constructor-arg name="age" value="21"/>
</bean>

见4、IOC创建对象方式

6.2、Set方式注入

  • 依赖注入

    • 依赖:bean对象的创建依赖于容器
    • 注入:bean对象中的所有属性由容器来注入
  • 实体类

    public class Student {
        private String name;
        private Address address;
        private String[] books;
        private List<String> list;
        private Map<String,String> map;
        private Properties info;
        private Set set;
        private String testNull;
    }
    
  • xml

    <bean id="add" class="com.wjh.pojo.Address">
        <property name="address" value="address"/>
    </bean>
    <bean id="student" class="com.wjh.pojo.Student">
        <!--普通值注入-->
        <property name="name" value="学生"/>
        <!--bean类型注入-->
        <property name="address" ref="add"/>
        <!--数组注入-->
        <property name="books">
            <array>
                <value>红楼梦</value>
                <value>水浒传</value>
                <value>西游记</value>
                <value>三国演义</value>
            </array>
        </property>
        <!--集合注入-->
        <property name="list">
            <list>
                <value>list1</value>
                <value>list2</value>
                <value>list3</value>
            </list>
        </property>
        <!--Map注入-->
        <property name="map">
            <map>
                <entry key="key1" value="value1"/>
                <entry key="key2" value="value2"/>
                <entry key="key3" value="value3"/>
            </map>
        </property>
        <!--Properties注入-->
        <property name="info">
            <props>
                <prop key="prop1">prop1</prop>
                <prop key="prop2">prop2</prop>
            </props>
        </property>
        <!--Set注入-->
        <property name="set">
            <set>
                <value>set1</value>
                <value>set2</value>
                <value>set3</value>
            </set>
        </property>
        <!--测试注入null-->
        <property name="testNull">
            <null/>
        </property>
    </bean>
    
  • 测试类

    public class DITest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            Student student = (Student) context.getBean("student");
            System.out.println(student);
        }
    }
    
    name='学生', 
    address=address='address, 
    books=[红楼梦, 水浒传, 西游记, 三国演义], 
    list=[list1, list2, list3], 
    map={key1=value1, key2=value2, key3=value3}, 
    info={prop2=prop2, prop1=prop1}, 
    set=[set1, set2, set3], 
    testNull='null
    

6.3 c、p命名空间注入

  1. p命名空间

    • p命名空间相当于 set注入

    • 导入xml约束

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

      <bean id="user" class="com.wjh.pojo.User" p:name="Mike" p:age="25"/>
      
  2. c命名空间

    • c命名空间相当于 构造注入

    • 导入xml约束

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

      <bean id="u" class="com.wjh.pojo.User" c:name="John" c:age="21"/>
      

6.4 bean的作用域

  • 单例模式 Spring默认的模式

    每一 Spring IOC 容器都拥有唯一的实例对象.

    <bean id="u" class="com.wjh.pojo.User" c:name="John" c:age="21" scope="singleton"/>
    
  • 原型模式

    一个 Bean 定义可以创建任意多个实例对象.

    <bean id="u" class="com.wjh.pojo.User" c:name="John" c:age="21" scope="prototype"/>
    
  • request session application websocket 都是在web开发中才用到

7、Bean自动装配

  • 自动装配是Spring满足bean依赖的一种方式
  • Spring在上下文中自动寻找,自动给bean装配属性

7.1 byName自动装配

  • 通过byName,他会去自动寻找set方法后面的属性名,来进行装配
<bean id="dog" class="com.wjh.pojo.Dog"/>
<bean id="cat" class="com.wjh.pojo.Cat"/>

<bean id="people" class="com.wjh.pojo.People" autowire="byType">
    <property name="name" value="Yeah!!!"/>
</bean>

7.1 byType自动装配

<bean class="com.wjh.pojo.Dog"/>
<bean class="com.wjh.pojo.Cat"/>

<bean id="people" class="com.wjh.pojo.People" autowire="byType">
    <property name="name" value="Yeah!!!"/>
</bean>
  • 通过byName自动装配时,必须保证bean的id是唯一的,并且id名必须和自动注入的属性的Set方法后的值一样
  • 通过byType自动装配时,必须保证bean的class是唯一的,并且class必须和自动注入的属性的类型一样

7.3 注解实现自动装配

  • @Autowired
  1. 要实现注解,就要配置好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"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:annotation-config/>
    
    </beans>
    
  2. 在实体类的属性上面添加注解:@Autowired

    • 也可以写在set方法上
    • Autowired是先根据byType,然后根据byName
    • Autowired要求数据不可以为空,会返回空指针
    • 为Autowired添加成:@Autowired(required = false) 当属性为空的时候,不会报错,会直接输出null
    public class People {
        @Autowired
        private Dog dog;
        @Autowired
        private Cat cat;
        @Autowired(required = false)
        private String name;
    }
    
    <context:annotation-config/>
    
    <bean id="cat" class="com.wjh.pojo.Cat"/>
    <bean id="dog" class="com.wjh.pojo.Dog"/>
    
    <bean id="people" class="com.wjh.pojo.People"/>
    
  3. @Qualifier(value = "cat22")

    • 添加Qualifier注解后,在xml文件中,id可以写成value的值

      @Autowired
      @Qualifier(value = "cat222")
      private Cat cat;
      
      <bean id="cat222" class="com.wjh.pojo.Cat"/>
      

8、注解开发

  • 依然先配置好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"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="com.wjh.pojo"/>
        <context:annotation-config/>
    
    </beans>
    
    • <context:component-scan base-package="com.wjh.pojo"/>
      • 它会将扫描到的包内的注解注册到Spring中,使其发生作用
      • 如果扫描到有@controller、@Service、@Repository、@Component等注解的java类,就会将这些类注册为bean。
      • 如果指定了context:component-scan就不用指定<context:annotation-config/>,前者包含后者。
  • @Component 注入bean

    等价于<bean id="user" class="com.wjh.pojo.User"/>

    @Component
    public class User {
        public String name = "wjh";
    }
    
  • @Component有几个衍生注解

    它们的功能与Component是一样的,都是将 类注册到Spring中

    • @Repository 用在Dao类
    • ``@Service ` 用在Service类
    • @Controller 用在Controller类
  • @Value 属性注入

    • 等价于<property name="name" value="wjh"/>
    • 当属性为private的时候,必须要写上set方法,不然取不到
    @Component 
    public class User {
        @Value("wjh")
        public String name ;
    
    }
    
  • @Autowired 自动装配属性

    public class People {
        @Autowired
        private Dog dog;
        @Autowired
        private Cat cat;
        @Autowired(required = false)
        private String name;
    }
    
    <bean id="cat" class="com.wjh.pojo.Cat"/>
    <bean id="dog" class="com.wjh.pojo.Dog"/>
    
    <bean id="people" class="com.wjh.pojo.People"/>
    
  • @Nullable 指定的属性可以为空 不报错

  • @Scope 指定作用域

    • singleton单例模式 – 全局有且仅有一个实例
    • prototype原型模式 – 每次获取Bean的时候会有一个新的实例

9、完全注解开发

  • 使用Java完成开发,不再使用xml来配置
  • 其实就是创建了一个Config类,代替xml,使用java语句来实现bean注册

MyConfig.java

  • @Configuration 声明一个类为配置类,用于取代bean.xml配置文件注册bean对象

  • @Bean 表示将这个类注册为Bean

    @Configuration
    public class MyConfig {
        @Bean
        public User getUser(){
            return new User();
        }
    }
    

实体类

  • @Component 等价于<bean id="user" class="com.wjh.pojo.User"/>

  • @Value 将属性注册到Spring

    @Component
    public class User {
        @Value("vdsvds")
        private String name;
    
        public String getName() {
            return name;
        }
    }
    

测试类

  • 用Java代替xml注册之后,创建ApplicationContext使用AnnotationConfigApplicationContext

  • context.getBean("getUser"); 获取类,是传入Config类中的类名

    ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
    User user = (com.wjh.pojo.User) context.getBean("getUser");
    System.out.println(user.getName());
    

10、代理模式

如果要为某个业务增加拓展,但是不能改变原有业务的代码,可以增加一层(代理类)在实现原有业务的基础上,增加业务代码,也就是利用代理模式

10.1静态代理

  • 抽象角色

    public interface Rent {
        void rent();
    }
    
  • 真实角色

    public class Real implements Rent{
        public void rent() {
            System.out.println("真实角色进行");
        }
    }
    
  • 代理角色

    public class Proxy implements Rent{
        private Real real;
        public Proxy() {
        }
        public Proxy(Real real) {
            this.real = real;
        }
        public void rent() {
            First();
            real.rent();
            Second();
        }
        public void First(){
            System.out.println("代理角色进行第一步");
        }
        public void Second(){
            System.out.println("代理角色进行第三步");
        }
    }
    
  • 测试

    public class TestProxy {
        public static void main(String[] args) {
            Real real = new Real();
            Proxy proxy = new Proxy(real);
            proxy.rent();
        }
    }
    代理角色进行第一步
    真实角色进行
    代理角色进行第三步
    

好处:

  • 公共业务拓展的时候,方便集中管理
  • 可以使真实角色的操作更纯粹,不用关注公共业务

缺点:

  • 一个真实角色对应一个代理角色,代码量翻倍,开发效率降低

10.2动态代理

Proxy : 代理类 InvocationHandler : 调用处理程序并返回代理结果

  • 抽象角色

    public interface Abstract {
        void test();
    }
    
  • 真实角色

    public class Real implements Abstract{
        public void test() {
            System.out.println("真实角色操作。。。");
        }
    }
    
  • InvocationHandler类

    生成代理的接口

    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);
        }
    
        //进行代理处理
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            log(method.getName());
            return method.invoke(target,args);
        }
    
        public void log(String msg){
            System.out.println("执行了"+msg+"方法");
        }
    }
    
  • 测试类

    public class Client {
        public static void main(String[] args) {
            //真实角色
            Real real = new Real();
            //代理角色
            ProxyInvocationHandler pih = new ProxyInvocationHandler();
    
            //设置需要代理的角色
            pih.setTarget(real);
    
            //动态生成代理类
            Abstract proxy = (Abstract) pih.getProxy();
            //调用方法,已经进行了代理处理
            proxy.test();
        }
    }
    

优点:

  • 动态代理模式,代理的是抽象角色,是一个接口,可以通过改变传入的真实角色进行代理处理。
  • 一个动态代理类代理一个类型的角色,一个动态代理类可以代理多个实现同一接口的角色
  • 不需要每一个真实角色都创建一个静态代理类了

11、AOP

导入aop依赖

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.6.8.RELEASE</version>
</dependency>

11.1 Spring API接口

通过Spring的API接口实现代理

  • xml文件导入Aop约束

    <?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">
        
    </beans>
    
  1. 抽象角色

    public interface UserService {
        void add();
        void delete();
        void update();
        void query();
    }
    
  2. 真实角色

    public class UserServiceImpl implements UserService{
        public void add() {
            System.out.println("增加了一个用户哟~~~");
        }
    }
    
  3. 代理角色添加的操作

    • 类继承MethodBeforeAdvice,表示在target类中的method前面执行这里面的操作
    //在方法前增加某个操作
    public class Log  implements MethodBeforeAdvice {
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println(target.getClass().getName()+"  的  "+method.getName()+"  要被执行咯");
        }
    }
    
    • 类继承`AfterReturningAdvice,表示在target类中的method前面执行这里面的操作
    public class Submit implements AfterReturningAdvice {
        public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
            System.out.println(target.getClass().getName()+"  的  "+method.getName()+"  被执行完成咯");
        }
    }
    
  4. xml文件注册类,来实现代理

    • 通过使用aop依赖来完成
    • 先将每个类注册到Spring中 再配置Aop
    • 配置好Aop之后,就完成了代理类,之后调用方法的时候,就直接输出代理类的结果了
    <!--注册bean-->
    <bean id="userService" class="com.wjh.service.UserServiceImpl"/>
    <bean id="log" class="com.wjh.log.Log"/>
    <bean id="submit" class="com.wjh.log.Submit"/>
    
    <!--配置Aop-->
    <aop:config>
        <!--切入点:expression:表达式,execution表示要执行的位置   修饰词 返回值 类名 方法名 参数-->
        <aop:pointcut id="pointcut" expression="execution(* com.wjh.service.UserServiceImpl.*(..))"/>
    
        <!--执行环绕增加 环绕通知可以在方法调用前后完成自定义的行为-->
    	<!--意思就是将log类加入到切入点pointcut-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="submit" pointcut-ref="pointcut"/>
    </aop:config>
    

    测试类

    public class Client {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
            UserService  service = (UserService) context.getBean("userService");
            service.add();
        }
    }
    

    常见的切点表达式:

    • 匹配任意公共方法的执行:

          execution(public * *(..))
      
    • 匹配任意以 set 开始的方法:

          execution(* set*(..))
      
    • 匹配定义了 AccountService 接口的任意方法:

          execution(* com.xyz.service.AccountService.*(..))
      
    • 匹配定义在 service 包中的任意方法:

          execution(* com.xyz.service.*.*(..))
      
    • 匹配定义在 service 包和其子包中的任意方法:

          execution(* com.xyz.service..*.*(..))
      

11.2 自定义类实现

通过自定义一个类,实现代理的操作,在之后的xml文件中,注册其为切面

  1. 自定义类

    写全代理类的操作

    public class DigPointCut {
        public void Before(){
            System.out.println("===方法执行前===");
        }
        public void After(){
            System.out.println("===方法执行后===");
        }
    }
    
  2. xml文件

    与SpringAPI不同的是,使用了切面,之后还是要注册切点和环绕增加的

    <!--注册bean-->
    <bean id="userService" class="com.wjh.service.UserServiceImpl"/>
    <bean id="diy" class="com.wjh.diy.DigPointCut"/>
    <aop:config>
        <!--自定义切面-->
        <aop:aspect ref="diy">
            <!--切入点-->
            <aop:pointcut id="point" expression="execution(* com.wjh.service.UserServiceImpl.*(..))"/>
            <!--代理操作-->
            <aop:after method="After" pointcut-ref="point"/>
            <aop:before method="Before" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
    

11.3 注解实现代理

  1. 为xml添加aop注解约束

    <aop:aspectj-autoproxy/>
    
  2. 自定义类

    • @Aspect 将AnnocationPointCut类注册为切面
    • @Before(execution(…)) 添加操作,并填入切点
    @Component
    @Aspect
    public class AnnocationPointCut {
    
        @Before("execution(* com.wjh.service.UserServiceImpl.*(..))")
        public void before(){
            System.out.println("===执行前===");
        }
        
        @After("execution(* com.wjh.service.UserServiceImpl.*(..))")
        public void After(){
            System.out.println("===方法执行后===");
        }
        
        //环绕增强
        @Around("execution(* com.wjh.service.UserServiceImpl.*(..))")
        public void around(ProceedingJoinPoint jp){
            System.out.println("环绕前");
            try {
                Object proceed = jp.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            System.out.println("环绕后");
        }
    
    }
    
  3. 测试类

    ApplicationContext context = new ClassPathXmlApplicationContext("annocation.xml");
    UserService  service = (UserService) context.getBean("userService");
    service.add();
    环绕前
    ===执行前===
    增加了一个用户哟~~~
    ===方法执行后===
    环绕后
    

12、整合Mybatis

与单纯的Mybatis不同的是:

  • 核心配置文件完全可以用Spring配置文件代替
    • 不再使用Utils类来创建SqlSessionFactory 用xml文件配置代替
    • 核心配置文件不再需要配置数据源,用xml的DataSource代替
    • 包括其他配置,包括typeAliases、mappers等等
    • 可以在核心配置文件留下typeAliases、settings,其他的交给Spring配置文件
  • 需要多加一个类来实现sqlSessionTemplate,进而对数据库进行操作

12.1 步骤:

  1. 导入相关jar包

    • junit

    • mybatis

    • mysql

    • spring

      1. spring-jdbc 要想Spring能够对数据库进行操作,就要导入这个包
      2. spring-webmvc
    • aop

    • mybatis-spring

      <dependencies>
          <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>5.1.25</version>
          </dependency>
          <dependency>
              <groupId>org.mybatis</groupId>
              <artifactId>mybatis</artifactId>
              <version>3.5.6</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-webmvc</artifactId>
              <version>5.3.18</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-jdbc</artifactId>
              <version>5.3.18</version>
          </dependency>
          <dependency>
              <groupId>org.aspectj</groupId>
              <artifactId>aspectjweaver</artifactId>
              <version>1.6.8.RELEASE</version>
          </dependency>
          <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
          <dependency>
              <groupId>org.mybatis</groupId>
              <artifactId>mybatis-spring</artifactId>
              <version>2.0.7</version>
          </dependency>
         
          <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
              <version>4.12</version>
              <scope>test</scope>
          </dependency>
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <version>1.18.22</version>
              <scope>provided</scope>
          </dependency>
      
      </dependencies>
      
  2. 编写配置文件

  3. 测试

12.2 sqlSessionTemplate

  • Spring配置文件

    <?xml version="1.0" encoding="GBK"?>
    <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
            https://www.springframework.org/schema/context/spring-context.xsd">
        
    </beans>
    
  1. 创建一个xml文件,用来进行spring操作

    • 配置数据源DataSource

      • 代替了mybatis-config.xml中的引入数据库数据
      <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

      • 代替了MybatisUtil中的创建SqlSessionFactory

        String resource = "org/mybatis/example/mybatis-config.xml";
        InputStream inputStream = null;
        inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        
        1. 将SqlSessionFactory类注册到Spring中

        2. 将上面创建的dataSource作为属性加入到SqlSessionFactory中

        3. 将核心配置文件加入到SqlSessionFactory中

        4. 将Mapper.xml文件加入到SqlSessionFactory中

          <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
              <property name="dataSource" ref="dataSource"/>
              <!--将mybatis-config.xml注册到SqlSessionFactory中-->
              <property name="configLocation" value="classpath:mybatis-config.xml"/>
              <!--将UserMapper.xml注册到SqlSessionFactory中-->
              <property name="mapperLocations" value="classpath:com/wjh/dao/*.xml"/>
          </bean>
          
    • 配置sqlSessionTemplate

      • 因为SQLSessionTemplate类没有set方法,所以只能通过构造器注入
      • 将SqlSessionFactory加入到sqlSessionTemplate中
      • 现在的sqlSessionTemplate就等于之前的sqlSession,可以完成一切对数据库的操作
      <!--配置sqlSessionTemplate-->
      <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
          <constructor-arg index="0" ref="sqlSessionFactory"/>
      </bean>
      
  2. 创建一个实现类,继承接口UserMapper,实现方法。

    public class UserMapperImpl implements UserMapper{
    
        private SqlSessionTemplate sqlSessionTemplate;
    
        public UserMapperImpl(SqlSessionTemplate sqlSessionTemplate) {
            this.sqlSessionTemplate = sqlSessionTemplate;
        }
    
        public List<User> selectUser(){
    
            UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class);
            return mapper.selectUser();
    
        }
    }
    
  3. 将实现类注册在xml配置文件中注册到Spring

    <bean id="userMapper" class="com.wjh.dao.UserMapperImpl">
        <property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
    </bean>
    
  4. 测试类

    public class TestUserMapper {
        @Test
        public void selectAll(){
            ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
            UserMapper  userMapper = (UserMapper) context.getBean("userMapper");
            List<User> users = userMapper.selectUser();
            for (User u:users
                 ) {
                System.out.println(u);
            }
        }
    }
    
    

12.3 SqlSessionDaoSupport

  • 当实现类继承SqlSessionDaoSupport类的时候,通过getSqlSession()方法可以直接获得sqlSession对象

  • 不再需要创建SqlSessionTemplate对象,直接调用getSqlSession()方法即可

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

13、事务

  • 是指一组要么同时执行成功,要么同时执行失败的SQL语句。是数据库操作的一个执行单元
事务的四大特点:
  • 原子性:一个事务内的所有操作是一个整体

  • 一致性:表示一个事务内,有一个操作失败,那么所有更改多的数据都必须回滚到修改前的状态

  • 隔离性:事务只会查看事务修改之前和修改后数据的状态,不会查看中间状态的数据

  • 持久性:事务完成之后,对系统的影响是永久的

Spring的声明式事务

MyBatis-Spring 借助了 Spring 中的 DataSourceTransactionManager 来实现事务管理。

为什么需要事务?

  • 如果不配置事务,可能会存在数据提交不一致的情况
  • 事务涉及到数据的一致性和完整性

通过AOP实现Spring事务的织入

  1. 配置声明式事务

    • 将数据源加入到事务中
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
  2. 结合AOP实现事务的织入,配置好事务通知

    • 配置事务加入的方法
    • name="*" 表示对于所有的方法都起作用
    • propagation表示事务的广播
    • required表示支持当前事务,如果当前没有事务,就新建一个事务
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    
  3. 配置事务切入

    • 先声明aop
    • 再加入切点 切点为aop作用的方法
    • 最后加入切入的方法
    <aop:config>
        <aop:pointcut id="pointCut" expression="execution(* com.wjh.dao.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/>
    </aop:config>
    

要注意【事务切入的包】 事务发生作用的是execution中包内的方法,而不是测试类调用包内方法的方法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值