Spring框架底层原理,原来这样简单(非常全面)

全面剖析Spring框架技术原理(非常全面)

​ Spring是一个全面的解决方案,但他坚持的原则:不重新发明轮子。

​ Spring框架由大约20个功能模块组成。这些模块被分成六个部分,分别是Core Container 、 data/access/Integration、Web、AOP(aspect Oriented Programming)、Instrumntaion及Test。

SpringCore是框架的最基础的部分,提供了IoC特性。Spring Context为企业级开发提供了便利和集成的工具。SpringAOP是基于Spring Core的符合规范的面向切面的编程实现。SpringJDBC提供了JDBC的抽象层,简化了jdbc编码,同时使用代码更健壮。SpringORM对市面上流行的ORM框架提供了支持。SpringWeb为Spring在web应用程序中的使用提供了支持。

Spirng框架的体现结构

Spring是一个开源框架

②Spring为简化企业级开发而生,使用Spring开发可以将Bean对象,Dao组件对象,Service组件对象等交给Spring容器来管理,这样使得很多复杂的代码在Spring中开发却变得非常的优雅和简洁,有效的降低代码的耦合度,极大的方便项目的后期维护、升级和扩展。

③Spring是一个IOC(DI)和AOP容器框架。

④Spring的优良特性

[1]非侵入式:基于Spring开发的应用中的对象可以不依赖于Spring的API

[2]控制反转:IOC——Inversion of Control,指的是将对象的创建权交给Spring去创建。使用Spring之前,对象的创建都是由我们自己在代码中new创建。而使用Spring之后。对象的创建都是由给了Spring框架。

[3]依赖注入:DI——Dependency Injection,是指依赖的对象不需要手动调用setXX方法去设置,而是通过配置赋值。

[4]面向切面编程:Aspect Oriented Programming——AOP

[5]容器:Spring是一个容器,因为它包含并且管理应用对象的生命周期

[6]组件化:Spring实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用XML和Java注解组合这些对象。

[7]一站式:在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上Spring 自身也提供了表述层的SpringMVC和持久层的Spring JDBC)

SpringIoC

控制反转(Inversion of Control,IoC),也称依赖注入(Dependency Injection,DI),是面向对象编程中的一种设计理念,用来降低程序代码之间的耦合程度。

​ 首先简单的说一下IOC(控制反转),IOC的基本思想就是反转资源获取的方向,传统的资源查找方式要求组件向容器发起请求,然后获取到所要请求的资源作为回应,应用了IOC之后,则是容器主动的将资源推送给它所管理的组件,组件只需要做的是选择一种合适的方式来接受资源,这种行为就被看做是组件被动的查找资源。DI(依赖注入),这个是对IOC的另一种表达方式,也就是组件以一些预先定义好的方式(例如setter方法)接受来自容器的资源注入,相对于IOC而言,这种表述更直接。

​ IoC(Inversion of Control)控制反转,对象创建责任的反转,在spring中BeanFacotory是IoC容器的核心接口,负责实例化,定位,配置应用程序中的对象及建立这些对象间的依赖。XmlBeanFacotory实现BeanFactory接口,通过获取xml配置文件数据,组成应用对象及对象间的依赖关系。

Spring框架分为四大模块:
Core核心模块。负责管理组件的Bean对象

spring-beans-4.0.0.RELEASE.jar

spring-context-4.0.0.RELEASE.jar

spring-core-4.0.0.RELEASE.jar

spring-expression-4.0.0.RELEASE.jar

创建一个HelloWorld类

HelloWorld.java

public class HelloWorld {

	private String user;
	
	public HelloWorld() {
		System.out.println("HelloWorld's constructor...");
	}
	
	public void setUser(String user) {
		System.out.println("setUser:" + user);
		this.user = user;
	}
	
	public HelloWorld(String user) {
		this.user = user;
	}

	public void hello(){
		System.out.println("Hello: " + user);
	}
	
}

创建Spring容器的xml配置文件,在项目根目录下(Eclipse的src目录、idea中使用resources目录,如果没有,可以自己创建)

applicationContext.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:util="http://www.springframework.org/schema/util"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
	
	<!-- 配置一个 bean -->
	<bean id="helloWorld" class="com.spring.helloworld.HelloWorld">
		<!-- 为属性赋值 -->
		<property name="user" value="Jerry"></property>
	</bean>
</bean>

测试类

public static void main(String[] args) {
//1. 创建 Spring 的 IOC 容器
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		//2. 从 IOC 容器中获取 bean 的实例
		HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");
		//根据类型来获取 bean 的实例: 要求在  IOC 容器中只有一个与之类型匹配的 bean, 若有多个则会抛出异常. 
		//3. 使用 bean
		helloWorld.hello();
}

​ 除了ClassPathXmlApplicationContext,ApplicationContext接口还有他实现类。例如FileSystemXmlApplicationContext也可用于加载Spring配置文件。

​ 除了ApplicationContext及其实现类,还可以通过BeanFactory接口及其实现类对Beran组件实施管理。

事实上,ApplicationContext就是建立在BeanFactory的基础上,BeanFactory是SpringIoc容器的核心,负责管理和它们之间的依赖关系,应用程序通过BeanFactory接口与springIoC容器交互。ApplicationContext是BeanFactory的子接口。

​ 容器负责吧组件所**依赖的具体对象注入(赋值给组件),从而避免组件之间以硬编码的方式耦合在一起。

SpringAOP

什么是AOP

AOP(Aspect-OrientedProgramming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

	而**AOP**技术则恰恰相反,它利用一种称为“**横切**”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“**Aspect**”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。**AOP**代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。

AOP的基本概念

  • (1)Aspect(切面):通常是一个类,里面可以定义切入点和通知
  • (2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
  • (3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
  • (4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
  • (5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

通知方法:

  1. 前置通知:在我们执行目标方法之前运行(@Before)
  2. 后置通知:在我们目标方法运行结束之后 ,不管有没有异常**(@After)**
  3. 返回通知:在我们的目标方法正常返回值后运行**(@AfterReturning)**
  4. 异常通知:在我们的目标方法出现异常后运行**(@AfterThrowing)**
  5. 环绕通知:动态代理, 需要手动执行joinPoint.procced()(其实就是执行我们的目标方法执行之前相当于前置通知, 执行之后就相当于我们后置通知**(@Around)**

启用@AspectJ支持

为了在Spring配置中使用@AspectJ切面,你首先必须启用Spring对@AspectJ切面配置的支持,并确保*自动代理(autoproxying)*的bean是否能被这些切面通知。自动代理是指Spring会判断一个bean是否使用了一个或多个切面通知,并据此自动生成相应的代理以拦截其方法调用,并且确保通知在需要时执行。

通过在你的Spring的配置中引入下列元素来启用Spring对@AspectJ的支持:

<aop:aspectj-autoproxy/>

SpringAOP实现

声明一个切面

切面使用aop:aspect来声明,backing bean(支持bean)通过 ref 属性来引用:

<aop:config>
  <aop:aspect id="myAspect" ref="aBean">
    ...
  </aop:aspect>
</aop:config>

<bean id="aBean" class="...">
  ...
</bean>

声明一个切入点

一个命名切入点可以在aop:config元素中定义,这样多个切面和通知就可以共享该切入点。

一个描述service层中所有service执行的切入点可以定义如下:

<aop:config>

  <aop:pointcut id="businessService" 
        expression="execution(* com.xyz.myapp.service.*.*(..))"/>

</aop:config>
<aop:config>

  <aop:aspect id="myAspect" ref="aBean">

    <aop:pointcut id="businessService" 
          expression="execution(* com.xyz.myapp.service.*.*(..)) &amp;&amp; this(service)"/>
    <aop:before pointcut-ref="businessService" method="monitor"/>
    ...
    
  </aop:aspect>

</aop:config>
前置通知

前置通知在匹配方法执行前运行。在<aop:aspect>中使用aop:before 元素来声明它。

<aop:aspect id="beforeExample" ref="aBean">

    <aop:before 
      pointcut-ref="dataAccessOperation" 
      method="doAccessCheck"/>
          
    ...
    
</aop:aspect>
后置通知

后置通知在匹配的方法完全执行后运行。和前置通知一样,可以在<aop:aspect> 里面声明它。例如:

<aop:aspect id="afterReturningExample" ref="aBean">

    <aop:after-returning 
      pointcut-ref="dataAccessOperation" 
      method="doAccessCheck"/>
          
    ...
    
</aop:aspect>
异常通知

异常通知在匹配方法抛出异常退出时执行。在<aop:aspect>中使用 after-throwing元素来声明:

<aop:aspect id="afterThrowingExample" ref="aBean">

    <aop:after-throwing
      pointcut-ref="dataAccessOperation" 
      method="doRecoveryActions"/>
          
    ...
    
</aop:aspect>
最终通知

最终通知无论如何都会在匹配方法退出后执行。使用after元素来声明它:

<aop:aspect id="afterFinallyExample" ref="aBean">

    <aop:after
      pointcut-ref="dataAccessOperation" 
      method="doReleaseLock"/>
          
    ...
    
</aop:aspect>
环绕通知

环绕通知是最后一种通知类型。环绕通知在匹配方法运行期的“周围”执行。 它有机会在目标方法的前面和后面执行,并决定什么时候运行,怎么运行,甚至是否运行。 环绕通知经常在需要在一个方法执行前后共享状态信息,并且是在线程安全的情况下使用 (启动和停止一个计时器就是一个例子)。注意选择能满足你需求的最简单的通知类型; 如果简单的前置通知能做的事情就绝对不要使用环绕通知。

Around通知使用aop:around元素来声明。通知方法的第一个参数的类型必须是 ProceedingJoinPoint类型。在通知的主体中,调用 ProceedingJoinPointproceed()方法来执行真正的方法。 proceed方法也可能会被调用并且传入一个Object[]对象 - 该数组将作为方法执行时候的参数。参见Section 6.2.4.5, “环绕通知”中调用具有 Object[]的proceed方法。

<aop:aspect id="aroundExample" ref="aBean">

    <aop:around
      pointcut-ref="businessService" 
      method="doBasicProfiling"/>
          
    ...
    
</aop:aspect>
<aop:config>

  <aop:aspect id="concurrentOperationRetry" ref="concurrentOperationExecutor">

    <aop:pointcut id="idempotentOperation"
        expression="execution(* com.xyz.myapp.service.*.*(..))"/>
       
    <aop:around
       pointcut-ref="idempotentOperation"
       method="doConcurrentOperation"/>
  
  </aop:aspect>

</aop:config>

<bean id="concurrentOperationExecutor"
  class="com.xyz.myapp.service.impl.ConcurrentOperationExecutor">
     <property name="maxRetries" value="3"/>
     <property name="order" value="100"/>  
</bean>

Aspectj实现AOP

声明一个切面

启用@AspectJ支持后,在application context中定义的任意带有一个@Aspect切面(拥有@Aspect注解)的bean都将被Spring自动识别并用于配置Spring AOP。以下例子展示了为完成一个不是非常有用的切面所需要的最小定义:

application context中一个常见的bean定义,它指向一个使用了@Aspect注解的bean类:

<bean id="myAspect" class="org.xyz.NotVeryUsefulAspect">
         <!-- configure properties of aspect here as normal -->
      </bean>
      
切入点指示符(PCD)的支持

Spring AOP支持在切入点表达式中使用如下的AspectJ切入点指示符:

其他的切入点类型

完整的AspectJ切入点语言支持额外的切入点指示符,但是Spring并不支持。它们分别是call, get, set, preinitialization, staticinitialization, initialization, handler, adviceexecution, withincode, cflow,cflowbelow, if, @this@withincode。在Spring AOP中使用这些指示符将会导致抛出IllegalArgumentException异常。

Spring AOP支持的切入点指示符可能会在将来的版本中得到扩展,从而支持更多的AspectJ切入点指示符。

  • execution - 匹配方法执行的连接点,这是你将会用到的Spring的最主要的切入点指示符。
  • within - 限定匹配特定类型的连接点(在使用Spring AOP的时候,在匹配的类型中定义的方法的执行)。
  • this - 限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中bean reference(Spring AOP 代理)是指定类型的实例。
  • target - 限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中目标对象(被代理的应用对象)是指定类型的实例。
  • args - 限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中参数是指定类型的实例。
  • @target - 限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中正执行对象的类持有指定类型的注解。
  • @args - 限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中实际传入参数的运行时类型持有指定类型的注解。
  • @within - 限定匹配特定的连接点,其中连接点所在类型已指定注解(在使用Spring AOP的时候,所执行的方法所在类型已指定注解)。
  • @annotation - 限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中连接点的主题持有指定的注解。
异常通知(After throwing advice)

抛出异常通知在一个方法抛出异常后执行。使用@AfterThrowing注解来声明:

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;

@Aspect
public class AfterThrowingExample {

  @AfterThrowing"com.xyz.myapp.SystemArchitecture.dataAccessOperation()"public void doRecoveryActions() {
    // ...
  }

}
最终通知(After (finally) advice)

不论一个方法是如何结束的,最终通知都会运行。使用@After 注解来声明。最终通知必须准备处理正常返回和异常返回两种情况。通常用它来释放资源。

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

@Aspect
public class AfterFinallyExample {

  @After"com.xyz.myapp.SystemArchitecture.dataAccessOperation()"public void doReleaseLock() {
    // ...
  }

}
环绕通知

最后一种通知是环绕通知。环绕通知在一个方法执行之前和之后执行。它使得通知有机会 在一个方法执行之前和执行之后运行。而且它可以决定这个方法在什么时候执行,如何执行,甚至是否执行。 环绕通知经常在某线程安全的环境下,你需要在一个方法执行之前和之后共享某种状态的时候使用。 请尽量使用最简单的满足你需求的通知。(比如如果简单的前置通知也可以适用的情况下不要使用环绕通知)。

环绕通知使用@Around注解来声明。通知的第一个参数必须是 ProceedingJoinPoint类型。在通知体内,调用 ProceedingJoinPointproceed()方法会导致 后台的连接点方法执行。proceed 方法也可能会被调用并且传入一个 Object[]对象-该数组中的值将被作为方法执行时的参数。

*当传入一个Object[]对象的时候,处理的方法与通过AspectJ编译器处理环绕通知略有不同。 对于使用传统AspectJ语言写的环绕通知来说,传入参数的数量必须和传递给环绕通知的参数数量匹配 (不是后台的连接点接受的参数数量),并且特定顺序的传入参数代替了将要绑定给连接点的原始值 (如果你看不懂不用担心)。Spring采用的方法更加简单并且能更好匹配它基于代理(proxy-based)的执行语法, 如果你使用AspectJ的编译器和编织器来编译

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;

@Aspect
public class AroundExample {

  @Around"com.xyz.myapp.SystemArchitecture.businessService()"public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
    // start stopwatch
    Object retVal = pjp.proceed();
    // stop stopwatch
    return retVal;
  }
}

Spring整合Mybatis框架实现访问数据库

在spring整合Mybatis框架前我们需要下载spring 整合mybatis框架的jar包,使用方式有两种

通过maven的pox文件添加jar依赖

首先我们需要下载mybatis的jar包

由于在整合中 我们会用到事物和数据源的支持,因此还需要加入spirng-jdbc-.ReLEASE.jar包和spring-tx-.RELEASE.jar包

创建实体类User

User.java

package com.ssm04.pojo;

import java.util.Date;

/**
 * @program: SSM
 * @description: 用户
 * @author: liu qing
 * @create: 2019-09-17 21:28
 */
public class User {
    private Integer id;
    private String userCode;
    private String userName;
    private String userPassword;
    private Integer gender;
    private Date birthday;
    private String phone;
    private String address;
    private Integer userRole;
    private Integer createdBy;
    private String creationDate;
    private Integer modifyBy;
    private String modifyDate;
    private String userRloeName;
    private Integer age;
    /**
     * 用户角色
     */
    private  Role role;


    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }

    public String getUserRloeName() {
        return userRloeName;
    }

    public void setUserRloeName(String userRloeName) {
        this.userRloeName = userRloeName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getUserRoleName() {
        return userRloeName;
    }

    public void setUserRoleName(String userRoleName) {
        this.userRloeName = userRoleName;
    }
}

创建数据访问接口

UserMapper.java

package com.ssm04.mapper;

import com.ssm04.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface UserMapper {

    //示例2
    List<User> getUserList(User user);


    //示例6
    /**
     * 查询用户列表(参数:Map)
     * @param userMap
     * @return
     */
    List<User> getUserListBymap(Map<String, String> userMap);


    //示例10
    List<User> getUserListp(User user);


    //增加方法
     int add(User user);


    //修改
     int modify(User user);


    //使用@Param注解实现多参数入参

     int updatePwd(@Param("id") Integer id, @Param("userPassword") String pwd);


    //delete方法
     int deleteUserById(@Param("id") Integer delId);


     List<User> getUserListId(@Param("userRole") Integer roleId);


}

创建mybatis的xml映射文件

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssm04.mapper.UserMapper">
    <select id="getUserListByUserName" resultType="User" parameterType="string">
        select * from smbms_user where userName like concat('%',#{userName},'%')
    </select>

<!--    //示例三-->
    <select id="getUserList" resultType="User" parameterType="User">
        select * from smbms_user where userName like concat('%',#{userName},'%') and userRole = #{userRole}
    </select>


<!--    //示例7-->
    <select id="getUserListBymap" resultType="User" parameterType="Map">
        select * from smbms_user where userName like concat('%',#{uName},'%') and userRole = #{uRole}
    </select>


    <!--    //示例8-->
    <select id="getUserListp" resultMap="userList" parameterType="User">
     select u.*,r.rloeName
     from smbms_user u,smbms_role r
     where u.userName like concat('%',#{userName},'%') and u.userRole = #{userRole} and u.userRole = r.id
    </select>


<!--    增加用户-->
    <insert id="add" parameterType="User">
        insert  into smbms_user (userCode,userName,userPassword,gender,birthday,phone,address,userRole,createdBy,creationDate)
                values (#{userCode},#{userName},#{userPassword},#{gender},#{birthday},#{phone},#{address},#{userRole},#{createdBy},#{creationDate})
    </insert>

<!--    示例9-->
    <resultMap type="User" id="userList">
     <result property="id" column="id"/>
      <result property="userName" column="userName"/>
       <result property="userRloeName" column="rloeName"/>
    </resultMap>
    <!--    示例13-->
    <!--    !&#45;&#45;    修改用户&ndash;&gt;-->
    <update id="modify" parameterType="User">
          update smbms_user set userCode=#{userCode},userName=#{userName},userPassword=#{userPassword},phone=#{phone} where id = #{id}
    </update>


<!--    示例15-->
<!--    //修改当用户密码-->
    <update id="updatePwd">
       update smbms_user set userPassword=#{userPassword} where id = #{id}
    </update>

<!--    示例17-->
    <delete id="deleteUserById" parameterType="Integer">
        delete from smbms_user where id=#{id}
    </delete>

    <resultMap id="userRoleResult" type="User">
        <id property="id" column="id"/>
        <result property="userCode" column="userCode" />
        <result property="userName" column="userName"/>
        <result property="userRole" column="userRole" />
        <association property="role" javaType="com.ssm04.pojo.Role">
            <id property="id" column="r_id"/>
           <result property="roleCode" column="roleCode"/>
            <result property="rloeName" column="rloeName"/>
        </association>
    </resultMap>
    <select id="getUserListId" resultMap="userRoleResult">
          select u.*,r.id as r_id,r.roleCode,r.rloeName
            from smbms_user u,smbms_role r where u.userRole = #{userRole} and u.userRole = r.id
    </select>
</mapper>

创建mybatis配置文件

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
 
</configuration>

建立spring容器的配置文件

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

</beans>

配置数据源

 <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url">
            <value><![CDATA[jdbc:mysql://127.0.0.1:3306/easybuy?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8]]></value>
        </property>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

**在创建一个bean **id为dataSource

org.apache.commons.dbcp2.BasicDataSource:dbcp数据库连接池

driverClassName:mysql数据库驱动

url:数据库连接url

username :数据库用户名

password :数据库密码

<![CDATA[jdbc:mysql://127.0.0.1:3306/easybuy?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8]]>

因为url属性的值包含特殊符合“&”,所以**这里需要将数据连接url进行转义**

配置SqSessoionFactoryBean

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

org.mybatis.spring.SqlSessionFactoryBean:在mybatis中,SqlSessionFactory由SqlSessionFactoryBuilder创建,在mybatis-spring中,是由SqlSessionFactoryBean创建的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值