Spring入门

375 阅读10分钟

一、Spring简介

1.Spring是一个轻量级的开源框架 , Spring -jar包下载地址:repo.spring.io/release/
2.内容:
• IoC容器
• AOP实现
• 数据访问支持
——简化JDBC/ORM 框架
——声明式事务
• Web集成

3.Spring的优点:

低侵入式设计
独立于各种应用服务器
依赖注入特性将组件关系透明化,降低了耦合度
面向切面编程特性允许将通用任务进行集中式处理
与第三方框架的良好整合

二、Spring的核心

控制反转(IoC:Inversion of Control)/依赖注入(DI:Dependecy Iniection)
面向切面编程(AOP:Aspect Oriented Programming)

1.控制反转/依赖注入
注入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"
	    xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd">
		<!-- 将需要在Spring中创建的类在配置文件中说明 -->
		<bean id="showHello" class="com.spring.ShowHello">
			<property name="helloWorld" ref="zhHelloWorld"></property>
		</bean>
</beans>

其中,id是Bean的标识,class是Bean的全限定名。这样通过BeanFactory容器的getBean(“showHello”);方法可以获取该类的实例
<property>表示Bean的属性,name为属性名,value为属性值,<property>节点可通过ref属性引用其他已经配置的Bean,ref的值是其他已经配置的Bean的标识。

public class IoCDemo {
    public static void main(String[] args){
	private static String path = "cn/ekgc/myspring/day02/ioc.xml";
	private static ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(path);
		HelloWorld helloworld=(HelloWorld)context.getBean("helloWorld");
		helloworld.sayHello();
	}

简而言之IoC就是对对象的创建权由代码转为外部容器(Spring)进行创建的方式,这种权力的转移称为控制反转。这种由容器控制程序之间的(依赖)关系,而非传统由代码操控。减轻降低了组件之间的依赖关系和耦合度。

2.面向切面编程(AOP)
aop.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"
		xsi:schemaLocation="http://www.springframework.org/schema/beans
			    	    http://www.springframework.org/schema/beans/spring-beans.xsd
			       	    http://www.springframework.org/schema/aop
				    http://www.springframework.org/schema/aop/spring-aop.xsd">
		<!-- 将需要Spring创建的类进行注册-->
	<bean id="userDao" class="com.myspring.UserDaoImpl"/>
	<bean id="userLogger" class="com.myspring.UserLogger"/>
	<!-- 使用Spring为我们提供的AOP功能实现切入-->
	<aop:pointcut expression="execution(*com.spring.UserDao.*(..))" id="myPointcut"/>
	    <aop:aspect id="myAspect" ref="userlogger">
	<!--设定在执行前还是执行后,即执行时机-->
	        <aop:before method="beforeSaveUser" pointcut-ref="myPointcut"/>
	        <aop:after method="afterSaveUser" pointcut-ref="myPointcut"/>
	    </aop:aspect>
	</aop:config>
</beans>

SpringAOP的实现是基于Java的代理机制。所谓面向切面编程,是一种通过预编译和运行期动态代理的方式实现在不修改源代码的情况下给程序动态添加功能的技术
AOP相关术语

增强处理(Advice) (前置增强、后置增强、环绕增强、异常抛出增强、最终增强等类型)
切入点(Pointcut)
连接点(Join Point)
切面(Aspect)
目标对象(Target object)
AOP代理(AOP proxy)
织入(Weaving)

3.依赖注入的方式
Setter注入(Setter Injection)
---基于JavaBean的Setter()方法为属性赋值,完成依赖关系的设置 灵活性好,但setter方法数量较多,时效性差
接口注入(Interface Injection)
---基于接口将调用与实现分离,这种注入方式必须实现容器所规定的接口。
构造器(方法)注入(Constructor Injection) Spring容器通过注入类的构造方法为属性赋值,将其所需的依赖关系注入其中。灵活性差,仅靠重载限制太多,时效性好。通过匹配的构造方法实例化,但建议保留无参构造

<bean id="user" class="com.newspring.User">
		<constructor-arg index="0" value="李逍遥"></constructor-arg>
	        <constructor-arg index="1" value="123456"></constructor-arg>
</bean>

在Spring配置文件中通过<constructor-arg>元素为构造方法传参:
a.通过<constructor-arg>元素的index 属性可以指定该参数的位置索引,位置从0 开始
b.<constructor-arg>元素还提供了type 属性用来指定参数的类型,避免字符串和基本数据类型的混淆
ioc.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">
	<!-- 注册需要Spring进行创建的bean组件 -->
	<bean id="user" class="cn.ekgc.myspring.day02.User">
		<!-- 如果需要进行依赖注入,那么使用标签property,使用的是setter方法注入
		<property name="username" value="李逍遥"/> -->
		<!-- 如果需要Spring在创建对象的时候,使用明确的构造方法,以便于将值进行注入 -->
		<!-- 那么,使用的就是构造方法注入 -->
		<constructor-arg index="0" value="重楼"/>
		<constructor-arg index="1" value="12345678901"/>
	</bean>
	<bean id="userService" class="cn.ekgc.myspring.day02.impl.UserServiceImpl"/>
	<bean id="userController" class="cn.ekgc.myspring.day02.UserController">
		<!-- 在控制层中,也存在一个属性,是一个接口UserService,因此使用接口注入 -->
		<property name="userService" ref="userService"></property>
	</bean>
</beans>

Spring支持集合注入(通过Spring容器为注入类的集合属性赋值的方式)

List注入
Set注入
Map注入
Property注入

分别使用<list>、<set>、<map>、<props>标签实现。
Student.Java

package cn.ekgc.myspring.day02;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class Student {
	private Long studentNo;
	private List<String> hobbyList;
	private Set<String> friendSet;
	private Map<String, String> countryMap;
	private Properties props;
	
	public void show() {
		System.out.println("studentNo = " + studentNo);
		System.out.println("=========注入List集合=========");
		for (String hobby : hobbyList) {
			System.out.println(hobby);
		}
		System.out.println("=========注入Set集合=========");
		for (String friend : friendSet) {
			System.out.println(friend);
		}
		System.out.println("=========注入Map集合=========");
		Set<String> keySet = countryMap.keySet();
		for (String key : keySet) {
			System.out.println(key + " : " + countryMap.get(key));
		}
		System.out.println("=========注入Properties=========");
		String value = props.getProperty("key");
		System.out.println(value);
	}

	public Long getStudentNo() {
		return studentNo;
	}
	public void setStudentNo(Long studentNo) {
		this.studentNo = studentNo;
	}
	public List<String> getHobbyList() {
		return hobbyList;
	}
	public void setHobbyList(List<String> hobbyList) {
		this.hobbyList = hobbyList;
	}
	public Set<String> getFriendSet() {
		return friendSet;
	}
	public void setFriendSet(Set<String> friendSet) {
		this.friendSet = friendSet;
	}
	public Map<String, String> getCountryMap() {
		return countryMap;
	}
	public void setCountryMap(Map<String, String> countryMap) {
		this.countryMap = countryMap;
	}
	public Properties getProps() {
		return props;
	}
	public void setProps(Properties props) {
		this.props = props;
	}
}

ioc-test.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="student" class="cn.ekgc.myspring.day02.Student">
		<property name="studentNo" value="9527"/>
		<property name="hobbyList">
			<list>
				<value>足球</value>
				<value>篮球</value>
				<value>排球</value>
				<value>乒乓球</value>
			</list>
		</property>
		<property name="friendSet">
			<set>
				<value>李逍遥</value>
				<value>雪见</value>
				<value>龙葵</value>
				<value>重楼</value>
			</set>
		</property>
		<property name="countryMap">
			<map>
				<entry key="CN" value="中国"/>
				<entry key="USA" value="美国"/>
				<entry key="UK" value="英国"/>
				<entry key="RUS" value="俄罗斯"/>
				<entry key="FR" value="法国"/>
			</map>
		</property>
		<property name="props">
			<props>
				<prop key="key">Spring IoC</prop>
			</props>
		</property>
	</bean>
</beans>

4.Spring AOP常用配置元素

<aop:config>:	    AOP配置的顶层元素,大多数的<aop:*>元素必须包含在<aop:config>元素内
<aop:pointcut>:		定义切点
<aop:aspect>:		定义切面
<aop:after>:		定义最终增强(不管被通知的方法是否执行成功)
<aop:after-returning>:	    定义after-returning增强
<aop:after-throwing>:	    定义after-throwing增强
<aop:around>:		定义环绕增强
<aop:before>:		定义前置增强
<aop:aspectj-autoproxy>:  启动@AspectJ注解驱动的切面

aop.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"
		xsi:schemaLocation="http://www.springframework.org/schema/beans
				    http://www.springframework.org/schema/beans/spring-beans.xsd
				    http://www.springframework.org/schema/aop
				    http://www.springframework.org/schema/aop/spring-aop.xsd">
	<bean id="userService" class="cn.ekgc.myspring.day02.aop.impl.UserServiceImpl"/>
	<bean id="userLogger" class="cn.ekgc.myspring.day02.aop.UserLogger"/>
	
	<!-- 使用Spring为我们提供的AOP进行功能的切入 -->
	<!--
		Spring在使用AOP功能的时候,同时使用了两种代理模式来实现它的AOP功能;
		1、JDK代理:JDK代理是Java原生的代理模式,该代理模式需要使用到接口;
			Spring默认/优先使用JDK代理。
		2、CGLIB代理:对于CGLIB代理来说,解决了JDK代理所必须使用接口这一特点,
			而是可以直接将代理作用在实现类上。
	-->
	<aop:config>
		<!-- 配置整个代理切入的切入点 -->
		<aop:pointcut expression="execution(* cn.ekgc.myspring.day02..*.*(..))" id="myPointcut"/>
		<aop:aspect id="myAspect" ref="userLogger">
			<!-- 设定方法执行的时机 -->
			<aop:before method="beforeSaveUser" pointcut-ref="myPointcut"/>
			<aop:after method="afterSaveUser" pointcut-ref="myPointcut"/>
			<aop:after-throwing method="exceptionSaveUser" throwing="ex" pointcut-ref="myPointcut"/>
		</aop:aspect>
	</aop:config>
</beans>

三、Spring注解

对于Spring来说,其注解方式,就是在简化Spring的配置文件。通过使用注解,可以不再xml中增加任何信息,从而将一个类变成Spring的Bean

有4个能够让一个类变成Bean的标签,分别是:
@Controller :用于标注控制器类 。用于进行处理请求,专门为控制层准备,需要结合Spring MVC
@Service:用于业务层 的注解,不仅仅能够将类变成Bean,而且能够通过AOP将事务切入,处理事务
@Repository:用于标注DAO类 。用于数据持久层,其作用仅仅只是将一个类变成Spring的Bean
@Component:实现Bean组件的定义 。当我们无法区分出来这个类该属于MVC的哪个层次的时候,就可以使用这个注解,这个注解也仅仅是将一个类变成Spring的Bean。

除了在类级别所能够使用的注解之外,还有用在属性上的注解,其目的在于进行依赖注入,有2个:
@Resource(name = ""):其中name属性的值就是需要注入的bean的id,那么,@Resource注解是按照bean的id进行依赖注入,相当于getBean();
@Autowire:当我们不知道bean的id是多少的时候,那么这个注解,就是按照Bean的类型来进行匹配。在使用的时候就要防止通过类型找到多个。

@Transactional:可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时我们也可以在方法级别使用该标注来覆盖类级别的定义。

Spring+Mybatis简例
先导入相应的jar包、以及Druid[ˈdruːɪd]数据库连接池
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" //处理事务
		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
			            http://www.springframework.org/schema/tx
			            http://www.springframework.org/schema/tx/spring-tx.xsd">
	<!-- 如果需要使用到Spring的注解配置,那么就需要设定好Spring对于注解扫描的基础包位置 -->
	<context:component-scan base-package="cn.ekgc.sm"/>
	
	<!-- 对于Spring结合任何ORM框架,都会去使用数据库连接池,这样能够提高效率 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
		<!-- 需要向DataSource中进行依赖注入相关信息 -->
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://localhost:3306/spring-mybatis_db"/>
		<property name="username" value="root"/>
		<property name="password" value="java"/>
		<!-- 为了能够提高整个数据库连接的效率,对于Druid进行相关的配置 -->
		<!-- 配置在数据库连接池中最少能够保留几个连接对象 -->
		<property name="minIdle" value="3"/>
		<!-- 配置在数据库连接池中最多的时候,能够创建多少个连接对象 -->
		<property name="maxActive" value="15"/>
		<!-- 配置当系统进行启动的时候,需要为系统创建多少个连接对象 -->
		<property name="initialSize" value="5"/> 
		<!-- 配置系统为多余的连接对象保留多长时间 -->
		<property name="minEvictableIdleTimeMillis" value="30000"/>
		<property name="maxEvictableIdleTimeMillis" value="60000"/>
	</bean>
	
	<!-- 配置Mybatis的SqlSessionFactory的Bean,让Spring接管Mybatis -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<!-- 指定Mybatis映射文件的位置 -->
		<property name="mapperLocations" value="classpath*:/mapper/*.mapper.xml"/>
	</bean>
	
	<!--
		对于Spring在结合了Mybatis之后,就不需要再为Dao层做具体的接口实现类。
		我们只需要去完成接口即可,这样让Spring能够扫描带这个接口,
		然后会去根据具体的Mybatis映射文件,通过反射机制,来动态的生成一个接口的
		实现类。
	-->
	<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
		<!-- 设定扫描数据持久层接口位置 -->
		<property name="basePackage" value="cn.ekgc.sm.dao"/>
	</bean>
	
	<!-- 配置Spring的事务处理机制 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	<!-- 因为Spring默认的代理机制是JDK,而JDK的代理机制是需要接口的 -->
	<!-- 但是,对于使用注解来说,我们的注解则是直接写在实现类上的 -->
	<!-- 因此,需要将默认的JDK代理模式,切换成CGLIB -->
	<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
</beans>

1.在配置文件applicationContext.xml中使用注解信息启动Spring容器:

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

<!-- 扫描包中注解标注的类 -->
<context:component-scan base-package="service,dao" />  
</beans>                              //指定需要扫描的基类包,多个包可用逗号隔开

在XML中配置了这个<context:component-scan>标签后,spring可以自动扫描base-package下面或者子包下面的java文件,如果扫描有@Component @Service @Controller等这些注解的类,则把这些类注册为bean
2
A

@Service("userDao") 
public class UserDaoImpl implements UserDao {
		…
}

与在XML配置文件中编写<bean id="userDao" class="dao.impl.UserDaoImpl" /> 等效

B

@Service("userService") 
public class UserServiceImpl implements UserService { 
	@Resource(name = "userDao")
	private UserDao dao; 
	…… 
}

为dao属性注入名为userDao的Bean。与在XML配置文件中编写如下等效

<bean id="userService" class="com.spring.UserServiceImpl">
<property name="dao" ref="userDao"></property>
</bean>

C. 使用注解方式定义切面
常用注解有@Aspect、@Before、@AfterReturning、@Around、@AfterThrowing、@After等
在配置文件中添加<aop:aspectj-autoproxy />元素,启用对于@AspectJ注解的支持(使用@AspectJ,首先要保证所用的JDK 是5.0或以上版本)

四、Spring的事务管理

1.事务包含一个或多个业务操作,这些操作要么都执行,要么都不执行。事务必须服从ACID原则 。ACID指的是原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)。
Spring事务管理分为2种方式,即编程式事务管理声明式事务管理
• 编程式事务管理是将事务管理代码嵌到业务方法中来控制事务的提交和回滚。推荐使用TransactionTemplate实现方式
声明式事务管理一般情况下比编程式事务好用。将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。使用TransactionProxyFactoryBean实现

2.Spring配置文件中关于事务配置由三部分组成,分别是DataSourceTransactionManager代理机制配置声明式事务:
• 导入tx和aop命名空间

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="......
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">

• 配置事务管理器,并为其注入数据源Bean

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSources"/>
</bean>

• 通过<tx:advice>配置事务增强(如何管理事务,只读、读写...也就是配置事务的隔离特效)

<tx:advice id="interceptor" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*save*" read-only="false"/>
            <tx:method name="*get*" read-only="true"/>
        </tx:attributes>
</tx:advice>

• 配置切面拦截哪些方法(切入点表达式,拦截上面的事务增强)

<aop:config >
        <aop:pointcut id="pointcut" expression="execution(* com.wzx.studyspringboot.SpringTxManage.*.*(..))"></aop:pointcut>
        <aop:advisor advice-ref="interceptor" pointcut-ref="pointcut"></aop:advisor>
</aop:config>

3.代理机制:
在Java中一般是2种,静态代理动态代理:Spring AOP使用了动态代理,一种是JDK代理,一种是CGLib代理
• JDK代理AOP时,代理目标必须存在接口
• CGLiB(Code Generation Library)为没有实现接口的类提供代理,时JDK动态代理的补充。由于CGLiB直接生成的是子类,子类覆盖代理目标的所有非final的方法。

五、Spring整合Mybatis

1 导入相关jar包
可以在mvnrepository.com/网站找各种jar包

2 建立数据库表
3 根据表建立相应的实体类,并且划分好包结构(控制层Controller、业务层Service、数据持久层Dao)
4 编写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"
		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
                                    http://www.springframework.org/schema/tx
                                    http://www.springframework.org/schema/tx/spring-tx.xsd">
	<!-- 设定Spring注解扫描基础包位置 -->
	<context:component-scan base-package="cn.ekgc.ums"/>

	<!-- 设定Spring读取properties配置文件的路径  -->
	<context:property-placeholder location="classpath:/jdbc.properties"/>
	
	<!-- 配置数据源DataSource信息 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
		<!-- 依赖注入JDBC连接数据库的四个基本信息 -->
		<property name="driverClassName" value="${jdbc.driver}"/>
		<property name="url" value="${jdbc.url}"/>
		<property name="username" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
		<property name="minIdle" value="${druid.minIdle}"/>
		<property name="maxActive" value="${druid.maxActive}"/>
		<property name="initialSize" value="${druid.initialSize}"/>
		<property name="minEvictableIdleTimeMillis" value="${druid.minEvictableIdleTimeMillis}"/>
		<property name="maxEvictableIdleTimeMillis" value="${druid.maxEvictableIdleTimeMillis}"/>
	</bean>

	<!-- 配置Mybatis的SqlSessionFactoryBean信息 -->
	<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<property name="mapperLocations" value="classpath*:/mapper/*.Mapper.xml"/>
	</bean>
	
	<!-- 配置Mybatis对于接口的扫描和自动装配机制  -->
	<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
		<property name="basePackage" value="cn.ekgc.ums.dao"/>
	</bean>

	<!-- 配置所使用的事务处理机制 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>

	<!-- 开启事务的注解扫描机制,并且将代理模式强制转换为CGLIB  -->
	<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
</beans>

Spring+Mybatis
• 配置数据源
对于任何持久化解决方案,连接数据库都是首要的问题。目前流行的数据源实现有dbcp、c3p0、Proxool、Druid等它们都实现了数据库连接池功能
• 配置SqlSessionFactoryBean
在MyBatis中,我们使用SqlSessionFactoryBuilder来创建SqlSessionFactory工厂。而在mybatis-spring集成环境中,可以使用SqlSessionFactoryBean来完成这个工作,它的内部封装了使用SqlSessionFactoryBuilder创建SqlSessionFactory的过程。同样,SqlSessionFactory需要依赖三部分东西:数据源、MyBatis的配置、SQL映射文件。我们先引用之前定义的数据源组件,再指向MyBatis的配置文件,最后为这个类中的mapperLocations属性注入值,即要引入的SQL映射文件。我们使用mapperLocations属性扫描式地加载SQL映射文件,指定一个匹配表达式即可。
• 配置SqlSessionTemplate
获得SqlSessionFactory的实例以后就可以获得SqlSession了,mybatis-spring整合包中提供了SqlSessionTemplate类。使用SqlSessionTemplate类可以负责管理MyBatis的SqlSession,调用SQL映射语句,实现对数据库的访问。
• 通过MapperFactoryBean创建代理对象
完成对数据库操作(需要针对每个mapper进行配置,麻烦),可以通过MapperScannerConfigurer进行mapper扫描:

<bean id="mapperScanner"class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="org.mybatis.spring.sample.mapper"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

basePackage属性是让你为映射器接口文件设置基本的包路径。你可以使用分号或逗号作为分隔符设置多于一个的包路径
这段配置会扫描org.mybatis.spring.sample.mapper下的所有接口,根据指定的包批量扫描Mapper接口并生成实例然后创建各自接口的动态代理类。

新建properties配置文件jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ums_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
jdbc.username=root
jdbc.password=java
druid.minIdle=3
druid.maxActive=10
druid.initialSize=5
druid.minEvictableIdleTimeMillis=30000
druid.maxEvictableIdleTimeMillis=60000

UserDao.java

public interface UserDao {
	public List<User> findAllUserList() throws Exception;
	public void saveUser(User user) throws Exception;
	public User findUserById(Long userId) throws Exception;
	public void updateUser(User user) throws Exception;
	public void deleteUserById(Long userId) throws Exception;
}

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="cn.ekgc.ums.dao.UserDao">
	<select id="findAllUserList" resultMap="userMap">
		select
			user_id user_id,
			username username,
			cellphone cellphone,
			id_card id_card
		from
			sys_user
	</select>
	
	<insert id="saveUser" parameterType="cn.ekgc.ums.entity.User">
		insert into sys_user(
			username, cellphone, id_card, create_time
		) values(
			#{username}, #{cellphone}, #{idCard}, #{createTime}
		)
	</insert>
	
	<select id="findUserById" parameterType="java.lang.Long" resultMap="userMap">
		select
			user_id user_id,
			username username,
			cellphone cellphone,
			id_card id_card
		from
			sys_user
		where
			user_id=#{userId}
	</select>
	
	<update id="updateUser" parameterType="cn.ekgc.ums.entity.User">
		update
			sys_user
		set
			username=#{username}, cellphone=#{cellphone},
			id_card=#{idCard}, update_time=#{updateTime}
		where
			user_id=#{userId}
	</update>
	
	<delete id="deleteUserById" parameterType="java.lang.Long">
		delete from sys_user where user_id=#{userId}
	</delete>
	
	<resultMap type="cn.ekgc.ums.entity.User" id="userMap">
		<id property="userId" javaType="java.lang.Long" column="user_id"/>
		<result property="username" javaType="java.lang.String" column="username"/>
		<result property="cellphone" javaType="java.lang.String" column="cellphone"/>
		<result property="idCard" javaType="java.lang.String" column="id_card"/>
	</resultMap>
</mapper>

Java中Dao层、Service层和Controllor层的区别:

Dao层:又叫数据访问层。针对数据库进行一些增删改查的操作。
Service层:又叫业务层。内置服务,接收来自Controller层的消息和将Dao层反馈信息传递至Controller层。
Controller层:负责请求转发,接受页面过来的参数,传给Service层处理,接收反馈信息,再传给页面。

运行流程:

一般来说,Controller层是负责接收外部请求的,它的职责就是解析请求参数,根据参数判断要做哪些事件。但是它里面没有逻辑性。而Service层是负责处理业务逻辑的,主要是解决做什么,怎么做的问题。而Dao层是只负责和数据库打交道(UserMapper.xml),把数据库的具体实现隔离开来。