Spring

Spring介绍

1.简介

Spring是一个开源框架,简化企业级开发

2.优点

  • 基于POJO的轻量级框架以及无侵入性
  • 通过IOC控制反转、DI依赖注入和面向接口解耦
  • 基于AOP进行声明式编程
  • 通过切面和模版减少样式代码

3.组成

1569934858546.png

IOC

降低程序间的耦合,将对象的创建和维护以及之间的依赖关系交给Spring提供的IOC容器管理,通过DI进行依赖注入,避免硬编码造成的过度程序耦合

程序耦合:
    类与类之间的依赖关系,会造成独立性很差
    方法之间的依赖关系
解耦:
    降低程序间的依赖关系
实际开发中:
    想做到完全不依赖是不可能的,所以实际开发中做到编译时不依赖,运行时才依赖
思路:
    1.通过反射对象的全限定类名来来创建对象,不使用new关键字
    2.通过读取配置文件拿要创建到对象的全限定类名,避免多次使用该类,以后替换麻烦

xml中将对象注入到IOC

创建一个xml.名字不是中文即可

    <!--xml基本元数据的基本结构-->
    <beans xmlns="http://www.springframework.org/schema/beans"
           <!--xsi前缀-->
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           <!--spring约束地址-->
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           <!--spring约束-->
           http://www.springframework.org/schema/beans/spring-beans.xsd">
	    <!--1.将对象交给Spring管理的三种方式
     					第二种和第三种方式只有在我们修改不了源码的情况下才会使用,比如调用写好的jar包
			-->
      1.常用方式:
          <bean id="对象唯一标识" class="对象全限定类名"></bean>
      2.通过工厂类的普通方法来创建对象,然后交给Spring
          <bean id="工厂类对象唯一标识" class="工厂类对象的全限定类名"></bean>
          <bean id="要创建的对象唯一标识" factory-bean="工厂类对象唯一标识" factory-method="创建对象的方法">
      3.通过工厂类的静态方法来创建对象,然后交给Spring
           <bean id="对象唯一标识" factory="工厂类的全限定类名" factory-method="创建对象的静态方法">
    </beans>

IOC创建对象

ApplicaitonContext的三个实现类:

ClassPathXmlApplicationContext:加载类路径下的文件,不在就加载不了
FileSystemApplicationContext:加载磁盘任意路径下的文件
AnnotationApplicationContext:读取注解
//加载xml文件创建spring容器对象
ApplicationContext context =  new ClassPathXmlApplicationContext("xml文件");
//根据对象的标识也就是id获取对象,然后强转
Object object =  context.getBean("唯一标识");

依赖注入

bean对象的作用域
      scope:
          singleton:单例
              生命周期跟随容器,容器创建对象就创建,容器销毁对象就销毁
          prototype:多例
              当调用对象时才创建,当对象长时间不使用并且没有对象引用,由GC回收

1.构造器注入

代码中创建有参构造方法,xml中使用constructor-arg标签

优点:

  • 创建对象时必须注入数据,否则无法创建成功

缺点:

  • 如果我们用不到这些数据,也必须赋值

属性:

  • type: 通过构造参数的类型来找到赋值
  • index: 通过构造参数的索引来找到赋值
  • name: 通过构造参数的名字来找到赋值 常用!
  • value:给基本类型和String类型赋值
  • ref:给其他bean类型赋值 指的是存在Spring容器中的bean对象
 <bean id="accountService" class="com.djn.springioc.service.impl.AccountServiceImpl">
      <constructor-arg name="name" value="丁江楠"></constructor-arg>
      <constructor-arg name="age" value="22"></constructor-arg>
   		<!--引用其他bean类型-->
      <constructor-arg name="birthday" ref="now"></constructor-arg>
  </bean>
  <!--向Spring容器添加Date对象-->
<bean id="now" class="java.util.Date"></bean>

2.set方法注入:更常用

代码中对属性创建set方法,在xml中使用property关键字

优点:

  • 可以直接使用默认的构造函数创建对象

缺点:

  • 获取对象时,如果没有注入,会没有值,不严谨

属性:

  • name:用于指定set方法名称
  • value:给基本类型和String类型赋值
  • ref:给其他bean类型赋值 指的是存在Spring容器中的bean对象
<bean id="accountService2" class="com.djn.springioc.service.impl.AccountServiceImpl2">
              <property name="userName" value="张贤伟"></property>
              <property name="age" value="22"></property>
</bean>

3.集合注入

<!--
  集合注入
  array,list,set,map,properties
-->
<bean id="accountService3" class="com.djn.springioc.service.impl.AccountServiceImpl3">
    <property name="args">
        <array>
            <value>array</value>
            <value>array</value>
            <value>array</value>
        </array>
    </property>

    <property name="list">
        <list>
            <value>123</value>
            <value>123</value>
            <value>123</value>
        </list>
    </property>

    <property name="set">
        <set>
            <value>456</value>
            <value>456</value>
            <value>456</value>
        </set>
    </property>

    <property name="map">
        <map>
            <entry key="123" value="456"></entry>
            <entry key="1234" value="456"></entry>
            <entry key="12345" value="456"></entry>
        </map>
    </property>

    <property name="properties">
        <props>
            <prop key="driver">driveer</prop>
        </props>
    </property>
</bean>

基于注解的IOC

1.用于将对象注入到IOC

1.@Component
        作用:将当前类对象存入到Spring对象中
        属性:
            value:用于指定bean对象的id,也就是唯一标识,如果不写那id默认为当前类名且首字母小写,大小写必须一致
2.@Controller:一般用于表现层
3.@Service:一般用于业务层
4.@Repository:一般用于持久层
⚠️:@Controller、@Service、@Repository作用与@Component一模一样,主要是为了我们的类职责看起来更加的清晰
    
还需要在xml中配置,该配置需要用到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">

    <!--告知spring创建时要扫描的包,扫描注解-->
    <context:component-scan base-package="com.djn.springioc"></context:component-scan>
</beans>

2.用于依赖注入的注解

1.@Autowired
        作用:将spring容器的bean对象自动注入,自动按照类型注入,只要Spring容器中有一个唯一的bean类型和要注入的bean类型匹配,就可以注入成功,
        如果没有,就报错
        如果有多个bean类型匹配,那就可以使用:@Qualifier或者@Resource
        
        @Autowired
        IAccountDao accountDao;
        会根据类型为IAccountDao去容器中找,而不是accountDao找
        
2.@Qualifier
        作用:可以在类型注入的基础上在按照名称注入,当Spring容器中有多个bean类型,可以根据它的属性value进行匹配注入
        属性:
            value:用于指定要注入bean的id
        注意:需要和Autowired一起使用,它只负责匹配名称,不负责注入
        
        @Autowired
        @Qualifier(value = "accountDao1")
        IAccountDao accountDao;
        会根据id为accountDao1去容器中找,而不是IAccountDao去找
        
3.@Resource
        作用:直接按照bean的id进行注入,可以独立使用
        属性:
            name:用于指定要注入对象的id
        @Resource(name = "accountDao1")
        IAccountDao accountDao;
        会根据id为accountDao1去容器中找
        
    ⚠️:以上三种只能注入其他bean类型,不能注入基本数据和String类型
4.@Value
        作用:用于注入基本数据和String类型,它可以使用SpEl(spring的el表达式 ${})
        @Value("500")
        int count;
        给count赋值为500

3.用于作用域和生命周期

1.@Scope
        作用:声明对象的作用域
        属性:
            value:singleton单例、prototype多例
2.@PostConstruct
        作用:用于指定初始化方法,在方法上声明
  @PreDestory
        作用:用于指定销毁方法,在方法上声明

4.用于替换xml配置

1.@Configuration
        作用:它的作用和beans.xml是一模一样的,指定当前类是配置类
        ⚠️:它也不一定需要写,当使用AnnontationApplicationContext获取spring容器对象指定配置
            类时这个注解就可以不写,可以指定多个(但是不建议指定多个),采取父子配置类的方式更清晰
2.@ComponentScan
        作用:告知spring创建时要扫描的包,扫描注解并且创建对象,
              与<context:component-scan base-package="com.djn.springioc"></context:component-scan>作用是一样的
        属性:
            value:用于指定要扫描的包,如果有多个包,可以@ComponentScan({"",""})这样指定
3.@Bean
        作用:用于将方法的返回对象存入spring容器中
        属性:
            name:指定bean的id,当不写时,默认是方法名
4.@Import:
        作用:用于指定配置的类,当其他的子配置类不写@Configuration时,可以在父配置类中通过它指定子配置类 
    
    //代表当前类是一个注解类
    @Configuration
    //扫描com.djn.ioccase包下的注解并注入到Spring容器
    @ComponentScan("com.djn.ioccase")
    //导入JDBCConfiguration配置类
    @Import(JDBCConfiguration.class)
    public class SpringConfiguration {
    
        //将JdbcTemplate注入到Spring容器中
        @Bean("jdbcTemplate")
        public JdbcTemplate createJdbcTemplate(DataSource dataSource) {
            return new JdbcTemplate(dataSource);
        }
    
        //将DataSource注入到Spring容器中
        @Bean
        public DataSource createDatasource() {
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource.setUrl("jdbc:mysql://localhost:3306/localtest");
            dataSource.setUsername("root");
            dataSource.setPassword("mysql04141015");
            return dataSource;
        }
 }

5.用于加载配置文件

    @PropertySource("classpath:配置文件")
    配合@Value使用
    
    @PropertySource("classpath:druid.properties")
    public class JDBCConfiguration {
    
    
        @Value("${driverClassName}")
        String driverClassName;
    
        @Value("${url}")
        String url;
    
        @Value("${username}")
        String username;
    
        @Value("${password}")
        String password;
    
    
        //将JdbcTemplate注入到Spring容器中
        @Bean("jdbcTemplate")
        public JdbcTemplate createJdbcTemplate(DataSource dataSource) {
            return new JdbcTemplate(dataSource);
        }
    
        //将DataSource注入到Spring容器中
        @Bean
        public DataSource createDatasource() {
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDriverClassName(driverClassName);
            dataSource.setUrl(url);
            dataSource.setUsername(username);
            dataSource.setPassword(password);
            return dataSource;
        }
 }

6.用于和Juit整合

1.@RunWith(SpringJunit4ClassRunner.class)
        作用:JUnit默认是提供了一个main方法,然后去找@Test注解,不会加载Spring文件,使用它可以替换掉main方法,使用Spring提供的
2.@ContextConfiguration
        作用:告诉spring运行器,spring创建是基于xml还是注解,并且指定文件位置
        属性:
            locations:指定xml文件的地址,需要加上classpath,表示在类路径下
            classes:指定注解类所在的位置
    ⚠️:SpringJUnit4ClassRunner requires JUnit 4.12 or higher.Spring5.x版本需要Junit在4.12及以上版本
=========================     ========================= 
⚠️:注解和xml选用原则:对于自己写的类使用注解更方便,对于别人写好的类还是使用xml,因为使用注解很麻烦,需要各种配置

AOP

AOP即“面向切面编程”,基于动态代理实现的,对程序的功能进行统一的维护,降低各部分业务逻辑之间的耦合,提高程序复用性和维护性
动态代理:
    通过代理真实对象,在客户端对象与真实对象之间起到中介作用,在不改变真实对象的源码情况下,来增强真实对象的功能
    分类:
        JDK提供的基于接口的动态代理
        Proxy.newInstance(目标对象类加载器、目标对象的接口、方法)
        Cglib提供的基于子类的动态代理
AOP会根据目标对象有没有实现接口来决定采用哪种代理方式

1.导入jar包:

 <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
 </dependency>

xml中配置AOP

1.配置步骤:
    1.将切面类存入到Spring容器中
    2.开始配置AOP
    3.配置切面
    4.配置通知类型 并且 将通知方法与切入点方法关联
    <!--配置切面类-->
    <bean id="logger" class="com.djn.springaop.Logger"></bean>
    <!--配置AOP-->
    <aop:config>
        <!--通用切入点表达式:
             id是表达式的表示标示
             expression是表达式
             必须配置在上面,使用pointcut-ref引用
             * com.djn.springaop.*.*(..)
             表示com.djn.springaop包下的所有类的所有方法;(..)表示所有的方法不管有没有参数都会执行,如果需要指定需要指定参数类型
        -->
        <aop:pointcut id="pt1" expression="execution(* com.djn.springaop.*.*(..))"></aop:pointcut>
        <!--配置切面-->
        <aop:aspect id="logAdvice" ref="logger">
            <!--配置通知类型 以及将通知方法和切入点方法关联-->
            
            <!--前置通知 切入点方法之前执行-->
            <aop:before method="beforePrint" pointcut-ref="pt1"></aop:before>
            <!--后置通知 切入点方法正常执行后执行,和异常通知只有一个会被执行-->
            <aop:after-returning method="afterReturningPrint" pointcut-ref="pt1"></aop:after-returning>
            <!--异常通知 切入点方法正常执行抛异常后执行,和后置通知只有一个会被执行-->
            <aop:after-throwing method="afterThrowingPrint" pointcut-ref="pt1"></aop:after-throwing>
            <!--最终通知 切入点方法无执行结束后执行 一定会被执行-->
            <aop:after method="afterPrint" pointcut="execution(* com.djn.springaop.*.*(..))"></aop:after>
            <!--环绕通知 需要明确指出切入点-->
            <aop:around method="aroundPrint" pointcut-ref="pt1"></aop:around>
        </aop:aspect>
    </aop:config>
2.环绕通知
    /**
     * 环绕通知
     *  问题:当配置了环绕通知后,切入点方法不执行,而只有通知方法执行了
     *  原因:环绕通知需要配置明确的切入点
     *  解决:Spring框架提供了ProceedingJoinPoint,该接口又一个方法proceed,就是指定明确的切入点
     *  其实环绕通知就是让我们可以手动指定通知方法何时执行
     */
    public static Object aroundPrint(ProceedingJoinPoint pdj) {
        Object value = null;
        try {
            System.out.println("前置通知Logger的afterPrint开始记录日志了...");
            Object[] args = pdj.getArgs();
            value = pdj.proceed(args);
            System.out.println("后置通知Logger的afterPrint开始记录日志了...");
            return value;
        } catch (Throwable throwable) {
            System.out.println("异常通知Logger的afterPrint开始记录日志了...");

            throw new RuntimeException(throwable);
        } finally {
            System.out.println("最终通知Logger的afterPrint开始记录日志了...");
        }
    }

⚠️:除了环绕通知其他四个通知顺序可能会打乱,所以建议还是使用环绕通知!!!!!!!!!

基于注解AOP

1.配置步骤
    1.@Component
        作用:将切面类存入Spring容器
    2.@Aspect
        作用:配置AOP
    3.@EnableAspectJAutoProxy
        作用:开启AOP
        等同于在xml中 <aop:aspectj-autoproxy/>
    3.@Before @AfterReturning @AfterThrowing @After @Around
        作用:通知类型
        属性:
            value:切入点表达式
    4.@Pointcut
        作用:通用切入点表达式
    5.在xml中扫描包 <context:component-scan/>
    
@Component("logger")
@Aspect
@EnableAspectJAutoProxy
public class LoggerAnnotation {

    @Pointcut("execution(* com.djn.springaop.*.*(..))")
    private void pt(){}

    @Before("pt()")
    public static void beforePrint() {
        System.out.println("前置通知Logger的beforePrint开始记录日志了...");
    }

    @AfterReturning("pt()")
    public static void afterReturningPrint() {
        System.out.println("后置通知Logger的afterPrint开始记录日志了...");
    }

    @AfterThrowing("pt()")
    public static void afterThrowingPrint() {
        System.out.println("异常通知Logger的afterReturningPrint开始记录日志了...");
    }

    @After("pt()")
    public static void afterPrint() {
        System.out.println("最终通知Logger的afterPrint开始记录日志了...");
    }

    /**
     * 环绕通知
     *  问题:当配置了环绕通知后,切入点方法不执行,而只有通知方法执行了
     *  原因:环绕通知需要配置明确的切入点
     *  解决:Spring框架提供了ProceedingJoinPoint,该接口又一个方法proceed,就是指定明确的切入点
     */
    @Around("pt()")
    public static Object aroundPrint(ProceedingJoinPoint pdj) {

        Object value = null;
        try {
            System.out.println("前置通知开始记录日志了...");
            Object[] args = pdj.getArgs();
            value = pdj.proceed(args);
            System.out.println("后置通知开始记录日志了...");
            return value;
        } catch (Throwable throwable) {
            System.out.println("异常通知开始记录日志了...");

            throw new RuntimeException(throwable);
        } finally {
            System.out.println("最终通知开始记录日志了...");
        }
    }
}

声明式事务

基于XML的事务

1.配置事务管理器
2.配置事务通知
3.配置AOP
4.配置通用表达式
5.将通知方法与切入点方法关联
6.配置事务的属性
<?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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置Spring创建容器时要扫描的包 注解扫描-->
    <context:component-scan base-package="com.djn.transaction"></context:component-scan>

    <!--开启AOP-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    <!--配置JDBC-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/localtest"></property>
        <property name="username" value="root"></property>
        <property name="password" value="mysql04141015"></property>
    </bean>

    <!--配置事务管理器-->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置事务的通知-->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <!--配置事务的属性
                isolation:用于指定事务的隔离级别,默认是DEFAULT,表示使用数据库默认的隔离级别
                propagation:用于指定事务的传播行为
                    默认是REQUIRED,表示一定会有事务,增删改选择它
                    SUPPORTS,表示有事务就用,没有就拉到,查找选择它
                read-only:表示是否只读,只有查询方法才能设置为true,默认是false,表示读写
                timeout:事务的超时时间,默认-1,表示永不超时,以秒为单位
                roback-for:指定一个异常,只有出现该异常事务才回滚,其他异常不回滚
                noroback-for:与roback-for相反,指定一个异常,只有出现该异常不回滚,其他异常才回滚
        -->
        <tx:attributes>
            <tx:method name="transfer" propagation="REQUIRED" isolation="REPEATABLE_READ" read-only="false"/>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <!--配置AOP-->
    <aop:config>
        <!--通用表达式-->
        <aop:pointcut id="pt1" expression="execution(* com.djn.transaction.*.*(..))"></aop:pointcut>
        <!--建立事务通知和切入点的关联-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
    </aop:config>
</beans>

基于注解的事务

1.配置事务管理器
2.开启Spring对事务注解的支持
3.在需要开启事务的类上或者方法上添加@Transactionl注解
    
<?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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置Spring创建容器时要扫描的包 注解扫描-->
    <context:component-scan base-package="com.djn.transaction"></context:component-scan>

    <!--开启AOP-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    <!--配置JDBC-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/localtest"></property>
        <property name="username" value="root"></property>
        <property name="password" value="mysql04141015"></property>
    </bean>

    <!--配置事务管理器-->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--开启spring对事务注解的支持-->
    <tx:annotation-driven transaction-manager="txManager"></tx:annotation-driven>
</beans>

整合Mybatis

Mybatis-spring 可以将mybatis代码无缝的整合到spring中,它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中

第一种方式

对于Mapper需要有一个实现类,然后注入SqlSession操作,并且将实现类注入到Spring容器中

1.导入jar包

<!--spring核心-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.9.RELEASE</version>
</dependency>

<!--mybatis-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.3</version>
</dependency>

<!--数据库-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.6</version>
</dependency>

<!--测试-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

<!--aopzhi ru织入-->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>



<!--spring和mybatis整合     -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <!--2.0+版本需要mybatis在3.5+ spring在5.0+-->
    <version>2.0.3</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.2</version>
</dependency>

2.配置dataSource和SqlsessionFactory

 <!--dataSource 使用Spring的数据源替换Mybatis的配置-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/localtest"></property>
        <property name="username" value="root"></property>
        <property name="password" value="mysql04141015"></property>
    </bean>

    <!--SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
      	<!--mybatis的配置文件 虽然也可以在spring配置中实现-->
        <property name="configLocation" value="mybatis-config.xml"></property>
    </bean>

3.创建sqlsession

不需要再直接使用sqlSessionFactory来创建sqlsession了,SqlSessionTemplate是sqlsession的一个实现类,他可以无缝代替sqlsession,它是线程安全的,可以被多个DAO和映射器使用

	<!--创建sqlSession-->
 <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
     <constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
 </bean>

4.在实现类中注入sqlsession,并且将实现类注入到Spring容器

public class StudentMapperImpl implements StudentMapper {

    private SqlSession sqlSession;

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

    public List<Student> findAll() {
        return sqlSession.getMapper(StudentMapper.class).findAll();
    }
}
  <bean id="studentMapper" class="com.djn.springmybatis.mapper.StudentMapperImpl">
        <property name="sqlSession" ref="sqlSession"></property>
  </bean>

5.开始调用

public class UserMapperTest {
    @Test
    public void findAll() throws IOException {
      	//读取配置文件 创建spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-beans.xml");
      	//获取实现类
        StudentMapper studentMapper = (StudentMapper) context.getBean("studentMapper");
        List<Student> studentList = studentMapper.findAll();
        for (Student student : studentList) {
            System.out.println(student);
        }
    }
}

第二种方式

不需要在spring.xml注入sqlSession,而是通过继承SqlSessionDaoSupport,直接getSession()获取Sqlsession,同样需要将实现类注入到Spring容器中

public class StudentMapperImpl extends SqlSessionDaoSupport implements StudentMapper {
 
    public List<Student> findAll() {
        return getSqlSession().getMapper(StudentMapper.class).findAll();
    }
}

2.在spring.xml配置 需要注入sqlSessionFactory

<bean id="studentMapper" class="com.djn.springmybatis.mapper.StudentMapperImpl">
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

第三种方式(常用)

不需要一个Mapper的实现类,也不需要继承SqlSessionDaoSupport,而是配置dao接口的扫描,动态的实现dao接口可以注入到Mapper容器中

<!--5.扫描dao接口,动态注入到容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!--要扫描的dao包-->
    <property name="basePackage" value="com.djn.dao"/>
    <!--注入sqlSessionFactory-->
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
posted @ 2020-04-21 01:42  范特西-  阅读(140)  评论(0)    收藏  举报