SSM:spring、spring MVC 、mybatis
spring5
1 概述
Spring是分层的 Java SE/EE应用 full-stack(全栈的)轻量级开源框架,以 IoC(Inverse Of Control:
反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 Spring
MVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多
著名的第三方框架和类库,逐渐成为使用最多的Java EE 企业应用开源框架。
IoC:
即控制反转-Inversion Of Control,作用为解耦合
AOP:
即面向切面编程,通过预编译方式与运行期动态代理实现程序功能的同一维护的一种技术
相关术语:
Joinpoint(连接点):所谓连接点就是指那些被拦截到的点。在spring中,这些点指的是方法。因为spring只支持方法类型的连接点。
Pointcut(切入点):我们要对哪些Joinpoint进行拦截
Advice(通知/增强):拦截到Joinpoint之后所要做的事情
通知的类型:前置通知、后置通知、异常通知、最终通知、环绕通知。
Introduction(引介):特殊的通知,在不修改类代码的前提下,在运行期为类动态地添加一些方法或Field。
Target(目标对象):代理的目标对象
Weaving(织入):指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。
Proxy(代理):被AOP织入后增强的结果代理类
Aspect(切面): 切入点和通知的结合
2 spring框架体系
可以看到整体被划分为:核心容器(Core Container)、AOP(Aspect Oriented Programming)、数据访问及集成(Data Access/Integratioin)、Web、报文发送(Messaging)、Test等模块。
核心容器(Core Container):
- spring-core:依赖注入DI与控制反转IoC的最基本实现
- spring-beans:Bean工厂与bean的装配
- spring-context:spring的context上下文,即IoC容器
- spring-expression:spring表达式语言
数据访问及集成(Data Access/Integratioin)
- spring-jdbc:jdbc的支持
- spring-Transactions:事务控制
- spring-ORM:对象关系映射,集成ORM框架
- spring-OXM:对象xml映射
- spring-jms:java消息服务
Web
- spring-web:基础web功能,如文件上传
- spring-webmvc:mvc实现
- spring-websocket:主要是与Web前端的全双工通讯协议。
- spring-webflux:是一个新的非阻塞式Reactive Web框架,可以用来建立异步、非阻塞、事件驱动的服务,并且扩展性非常好。
Test
封装测试方法
spring-aop:
面向切面编程(Aspect Oriented Programming)
spring-aspects:
集成AspectJ (面向方面编程(AOP)扩展)
spring-instrument:
提供一些类级的工具支持和ClassLoader级的实现,用于服务器
spring-messaging:
为Spring框架集成一些基础的报文发送应用。
3 spring的使用 IOC+AOP(带测试test)
1 xml配置文件方式:
准备条件:
jar包(此处为maven坐标):
(maven中会自动导入相关依赖包,一家人整整齐齐就都来了)
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.4.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
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">
</beans>
配置方式
配置IOC:
1 实例化bean
方式一:默认无参构造
<bean id="实例bean标识" class="Bean的包类名(全限定)"/>
第二种方式:spring 管理静态工厂-使用静态工厂的方法创建对象
<bean id="指定bean的id" class="指定静态工厂的全限定类名" factory-method="指定生产对象的静态方法"> </bean>
第三种方式:spring 管理实例工厂-使用实例工厂的方法创建对象
<bean id="实例工厂bean的id" class="com.itheima.factory.InstanceFactory"></bean>
<bean id="指定bean的id" factory-bean="实例工厂bean的id" factory-method="createAccountService"></bean>
2 参数的依赖注入(DI Dependency Injection)
注入:给成员变量赋值
方式一: 构造函数注入
<bean id="实例bean的id" class="实例bean的全限定类名">
<constructor-arg name="参数在构造函数中的名称" value="赋值(基本数据或String)">
</constructor-arg>
<constructor-arg name="参数在构造函数中的名称" ref="其他bean类型"></constructor-arg>
</bean>
<bean id="其他bean类型id" class="该Bean的全限定类名"></bean>
constructor-arg 属性:
index:指定参数在构造函数参数列表的索引位置
type:指定参数在构造函数中的数据类型
name:指定参数在构造函数中的名称
value:它能赋的值是基本数据类型和 String 类型
ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean
方式二:set 方法注入
<bean id="实例bean的id" class="实例bean的全限定类名">
<property name="set 方法后面的部分" value="赋值(基本数据或String)"></property>
<property name="set 方法后面的部分" ref="其他bean类型"></property>
</bean>
<bean id="其他bean类型id" class="该Bean的全限定类名></bean>
property属性:
name:找的是类中 set 方法后面的部分
ref:给属性赋值是其他 bean 类型的
value:给属性赋值是基本数据类型和 string 类型的
方式三:使用 p 名称空间注入数据(本质还是调用 set 方法)
<bean id="实例bean的id" class="实例bean的全限定类名"
p:字段名="值" p:字段名-ref="其他bean类型"/>
补充:
注入单列集合类:
List 结构的:array, list, set
<bean id="实例bean的id" class="实例bean的全限定类名">
<!-- 在注入集合数据时,只要结构相同,标签可以互换 -->
<!-- 给数组注入数据 -->
<property name="myStrs">
<set>
<value>值</value>
</set>
</property>
<!-- 注入 list 集合数据 -->
<property name="myList">
<array>
<value>AAA</value>
</array>
</property>
<!-- 注入 set 集合数据 -->
<property name="mySet">
<list>
<value>CCC</value>
</list>
</property>
注入双列集合类:Map 结构的 map, entry, props, prop
<property name="myMap">
<props>
<prop key="Key1">值</prop>
</props>
</property>
<!-- 注入 properties 数据 -->
<property name="myProps">
<map>
<entry key="Key1" value="值"></entry>
<entry key="Key2">
<value>值</value>
</entry>
</map>
</property>
配置AOP步骤:
第一步:把通知类的创建也交给 spring 来管理
第二步:使用 aop:config 标签开始 aop 的配置
第三步:使用 aop:aspect 标签开始配置切面,写在 aop:config 标签内部
id 属性:给切面提供一个唯一标识
ref 属性:用于引用通知 bean 的 id。
第四步:使用对应的标签在 aop:aspect 标签内部配置通知的类型
使用 aop:befored 标签配置前置通知,写在 aop:aspect 标签内部
method 属性:用于指定通知类中哪个方法是前置通知
pointcut 属性:用于指定切入点表达式。
切入点表达式写法:
关键字:execution(表达式)
表达式内容:
全匹配标准写法:
访问修饰符 返回值 包名.包名.包名…类名.方法名(参数列表)
标准通知配置
<!-- 配置通知类 -->
<bean id="通知类id" class="通知类全限定名"></bean>
<!-- 配置 aop -->
<aop:config>
<aop:pointcut expression="execution( 全匹配 )" id="匹配ID" >
<!-- 配置切面 -->
<aop:aspect id="切面id" ref="通知类id">
<!-- 配置前置通知 -->
<aop:before method="通知类方法名" pointcut="execution( 全匹配 )"/>
<!-- 配置后置通知 -->
<aop:after-returning method="通知类方法名" pointcut="execution( 全匹配 )"/>
<!-- 配置异常通知 -->
<aop:after-throwing method="通知类方法名" pointcut="execution( 全匹配 )"/>
<!-- 配置最终通知 -->
<aop:after method="通知类方法名" pointcut="execution( 全匹配 )"/>
</aop:aspect>
</aop:config>
环绕通知配置:
<aop:config>
<aop:pointcut expression="execution( 全匹配 )" id="匹配ID" />
<aop:aspect id="环绕通知类ID" ref="全限定名">
<!-- 配置环绕通知 -->
<aop:around method="transactionAround" pointcut-ref="pt1"/>
</aop:aspect>
</aop:config>
3.1.2 配置文件开发式的优缺点:
优点:结构清晰,修改不需要改动源码,只需要改动配置文件即可
缺点:代码量大
3.2 xml+注解配置方式
3.2.1 准备条件:
jar包(此处为maven坐标):
同上!
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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置 spring 创建容器时要扫描的包 -->
<context:component-scan base-package="包名a"></context:component-scan>
<!-- 开启 spring 对注解 AOP 的支持 -->
<aop:aspectj-autoproxy/>
</beans>
3.2.2 配置方式:
自定义引用数据类型采用注解方式,导入的jar包和工具类等采用配置文件方式。
配置文件需要配置 创建容器要扫描的包 标签:<context:component-scan base-package=“com.itheima”/>
其他配置同上
常用注解:
1 用来创建对象的
@Component(value=" bean的ID")
注解配置管理的资源(即要讲其交给spring管理)
参数:value:指定 bean 的 id。如果不指定 value 属性,默认 bean 的 id 是当前类的类名。首字母小写
@Controller(表示层)、@Service(业务层) 、@Repository(持久层)
同Component,
参数:value:指定 bean 的 id。如果不指定 value 属性,默认 bean 的 id 是当前类的类名。首字母小写
ps:如果注解中有且只有一个属性要赋值时,且名称是 value ,value 在赋值的时候是可以不写的
2 用来注入数据
@Autowired
自动按照类型注入。它只能注入其他 bean 类型。当有多个类型匹配时,使用要注入的对象变量名称作为 bean 的 id,在 spring 容器查找,找到了也可以注入成功。找不到就报错。
@Qualifier
在自动按照类型注入的基础之上,再按照 Bean 的 id 注入。它在给字段注入时不能独立使用,必须和
@Autowire 一起使用;但是给方法参数注入时,可以独立使用。
@Resource(name=" id");
直接按照 Bean 的 id 注入。它也只能注入其他 bean 类型。
name:指定 bean 的 id。
@Value(value=" id")
注入基本数据类型和 String 类型数据的
value:用于指定值
3 用于改变作用范围
@Scope
作用:指定 bean 的作用范围。
value:指定范围的值。
取值:singleton(单例)、 prototype(多例)、 request、 session 、globalsession
4 和生命周期相关
@PostConstruct
用于指定初始化方法 置于方法上
@PreDestroy
用于指定销毁方法,置于方法上
优点 :集合了注解的简洁与配置文件 的清晰,开发中推荐使用
5 AOP相关
@Aspect
把当前类声明为切面类。作用于类上
@Before
把当前方法看成是前置通知。 作用于方法上
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
@AfterReturning
把当前方法看成是后置通知。
@AfterThrowing
把当前方法看成是异常通知。
@After
把当前方法看成是最终通知。
@Around
把当前方法看成是环绕通知。
@Pointcut
指定切入点表达式
补充1:解决环绕通知调用问题。
- spring 框架为我们提供了一个接口,该接口可以作为环绕通知的方法参数来使用
- ProceedingJoinPoint。当环绕通知执行时,spring 框架会为我们注入该接口的实现类。
- 它有一个方法 proceed(),就相当于 invoke,明确的业务层方法调用
补充2:解决切入点表达式问题
@Around("pt1()")
3.3 纯注解方式
准备:
jar包(此处为maven坐标):参考同上
2 配置类
注解:
@Configuration
作用:
用于指定当前类是一个 spring 配置类,当创建容器时会从该类上加载注解。获取容器时需要使用AnnotationApplicationContext(有@Configuration 注解的类.class)。
可选参数:
value:用于指定配置类的字节码
@ComponentScan
作用:
用于指定 spring 在初始化容器时要扫描的包。
属性:
basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样。
@EnableAspectJAutoProxy
作用:
开启AOP代理
@Bean
作用:
该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。
属性:
name:给当前@Bean 注解方法创建的对象指定一个名称(即 bean 的 id)。
@PropertySource
作用:
用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。
属性:
value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath:
@Import
作用:
用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解。当然,写上也没问题。
属性:
value[]:用于指定其他配置类的字节码。
通过注解获取容器:
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
3.4 Spring 整合 Junit
配置步骤:
第一步:导入 spring 整合 Junit 的坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
第二步:使用@RunWith 注解替换原有运行器
@RunWith(SpringJUnit4ClassRunner.class)
第三步:使用@ContextConfiguration 指定 spring 配置文件的位置
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:bean.xml"})
@ContextConfiguration 注解:
locations 属性:用于指定配置文件的位置。如果是类路径下,需要用 classpath:表明
classes 属性:用于指定注解的类。当不使用 xml 配置时,需要用此属性指定注解类的位置。
第四步:使用@Autowired 给测试类中的变量注入数据
Spring+JDBCtemplate
1 坐标导入
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--此处导入的为c3p0连接池-->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
配置文件:此处只写不同
<!--spring框架也提供了一个内置数据源,我们也可以使用spring的内置数据源,它就在
spring-jdbc-5.0.2.REEASE.jar 包中:-->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value=" "></property>
<property name="username" value=" "></property>
<property name="password" value=" "></property>
</bean>
<!-- 引入外部属性文件: -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:全限定名"/>
</bean>
<!-- 另一种方式: -->
<context:property-placeholder location="classpath:全限定名"/>
JdbcTemplate的获取
JdbcDaoSupport 是spring 框架为我们提供的一个类,该类中定义了一个 JdbcTemplate 对象,我们可以
直接获取使用,但是要想创建该对象,需要为其提供一个数据源
Spring 中的事务控制
Spring 中事务控制的 API 介绍
PlatformTransactionManager
此接口是 spring 的事务管理器,它里面提供了我们常用的操作事务的方法
真正管理事务的对象
org.springframework.jdbc.datasource.DataSourceTransactionManager 用 使用 SpringJDBC 或 或 iBatis 进行持久化数据时使用
org.springframework.orm.hibernate5.HibernateTransactionManager 使用Hibernate 版本进行持久化数据时使用
TransactionDefinition
它是事务的定义信息对象
TransactionStatus
此接口提供的是事务具体的运行状态
基于 XML 的声明式事务控制(配置方式 )
1 坐标(必须)
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
</dependencies>
2 约束
<?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: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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
3 事件配置
<!-- 配置一个事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入 DataSource -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 事务的配置 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--在 在 tx:advice 标签内部 配置事务的属性 -->
<tx:attributes>
<!-- 指定方法名称:是业务核心方法
read-only: 是否是只读事务。默认 false,不只读。
isolation: 指定事务的隔离级别。默认值是使用数据库的默认隔离级别。
propagation:指定事务的传播行为。
timeout: 指定超时时间。默认值为:-1。永不超时。
rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。
没有默认值,任何异常都回滚。
no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回滚。没有默 认值,任何异常都回滚。 -->
<tx:method name="*" read-only="false" propagation="REQUIRED"/>
<tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<!-- 配置 aop -->
<aop:config>
<!-- 配置切入点表达式 -->
<aop:pointcut expression="execution(表达式)" id="pt1"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"/>
</aop:config>
基于注解的配置
1 坐标:同上
2 约束(无)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.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">
<!-- 配置 spring 创建容器时要扫描的包 -->
<context:component-scan base-package="要扫描的包"></context:component-scan>
<!-- 配置 JdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置 spring 提供的内置数据源 -->
<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/数据库名"></property>
<property name="username" value="root"></property>
<property name="password" value="1234"></property>
</bean>
</beans>
相关注解:
@Transactional :
作用:在业务层定义事件
常用参数: read-only: 是否是只读事务。默认 false,不只读。
isolation: 指定事务的隔离级别。默认值是使用数据库的默认隔离级别。
propagation:指定事务的传播行为。
timeout: 指定超时时间。默认值为:-1。永不超时。
rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。
没有默认值,任何异常都回滚。
no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回
滚。没有默认值,任何异常都回滚
补充:事件的传播行为
REQUIRED(默认值):如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择
SUPPORTS: 支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
MANDATORY: 使用当前的事务,如果当前没有事务,就抛出异常
REQUERS_NEW: 新建事务,如果当前在事务中,把当前事务挂起。
NOT_SUPPORTED: 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
NEVER: 以非事务方式运行,如果当前存在事务,抛出异常
NESTED: 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED 类似的操作。
@EnableTransactionManagement
作用:用在管理配置类处,开启事件管理。
配置类:
@Configuration
@ComponentScan("cn.test")
@EnableAspectJAutoProxy
@EnableTransactionManagement
@Import({BeanFactory.class})
@Transactional
public class Config {
}
Bean类:
@Configuration
@PropertySource("classpath:mysql.properties") //导入配置文件类
@EnableTransactionManagement
public class BeanFactory {
@Value("${jdbc.driverClassName}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Autowired
private DataSource dataSource; //注入DataSource
@Bean //创建生成 Bean的方法,然后添加到容器中
public DataSource getDataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
@Bean
public JdbcTemplate getJdbcTemplate(){
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
return jdbcTemplate;
}
@Bean //生成事件管理器Bean
public PlatformTransactionManager getPlatformTransactionManager(){
PlatformTransactionManager platformTransactionManager = new DataSourceTransactionManager(dataSource);
return platformTransactionManager;
}
}