spring笔记


文档: Spring Framework Reference Documentation

官网下载地址:repo.spring.io

Github:Releases · spring-projects/spring-framework (github.com)

导包:

直接导入一个比较大的包,让maven去帮助我们导入它的依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>
<!-- 整合jdbc -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>

优点

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

弊端

  • 经过了长久的发展,整合了许多框架,配置很多。于是出现了springBoot来简化spring的配置

组成

七大核心功能模块

在这里插入图片描述

IOC理论推导

在以往的程序中,我们需要使用哪个dao层业务就需要在业务层代码中进行修改。当程序体量十分庞大的时候,再手动修改代码的代价十分的昂贵。于是有了这一种思想,通过在业务层添加一个方法set,让用户调用set方法来主动选择需要哪一种业务代码。这种方式降低了系统耦合性。这就是IOC的原型

IOC本质

控制反转是一种思想,依赖注入(DI)是实现控制反转的一种方式

spring中实现控制反转的是IoC容器,它的实现方式也是依赖注入

HelloSpring(第一个spring程序)

实体

package com.zhong.pojo;

public class Hello {

    private String str;

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

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

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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--使用spring来创建对象,在spring中这些对象都叫做bean-->
    <bean id="hello" class="com.zhong.pojo.Hello">
        <!--通过properties标签来对一个对象的值赋值-->
        <property name="str" value="Spring" />
    </bean>

</beans>

测试

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

public class MyTest {

    public static void main(String[] args) {
        //这里,如果使用xml来创建对象的话,必须使用new ClassPathXmlApplicationContext来加载xml文件
        //这个方法的参数是可变长参数,我们可以传入多个值
        //获取spring的上下文对象(拿到spring容器)
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");

        //对象都在spring中进行管理,如果要使用,要取出来
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.toString());
    }
}

IOC创建对象的方式

  • 默认使用无参构造方法创建对象(在拿到spring容器的时候,会自动创建xml里配置的所有对象)

  • 有惨构造方式

    1. 下标

      <!--   有参构造方式_下标赋值-->
      <bean id="user" class="com.zhong.dao.User">
          <constructor-arg index="0" value="123" />
      </bean>
      
    2. 类型

      <!--通过类型匹配来使用有参构造-->
      <!--参数多个类型相同会出问题。所以不建议使用-->
      <!--类型相同的时候,相同类型的参数会按照标签顺序进行赋值-->
      <bean id="user" class="com.zhong.dao.User">
          <constructor-arg type="java.lang.String" value="123"></constructor-arg>
      </bean>
      
    3. 参数名

      <!--直接通过参数名赋值-->
      <bean id="user" class="com.zhong.dao.User">
          <constructor-arg name="name" value="123"></constructor-arg>
      </bean>
      

    在配置文件加载的时候,spring容器中的对象会被初始化(也就是自动的new出来放在容器中等待我们去取)

Spring配置

1.别名

别名,可以给容器创建出来的对象起一个别名,用户可以通过创建的对象的id和别名(两者可同时使用,取的都是一个对象)来获取同一个对象。

但个人感觉多次一举

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

2.配置

id:用户可以取到的这个对象的名字(也就是变量名)

class:bean标签该去创建一个什么类型的对象(也就是对象类型)

name:对象别名,通过name可以对同一个对象取多个别名,分隔符可以是逗号,分号,空格

<bean id="userTest" class="com.zhong.dao.UserT" name="t,userT2 u3;u4">
    <property name="name" value="123"></property>
</bean>

3.import

import一般用于团队开发,可以将多个配置文件导入到一个配置文件中,这样可以通过这个总的配置文件拿到各个配置文件中初始化的对象。

问题:id相同怎么办?

当出现导入的两个配置文件中的对象的id相同,那么后导入的配置文件会覆盖前导入的配置文件

依赖注入(DI)

1.构造器注入

2.Set方式注入

测试环境搭建

  1. 复杂类型

    package com.zhong.pojo;
    
    public class Address {
        private String address;
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    }
    
    
  2. 真实对象

    package com.zhong.pojo;
    
    import java.util.*;
    
    public class Student {
    
        private String name;
        private Address address;
        private String[] books;
        private List<String> hobbies;
        private Map<String, String> cards;
        private Set<String> games;
        private Properties info;
        private String wife;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    
        public String[] getBooks() {
            return books;
        }
    
        public void setBooks(String[] books) {
            this.books = books;
        }
    
        public List<String> getHobbies() {
            return hobbies;
        }
    
        public void setHobbies(List<String> hobbies) {
            this.hobbies = hobbies;
        }
    
        public Map<String, String> getCards() {
            return cards;
        }
    
        public void setCards(Map<String, String> cards) {
            this.cards = cards;
        }
    
        public Set<String> getGames() {
            return games;
        }
    
        public void setGames(Set<String> games) {
            this.games = games;
        }
    
        public Properties getInfo() {
            return info;
        }
    
        public void setInfo(Properties info) {
            this.info = info;
        }
    
        public String getWife() {
            return wife;
        }
    
        public void setWife(String wife) {
            this.wife = wife;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", address=" + address +
                    ", books=" + Arrays.toString(books) +
                    ", hobbies=" + hobbies +
                    ", cards=" + cards +
                    ", games=" + games +
                    ", info=" + info +
                    ", wife='" + wife + '\'' +
                    '}';
        }
    }
    
  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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="student" class="com.zhong.pojo.Student">
            <!--set注入,普通值直接使用value进行注入-->
            <property name="name" value="123" />
        </bean>
    
    </beans>
    

注入

<bean id="address" class="com.zhong.pojo.Address"></bean>
<bean id="student" class="com.zhong.pojo.Student">
    <!--set注入,普通值直接使用value进行注入-->
    <property name="name" value="123" />
    <!--bean注入,使用ref-->
    <property name="address" ref="address" />

    <!--数组-->
    <property name="books">
        <array>
            <value>红楼梦</value>
            <value>水浒传</value>
            <value>西游记</value>
        </array>
    </property>

    <!--list-->
    <property name="hobbies">
        <list>
            <value></value>
            <value></value>
            <value>写代码</value>
            <value>篮球</value>
        </list>
    </property>

    <!--map-->
    <property name="cards">
        <map>
            <entry key="身份证" value="123456789012345678" />
            <entry key="银行卡" value="123456789012345678" />
        </map>
    </property>

    <!--set-->
    <property name="games">
        <set>
            <value>LOL</value>
            <value>CSGO</value>
        </set>
    </property>

    <!--null-->
    <property name="wife">
        <null/>
    </property>

    <!--properties-->
    <property name="info">
        <props>
            <prop key="学号">2008030201</prop>
            <prop key="性别"></prop>
        </props>
    </property>
</bean>

3.拓展方式注入

c命名空间和p命名空间注入

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

    <!--p命名空间注入(properties就是set注入)-->
    <bean id="user" class="com.zhong.pojo.User" p:age="18" p:name="123" />


    <!--c命名空间注入(构造器注入)-->
    <bean id="user2" class="com.zhong.pojo.User" c:age="18" c:name="123" />

</beans>

导入xml约束

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

bean作用域

1.单例模式(默认)

bean的作用域默认都是单例模式,我们也可以显式的定义为单例模式

<bean id="user2" class="com.zhong.pojo.User" c:age="18" c:name="123" scope="singleton" />

2.原型模式

每次从容器中取出来的对象都是一个新的对象,尽管这些对象的属性值相同

<bean id="user2" class="com.zhong.pojo.User" c:age="18" c:name="123" scope="prototype" />

Bean的自动装配

spring中有三种装配方式

  1. 在xml种显式配置(手动)
  2. 在java中显示配置
  3. 隐式自动装配

byName自动装配

<!--byname:通过setXXX()这个方法set后面的名字来查找进行自动装配-->
<bean id="people" class="com.zhong.pojo.People" autowire="byName">
    <property name="name" value="123" />

</bean>

byType

<!--byType:通过查找类型自动装配,但是要保证类型全局唯一-->
<bean id="people" class="com.zhong.pojo.People" autowire="byType">
    <property name="name" value="123" />

</bean>

注解实现自动装配

注解实现自动装配是@Autowired。它的工作原理是先使用byType在beans.xml中上下文查找,如果类型数量大于1,再使用byName进行查找

使用注解开发需要再导入一个约束

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

然后在我们需要自动装配的类的属性上写上@Autowired

package com.zhong.pojo;

import org.springframework.beans.factory.annotation.Autowired;

public class People {
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;
    private String name;

}

@Autowired(request = false)这样被标注的属性可以为null。同时也可以使用@nullable使属性可以为null

@Autowired优先按照类型匹配,@Qualifier(value=“xxx”)这个注解则会优先使用byName进行匹配。@Resource java自带的注解,也可以实现自动装配,但在java11取消

使用注解开发

在spring4之后使用注解开发需要导入aop的包

1.bean

@component:放在类上,在配置文件中配置组件扫描的指定的包下起作用,说名该类是一个bean,需要被spring容器管理

2.属性如何注入

@Value(“xxx”):放在属性上,直接给属性注入值。复杂类型不适用,只用于普通值的注入

3.衍生如何注入

@component有衍生注解,在web开发中,按照mvc三层架构

  • dao @Repository:功能和@Component一样只是为了和实体类进行区分
  • service @Service
  • controller @Controller

4.自动装配

5.作用域

@Scope(“xxx”)singleton单例模式

使用java的方式配置spring

package com.zhong.config;

import com.zhong.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration //被spring托管,注册到容器中,它本身也是一个@Component。并且这个注解的意思是标志这个类是原来的配置.xml文件
//既然是原来的xml文件,那么原来的一些功能也可以通过注解来使用
@ComponentScan("com.zhong.pojo")
@Import(comfig2.class)
public class MyConfig {


    //注册一个bean,方法的名字就是bean标签里的id
    //返回值就是bean标签里的class
    //1.@Bean和2.在实体类上加上@Component配置类加上扫描,选择其一
    @Bean
    public User getUser() {
        return new User();//返回要注入到bean的对象
    }
}
package com.zhong.pojo;

import org.springframework.beans.factory.annotation.Value;

public class User {

    @Value("123")
    private String name;

    public User(String name) {
        this.name = name;
    }

    public User() {
    }

    public String getName() {
        return name;
    }

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

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

代理模式

SpringAOP的底层就是代理模式

1.静态代理

好处

  • 让被代理角色更加纯粹
  • 公共业务交给代理角色实现
  • 公共业务拓展时,便于集中管理

坏处

  • 一个被代理会产生一个代理

2.动态代理

动态代理的底层是反射。动态代理分为两大类:基于接口的动态代理,基于类的动态代理

  • 基于接口 JDK动态代理(原生)
  • 基于类 cglig
  • java字节码实现 Javasist

这里我们使用原生的jdk动态代理,需要了解两个类proxy:代理、invocationhandler :调用处理程序

package demo02;

import demo01.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);

    }

    //处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object invoke = method.invoke(target, args);
        return invoke;
    }
}
package demo01;

public class Client {
    public static void main(String[] args) {
        //被代理角色
        Host host = new Host();

        //代理角色
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();

        //调用程序处理对象来处理要调用的接口对象
        proxyInvocationHandler.setRent(host);

        Rent proxy = (Rent) proxyInvocationHandler.getProxy();

        proxy.rent();
    }
}

SpringAOP

springAOP的底层实现还是代理模式,其实就是代理模式的spring封装,我们只需要去使用。

首先,使用sprinAOP需要导入

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>
  • 使用spring的api接口

    <?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.zhong.service.UserServiceImpl"></bean>
        <bean id="log" class="com.zhong.log.Log"></bean>
        <bean id="afterLog" class="com.zhong.log.AfterLog"></bean>
      <!--     xmlns:aop="http://www.springframework.org/schema/aop"
                http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd"
    这里配置aop约束
    -->
    
        <!--原生api接口-->
        <!--需要导入aop约束-->
        <aop:config>
            <!--配置切入点-->
            <!--expression:表达式execution(要执行的位置 修饰词(public等) 返回值  类名 方法名 参数)-->
            <aop:pointcut id="pointcut" expression="execution(* com.zhong.service.UserServiceImpl.*(..))"/>
            <!--执行环绕增加-->
            <aop:advisor advice-ref="log" pointcut-ref="pointcut" />
            <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut" />
        </aop:config>
    </beans>
    

    需要注册的bean继承某些类才能够被切入点配置

    package com.zhong.log;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
    import java.lang.reflect.Method;
    
    public class Log implements MethodBeforeAdvice {
    
        //args 方法需要调用的参数
        //method 被代理类需要被调用的方法
        //target 被代理类
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println(target.getClass().getName()+"的"+method.getName()+"准备执行了");
        }
    }
    
  • 使用自定义类

    <?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.zhong.service.UserServiceImpl"></bean>
    
        <!--自定义切面-->
        <bean id="diy" class="com.zhong.diy.DiyPointCut"></bean>
    
        <aop:config>
            <!--引用自定义切面-->
            <aop:aspect ref="diy">
                <!--切入点-->
                <aop:pointcut id="point" expression="execution(* com.zhong.service.UserServiceImpl.*(..))"/>
    
                <!--通知-->
                <aop:before method="before" pointcut-ref="point" />
                <aop:after method="after" pointcut-ref="point" />
            </aop:aspect>
        </aop:config>
    </beans>
    
    package com.zhong.diy;
    
    public class DiyPointCut {
    
        public void before () {
            System.out.println("======================before");
        }
    
        public void after() {
            System.out.println("======================after");
        }
    }
    
  • 使用注解实现

    <?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.zhong.service.UserServiceImpl"></bean>
        <bean id="log" class="com.zhong.log.Log"></bean>
        <bean id="afterLog" class="com.zhong.log.AfterLog"></bean>
    
        <!--使用注解AOP-->
        <bean id="annotationPointCut" class="com.zhong.diy.AnnotationPointCut"></bean>
        <!--开启自动代理-->
        <aop:aspectj-autoproxy/>
    
    
    </beans>
    
    package com.zhong.diy;
    
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    
    @Aspect//标记该类是切面
    public class AnnotationPointCut {
    
        @Before("execution(* com.zhong.service.UserServiceImpl.*(..))")
        public void before() {
            System.out.println("==============================before");
        }
    
        @After("execution(* com.zhong.service.UserServiceImpl.*(..))")
        public void after() {
            System.out.println("=================================after");
        }
    
        //环绕中,使用参数获得连接点
        @Around("execution(* com.zhong.service.UserServiceImpl.*(..))")
        public void around(ProceedingJoinPoint jp) throws Throwable {
    
            System.out.println("环绕前");
    
            Signature signature = jp.getSignature();
            System.out.println(signature);
            Object proceed = jp.proceed();//真正执行方法
    
            System.out.println("环绕后");
            System.out.println(proceed);
        }
    }
    

    这里可以通过方法注释配置切入点

    /**
     * 切面类:注解的切面类
     */
    @Aspect
    public class MyAspectAnno {
        //通过@Pointcut注释在方法上配置切入点,之后在@Before通过value=方法名的方式调用该切入点
        @Pointcut(value="execution(* com.itheima.spring.demo1.OrderDao.find(..))")
        private void pointcut(){}
        
        //前置通知
        @Before(value="MyAspectAnno.pointcut()")
        public void before(){
           System.out.println("前置通知======");
       }
      //后置通知
        @AfterReturning(value="MyAspectAnno.pointcut()", returning="result")
        public void afterReturning(Object result){
            System.out.println("后置通知====="+result);
        } //环绕通知
        @Around(value="MyAspectAnno.pointcut()")
        public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
            System.out.println("环绕前增强=====");
            Object obj = joinPoint.proceed();
            System.out.println("环绕后增强=====");
            return obj;
        }
        //异常抛出通知
        @AfterThrowing(value="MyAspectAnno.pointcut()" , throwing="e")
        public void find(Throwable e ){
           System.out.println("异常抛出通知======"+e.getMessage());
       }
    
      // 最终通知:
        @After(value="MyAspectAnno.pointcut()")
        public void after( ){
           System.out.println("最终通知======");
       }
    }
    

    整合mybatis

    相关jar包

    <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.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.22</version>
        </dependency>
        <!--spring操作数据库需要spring-jdbc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.22</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.2</version>
        </dependency>
    </dependencies>
    

1.编写数据源配置

spring-dao.xml

<!--使用context读取db.properties文件的数据-->
<context:property-placeholder location="classpath:db.properties"/>

<!--dataSource 使用spring的数据源替换mybatis的数据源
这里使用spring的jdbc
-->
<!--使用驱动管理数据源-->
<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?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false"/>
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
</bean>

2.编写sqlSessionFactory

spring-dao.xml

<!--配置sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
    <property name="mapperLocations" value="classpath:com/zhong/mapper/UserMapper.xml"/>
</bean>

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>
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    
    <typeAliases>
        <package name="com.zhong.pojo"/>
    </typeAliases>

</configuration>

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhong.mapper.UserMapper">

    <select id="selectUser" resultType="user">
        select *
        from mybatis.user;
    </select>

</mapper>

3.编写sqlSessionTemplate

spring-dao.xml

<!--调用sqlSession还需要一个sqlSessionTemplate-->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
    <!--SqlSessionTemplate这个类没有set方法,只能使用构造器注入-->
    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

4.给接口加实现类

UserMapperImpl.java

package com.zhong.mapper;

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

import java.util.List;

public class UserMapperImpl implements UserMapper {

    private SqlSessionTemplate sqlSessionTemplate = null;

    public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
        this.sqlSessionTemplate = sqlSessionTemplate;
    }

    /*从使用xml文件写sql语句转变成使用SqlSessionTemplate*/
    public List<User> selectUser() {
        UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class);
        return mapper.selectUser();
    }
}

5.实现类注入spring中

spring-dao.xml

<!---->
<bean id="userMapper" class="com.zhong.mapper.UserMapperImpl">
    <property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
</bean>

6.测试

import com.zhong.mapper.UserMapper;
import com.zhong.pojo.User;

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 userMapper = context.getBean("userMapper", UserMapper.class);
        List<User> userList = userMapper.selectUser();
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

总配置文件,这个文件写好之后可以通过import导入到applicationContext使用,之后就不必改动了

spring-dao.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:aop="http://www.springframework.org/schema/aop"
       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/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!--使用context读取db.properties文件的数据-->
    <context:property-placeholder location="classpath:db.properties"/>

    <!--dataSource 使用spring的数据源替换mybatis的数据源
    这里使用spring的jdbc
    -->
    <!--使用驱动管理数据源-->
    <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?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false"/>
        <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" />
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/zhong/mapper/UserMapper.xml"/>
    </bean>

    <!--调用sqlSession还需要一个sqlSessionTemplate-->
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <!--SqlSessionTemplate这个类没有set方法,只能使用构造器注入-->
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>

    <!---->
    <bean id="userMapper" class="com.zhong.mapper.UserMapperImpl">
        <property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
    </bean>

</beans>

方式2

使用类继承

package com.zhong.mapper;

import com.zhong.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {
    public List<User> selectUser() {
        return getSqlSession().getMapper(UserMapper.class).selectUser();
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       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
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!--使用context读取db.properties文件的数据-->
    <context:property-placeholder location="classpath:db.properties"/>

    <!--dataSource 使用spring的数据源替换mybatis的数据源
    这里使用spring的jdbc
    -->
    <!--使用驱动管理数据源-->
    <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?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false"/>
        <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" />
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/zhong/mapper/UserMapper.xml"/>
    </bean>

    <bean id="userMapper2" class="com.zhong.mapper.UserMapperImpl2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>

</beans>

声明式事务

spring事务分为两种

  • 編程式事务
  • 声明式事务
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

<!--结合AOP实现事务织入-->
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--给哪些方法配置事务-->
    <tx:attributes>
        <tx:method name="add"/>
        <tx:method name="delete"/>
        <tx:method name="update"/>
    </tx:attributes>
</tx:advice>

<!--配置事务切入-->
<aop:config>
    <aop:pointcut id="txPointCut" expression="execution(* com.zhong.mapper.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值