在第13篇博客中,我们实现了SSM整合的第一大步,使用mybatis实现MVC3层架构中的M层
本篇博客我们要做的就是为项目引入spring框架,它的作用如下
-
IOC对应到以前的MVC架构中,它的作用就是管理service调用dao层的对象实例,和servlet层调用service层的对象实例,即管理dao层和service层的bean;【所以我们要将service层要用的dao层的实例注入spring容器中;对于controller层要调用的service层的实例的装配,我们就留到开发controller的时候再装配】
-
正是因为spring容器要管理service层的bean,所以AOP横向功能增强也应该在spring容器中配置,事务也应该在spring容器中配置;【所以我们要在spring容器中配置横切的事务,还可以配置其他的增强功能,即在service层方法执行前后增强功能】
-
除此之外,由于要整和spring和mybatis,所以spring容器中还要配置mybatis的数据源节点和sqlSessionFactory节点;【所以我们要在spring容器中配置mybatis这两个核心节点】
-
以及管理封装mybatis操作的mapper的实现类(这一步可以使用dao接口包扫描,让spring自动为我们创建实现类并让我们在配置文件中实现注入)【这一点其实和第一点有点重复,这一点就当作第一点的补充说明,说明我们注入的dao层的实例怎么来的】
目录
0.回顾
1.为什么要使用数据库连接池
-
对于一个简单的数据库应用,由于对于数据库的访问不是很频繁,这时可以简单地在需要访问数据库时,就新创建一个连接,用完后就关闭它,这样做也不会带来什么明显的性能上的开销
-
但是对于一个复杂的数据库应用,情况就完全不同了,频繁的建立、关闭连接,会极大的减低系统的性能,因为对于连接的使用成了系统性能的瓶颈
-
连接复用,通过建立一个数据库连接池以及一套连接使用管理策略,使得一个数据库连接可以得到高效、安全的复用,避免了数据库连接频繁建立、关闭的开销
-
对于共享资源,有一个很著名的设计模式:资源池。该模式正是为了解决资源频繁分配、释放所造成的问题的。把该模式应用到数据库连接管理领域,就是建立一个数据库连接池,提供一套高效的连接分配、使用策略,最终目标是实现连接的高效、安全的复用
-
数据库连接池的基本原理是在内部对象池中维护一定数量的数据库连接,并对外暴露数据库连接获取和返回方法。如:
-
外部使用者可通过getConnection 方法获取连接,使用完毕后再通过releaseConnection方法将连接返回,注意此时连接并没有关闭,而是由连接池管理器回收,并为下一次使用做好准备
2.怎么使用数据库连接池
上面的概念都说明了,资源池是一种设计模式,所以我们可以自己实现数据库连接池,也可以使用别人写好的数据库连接池;不管是哪一种,编写连接池必须需实现java.sql.DataSource接口,DataSource接口中定义了两个重载的getConnection方法
- Connection getConnection()
- Connection getConnection(String username, String password)
3.开源数据库连接池
现在很多WEB服务器(Weblogic, WebSphere, Tomcat)都提供了DataSoruce的实现,即连接池的实现。通常我们把DataSource的实现,按其英文含义称之为数据源,数据源中都包含了数据库连接池的实现
也有一些开源组织提供了数据源的独立实现:
- DBCP 数据库连接池
- C3P0 数据库连接池
在使用了数据库连接池之后,在项目的实际开发中就不需要编写连接数据库的代码了,直接从数据源获得数据库的连接
1.spring整合mybatis(配置数据源和sqlSessionFactory节点)
创建一个spring文件的子文件spring-dao.xml,专门用于整合mybatis,主要就是配置mybatis中的数据源,以及mybatis要使用的sqlSessionFactory对象和sqlsession对象
<?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">
<!--1、关联数据库配置文件
关联配置文件的作用就是用于读取里面的4大参数,用于下面配置数据库连接池-->
<context:property-placeholder location="classpath:db.properties"/><!--固定配置-->
<!--2、连接池/数据源配置
dbcp:半自动化操作,不能自动连接,需要手动连接
c3p0:自动化操作,能够自动加载配置文件,并自动设置到对象中
druid
hikari
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--3、SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><!--使用内置的类注入bean-->
<property name="dataSource" ref="dataSource"/>
<!--绑定数据源,数据源就是用来管理连接数据库的连接对象的-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!--绑定mybatis配置文件,实现两个文件配置内容的联动/融合-->
</bean>
<!--4、配置dao接口扫描包,可以动态的实现dao接口,并将实现类注入到spring容器中
它就相当于原来为了封装mybatis的操作我们自己去定义了一个类实现mapper接口-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--注入sqlSessionFactory,因为自动生成实现类使用的是我们手动实现的方法2,继承SqlSessionDaoSupport-->
<property name="basePackage" value="com.thhh.mapper"/>
<!--设置要扫描的mapper的包-->
</bean>
</beans>
从上面的例子中我们可以发现,在spring容器中读取配置文件之后,我们可以直接在spring容器中通过EL表达式来取值,入上面的${jdbc.driver},使用配置文件的好处就在于我们不用修改XML文件,不修改配置文件我们在做出修改之后就不用重启服务器,只需要重新更新一下发布的项目的资源文件即可
我们还可以对比一下,我们原来使用spring内置的DriverManagerDataSource的时候是怎么配置数据源的,上面其实就是换了一个数据源(ComboPooledDataSource),以及数据源的参数配置方式从直接写死到读取配置文件,其他的都没有什么区别;而这个操作原本是在mybatis核心配置文件中做的,但是我们将spring和mybatis整合的时候就将这个配置直接迁移到spring容器中来做了
除了使用的数据源更换了之外,封装mybatis的方法也变了,原来我们需要自己手动的实现mypper接口,然后在mapper的每个方法中封装mybatis调用这个方法的操作步骤,最后将数据返回;现在我们可以实现spring容器提供的包扫描方式来自动为我们生成实现类,并且这个实现类中封装mybatis操作步骤的原理就是原来手动实现mapper的时候使用的方法2 —— 继承SqlSessionDaoSupport ,下图中的文字有误,应该是继承了SqlSessionDaoSupport 类,调用SqlSessionDaoSupport .getSession()获取session对象
详细理解可以参考前面的博客
Spring5(21) —— 整合MyBatis方式1.
Spring5(22) —— 整合MyBatis方式2.
2.spring装配service层(bean管理、事务和AOP配置)
创建一个spring文件的子文件spring-service.xml,专门用于整合service层的操作,主要是事务操作和其他一些AOP增强
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns: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">
<!--1、扫描service下的包下有自动装配的注解-->
<context:component-scan base-package="com.thhh.service"/>
<!--2、将业务实现类注入到spring容器中,
可以通过配置文件和注解(上面已经开启了注解扫描)两种方式实现-->
<bean id="BookServiceImpl" class="com.thhh.service.BookServiceImpl">
<property name="bookMapper" ref="bookMapper"/><!---->
</bean>
<!--3、声明式事务,很明显直接装配了一个数据源事务管理器-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源,因为我们可以同时使用好几个数据源,
所以这里必须指定事务管理器管理的是哪一个数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--4、AOP横切事务,可以配合事务使用,用于指定事务开启时机;也可以做增强业务的横切-->
</beans>
上图中对于事务的操作,我们可以参考学习spring的声明式事务的博客
可见要开启事务,上面的代码就是官方文档给出的标准