Spring
1、春天
1.1、简介
- Spring:春天----》给软件行业带来了春天!
- SSH:Struct2 + Spring + Hibernate!
- SSM:SpringMVC + Spring + Mybatis
官网:https://spring.io/projects/spring-framework#overview
官方下载地址:https://repo.spring.io/relase/org/springframework/spring
GitHub:https://github.com/spring-projects/spring-framework
<!--操作Spring的基本依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!--操作SpringMVC的依赖--> 内部包含了Spring的基本依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.20.RELEASE</version>
</dependency>
<!--操作数据库的依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.20</version>
</dependency>
1.2、优点
- Spring是一个开源的免费的框架(容器)!
- Spring是一个轻量级的、非入侵式的框架!
- 控制反转(IOC),面向对象编程(AOP)
- 支持事务管理,对框架整合的支持
总结一句话:Spring就是一个轻量级的框架,支持控制反转IOC和面向对象AOP
1.3、组成
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fa4ZdfRM-1687687425935)(D:\Typora笔记\图片思维导图\Spring七大模块思维导图.png)]
1.4、拓展
在Spring的官网中有这个介绍:现代化的Java开发!说白就是基于Spring的开发!
三大关键词:Build Anything(构造一切) Coordinate Anyting(协调一切) ConnectEverything(连接一切)
-
Spring Boot
- 一个快速开发的脚手架
- 基于SpringBoot可以快速的开发单个微服务
-
Spring Cloud
- SpringCloud是基于SpringBoot实现的
因为现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring及SpringMVC!承上启下的作用!
弊端:发展了太久之后,违背了原来的理念!配置十分繁琐,简称:“配置地狱!”
2、IOC理论指导
1、UserDao接口
2、UserDaoImpl 实现类
3、UserService 业务接口
4、UserServiceImpl 业务实现类
在我们之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去更改原代码!如果程序代码量十分大,修改一次额成本代价十分昂贵!
我们使用一个Set接口实现,已经有了革命性的变化!
private UserDao userdao;
//利用set实现动态值的注入!
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
- 之前,程序是主动创建对象!控制权在程序员手上!
- 使用Set注入之后,程序不再具有主动性,而是变成了被动的接收对象!
这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注的在业务的实现上!这是IOC的原型!控制反转
IOC本质
控制反转IOC(Inversion Of Control)是一种设计思想,DI(依赖注入)是一种IOC实现方法,也有人认为DI只是IOC的另一种说法。没有IOC的程序中,我们使用面向对象编程,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IOC容器,其实现方法是依赖注入(Dependency Injection,DI)。
3、Hello Spring
<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-3.0.xsd">
<!--使用Spring来创建对象,在Spring这些称为Bean-->
<bean id="hello" class="com.pojo.Hello">
<property name="str" value="Spring" />
</bean>
</beans>
思考问题:
1)Hello对象是由谁创建的?
hello对象是由Spring创建的
2)Hello对象的属性是怎么设置的?
hello对象的属性是Spring容器设置的,这个过程叫控制反转
反转:程序本身不创建对象,而变成被动的接收对象
依赖注入:通过set方法进行注入
4、IOC创建对象的方式
两个重要的属性:1、id 唯一标识 2、class 需要创建对象的类
不能出现两个相同的Bean
类ApplicationContext Spring的接口容器
实现类 ClassPathXmlAppliactionContext 从类路径加载Spring配置文件并且new 出当中的所有对象 装入容器当中
Spring配置文件可以存放多个
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplication(beanXml文件...);
类 对象 = context.getBean("bean文件id",返回的 类.class);
}
1、使用无参构造创建对象,默认!
2、假设我们要使用有参构造创造对象。
(1)下标赋值
<bean id="user" class = "com.包名.JavaBean类名">
<constructor-arg index="下标" value="赋值" />
</bean>
-- 下标从0开始
(2)类型赋值(引用类型必须要Java.lang.包装类名)
<bean id="user" class="com.包名.javaBean类名">
<constructor-arg type="int" value="6" />
</bean>
-- 不推荐使用
(3)属性名赋值
<bean id="user" class="com.包名.javaBean类名">
<constructor-arg name="属性名" value="值"/>
</bean>
总结:在配置文件加载的时候,Spring容器当中的对象就已经被初始化了,并且有且仅有一个对象。
5、Spring配置
5、1 别名
<!--别名,如果我们添加了别名,我们也可以使用别名获取到这个对象-->
<alias name="user" alias="userNew"/>
被name所代替,name可以取多个别名,只需要用一些方式隔开比如:, ; 空格
5、2 Bean的配置
-
applicationContext.xml
<import resource="bean.xml"/>
使用的时候,直接使用总的配置就可以了
5、3 依赖注入
ref:引用
<bean id="" class="类名">
<property name="值或者方法去掉set" ref="需要引用的id"/>
</bean>
数组注入:array
<bean id="" class="类名">
<property name="属性">
<array>
<value></value>
<value></value>
<value></value>
</array>
</property>
</bean>
list注入:list
<bean id="" class="类名">
<property name="属性">
<list>
<value></value>
<value></value>
<value></value>
</list>
</property>
</bean>
entry:键值对
<bean id="" class="类名">
<property name="属性">
<map>
<entry key="键" value="值"/>
</map>
</property>
</bean>
properties:key对应值
<property name="prop">
<props>
<prop key="url">mysql://localhost3306:t166?UseSSL=false</prop>
<prop key="driver">com.jdbc.mysql.Driver</prop>
<prop key="username">root</prop>
<prop key="password">root</prop>
</props>
</property>
5、4 如何添加一下特殊符号?
1、使用网页标签转义符 例如: <;
2、使用<![CDATA[值]]> 包括住
5、5 util命名空间
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util/spring-util.xsd">
使用命名空间
<util:数据类型 id="">
<></> 相关属性值
</util:数据类型>
<bean id="bean名" class="返回的类型">
<property name="属性" ref="调用命名空间的id"/>
</bean>
</beans>
5、6 XML自动装配
Spring可以完成自动化的注入,自动化注入即自动装配。可以根据名字也可以根据类型
1)根据名字
<bean id="bean名" class="包名中的Class" autowire="byName"/>
<bean id="set方法去掉set小写字母开头" class="包名中的Class"/>
注意:自动装配也是根据set方法去写的,被注入的对象id尽量不要随便写
2)根据类型
<bean id="bean名" class="包名中的Class" autowire="byType"/>
<bean class="包名中的Class"/>
注意:根据类型装配也是一样需要根据set方法去写,且不能有多个相同对象的bean。不然会报错 报错信息是实际上超出一个
5、7 Spring外部引入属性配置文件
<!--引入外部properties文件-->
<context:property-placeholder location="driver.properties"/>
<bean id="datasource" class="com.pojo.driver.Jdbc2">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
**注意点:**命名空间记得赋值粘贴 , 如过在Properties文件当中用driver username password url 会被识别成系统变量所以要取个别名称。
6、 Bean的作用域
属性:scope
单例模式:scope(作用域) = Singleton(单例模式) 只会生成一个对象
多例模式:scope(作用域) = protoType(多例模式) get一次生成一个新对象
Spring默认scope是单例模式Singleton;
1、 BeanFactory 和 FactoryBean?
BeanFactory是Spring的顶级容器对象,负责创建对象的工厂
FactoryBean是一个Bean,是辅助Spring实例化其它Bean对象的一个Bean
在Spring当中Bean分为两类:
第一类:普通Bean
第二类:工厂Bean
2、 Bean的实例化方式
Spring为Bean提供了多种实例化方式,通常包括四种方式。(为了让我们创建对象更加的灵活)
2、1 普通创建
<bean id="对象标识名字" class="包名下的Bean类"></bean>
2、2 简单工厂模式实例化
类编写
public class Star{ //明星类
public Star(){
System.out.println("无参构造器");
} //无参构造器
}
public class StarFactory{ //明星工厂类
public static Star get(){ //返回创建的明星对象
return new Star();
}
}
xml编写
<bean id="createStar" class="包下的明星工厂类" factory-method="get"></bean> //factory-method指的是工厂方法名
2、3 工厂Bean创建
类编写
public class Vip{ //vip的类
public Vip(){
System.out.println("无参构造方法");
}
}
public class VipFactory{ //Vip工厂
public Vip get(){
return new Vip(); //返回Vip对象
}
}
xml编写
<bean id="createVipFac" class="包下的VipFactory类"/>
<bean id="getVip" factory-bean="需要被作为工厂使用的id" factory-method="factory-bean中的方法名"/>
2、4 通过FactoryBean接口实例化
类编写
public class Person{
public Person(){
System.out.println("无参构造方法");
}
}
public class PersonFactoryBean implments FactoryBean<Person>{
@Override
public Person getObject() throws Exception { //返回Person的对象
return new Person();
}
@Override
public Class<?> getObjectType() {
return null;
}
}
xml编写
<bean id="getPerson" class="包下的PersonBeanFactory类"/>
7、 Bean的生命周期
Bean的生命周期大致可以分为五步
第一步:实例化Bean
第二步:Bean属性值赋值
第三步:初始化Bean
第四步:使用Bean
第五步:销毁Bean
1、1 Bean的生命周期五步的操作
类编写
public class User{
private String name;
public User(){
System.out.println("第一步:构造方法执行");
}
public void setName(String name){
System.out.println("第二步:赋值操作");
this.name = name;
}
public void init(){ //自己配置在Spring框架当中调用
System.out.println("第三步:初始化对象");
}
public void destroyBean(){ //自己配置销毁Bean的方法
System.out.println("第五步:销毁Bean对象");
}
}
xml编写
<bean id="getUser" class="包下的User类" init-method="init" destroy-method="destroyBean">
<property name="name" value="小王"/>
</bean>
8、new出的对象纳入容器管理中
概述:自己new出来的对象是不会被我们的ApplicationContext给管理的,如果需要管理的话就需要加入一个DefaultListableBeanFactory类进来,它是用来帮我们生成bean豆子的
Student stu = new Student();
DefaultListableFactory factory = new DefaultListableFactory();
factory.registerSingleton('bean名字',stu);
当我们用context对象去获取这个对象的时候,就可以发现同一个地址,该对象被我们的bean工厂给接管了。
9、循环依赖是如何解决的?
引子:什么是循环依赖? 就比如人跟宠物 人的宠物是狗狗 狗狗的主人是xxx 两个都有个对象固定在之中。
但是实例化的时候互相依赖是不会报错的,为什么?
1、在spring容器加载的时候,实例化Bean,只要任意一个Bean实例化之后,马上进行 ‘曝光’ 【不等属性赋值就直接调用】
2、曝光之后,再进行属性的一个赋值(底层调用set方法)如果是构造方法注入的话那就直接报错
3、记住作用域(scope)是在单例Singleton的情况之下 或者是 有一个是Singleton
10、Spring IOC注解式开发
10、1 声明Bean注解
1、Component:注册bean(bean的id名)
Component(“bean的id名”) >>> 该注解只能放在类名上面
2、Service:Component的别名 用在业务逻辑层增加代码的可读性
3、Controller:用在控制层代码,为了增加代码的可读性
4、Repository:用在数据访问层,为了增加代码的可读性
以上都是Component,只是为了让大家更好的区分这个注解Bean是个做什么的Bean
元注解Bean使用:
1、开启context命名空间使用包扫描
<context:component-scan base-package=“com.pojo”/>
2、如何配置多个包进行扫描?
1)<context:component-scan base-package=“com.pojo.bean,com.pojo.bean2”/> 用逗号隔开每个要扫描的包
2)<context:component-scan base-package=“com.pojo”/> 直接将父包丢入,不过效率会降低
3、注解筛选生效实效
1)注解全部失效,靠引用生效
<context:component-scan base-package="com.包" use-default-filters="false"> //所有注解全部失效
<context:include-filter type="annotation" expression="全限定名"/> //代表引用xx注解生效
</context:component-scan>
2)注解全部生效,靠排除实效
<context:component-scan base-package="com.包"> //use-default-filters默认就是true
<context:exclude-filter type="annotation" expression="全限定名"/> //代表排除xx注解失效
</context:component-scan>
10、2 注入注解
1、@Value:当属性是简单类型的时候,就可以使用该注解 例如:String int double
===》使用@Value,不需要提供set方法
=============== 非简单类型的注入 ===============
2、@AutoWired:当属性如果是非简单类型,就可以使用该注解 例如:JavaBean类
===》使用AutoWired不需要传参数
缺点:如果是多个同一个接口实现的属性,那就无法进行自动装配
3、@Qualifier:当一个接口有多个实现的时候想指定一个属性注入的时候,就可以用该注解指定
@Qualifer(“bean名称”)
前提:必须要和**@AutoWired**一起使用,否则的话是无法找到属性的,连属性都找不到就更别说名字了
4、@Resource注解
@Resource注解也可以完成非简单类型注入。它是Java自带的注解,而@Autowired是Spring携带的
@Resource注解默认是根据名字装配,如果名字未找到就会根据类型装配
===》只能用在属性和方法上
@AutoWired 和 @Resource 的区别
@AutoWired:默认是根据类型装配,如果想要根据名字装配必须联合 @Qualifier一起使用
作用域可以使用在构造器 方法 属性上
@Resource:默认根据名字装配,找不到则根据类型装配,
作用域只能用在属性和方法上
10、3 spring配置文件相关注解
@ComponentScan({“需要扫描的包的位置”})
该注解是充当我们的context命名空间的 component-scan base-package使用的
@Configuration 该配置没有任何参数,是个签名,代表这个是充当spring配置文件使用的
@EnableAspectJAutoProxy(proxyTargetClass = true) 该配置说明的是启用Aspect的自动代理
11、GoF代理模式
在java程序当中的代理模式的作用:
1、当一个对象需要受到保护的时候,可以考虑使用代理对象去完成某个行为
2、需要给某个对象的功能进行功能增加的时候,可以考虑一个代理进行增强
====================================================================
代理模式的三大角色:
第一个角色:目标对象(真正的对象)
第二个角色:代理对象(对象的替身)
第三个角色:目标对象和代理对象的公共的接口
====================================================================
前提:代理对象要和目标对象具有相同的行为,就要实现同一个接口或同一些接口
1、静态代理
public interface OrderService { //代理对象 和 目标对象的共用接口
/**
* 生成订单
*/
void generate();
/**
* 修改订单信息
*/
void modify();
/**
* 查看订单详情
*/
void detail();
}
public class OrderServiceImpl implements OrderService { //具体对象
@Override
public void generate() {
System.out.println("生成订单");
}
@Override
public void modify() {
System.out.println("修改订单");
}
@Override
public void detail() {
System.out.println("订单详情");
}
}
public class OrderServiceProxy implements OrderService { //代理对象
private OrderService target;
public OrderServiceProxy(OrderService target) {
System.out.println("我是代理类");
this.target = target;
}
@Override
public void generate() {
target.generate();
}
@Override
public void modify() {
target.modify();
}
@Override
public void detail() {
target.detail();
}
}
总结:静态代理模式,需要代理的对象就越不好维护,并且消耗资源太大不建议使用。
2、动态代理
在程序的运行阶段,在内存当中生成动态代理类,目的是为了减少代理类的数量,解决代码复用的问题
- JDK内置动态代理技术:只能代理接口
Proxy.newProxyInstance(‘类加载器’,‘代理需要实现的接口’,‘’)
newProxyInstance的三大参数:
第一个参数 ClassLoader(类加载器):我们运行编译的Class文件,要执行就得先加载到内存当中。加载类就需要类加载器。所以这里需要指定类的加载器,并且我们的代理对象和目标对象要使用同一个加载器
第二个参数 interfaces(接口类):代理对象和目标对象共用的接口
第三个参数 InvocationHandler(处理器):在调用器当中编写的就是增强代码,因为具体要给哪个方法加强,JDK是检测不到的。
- GGLIB动态代理技术:开源项目,既可以代理接口又可以代理类,底层通过继承的方式实现的,性能要比JDK动态代理好
- Javassist动态代理技术:Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京大学的数学和计算机科学系的
Shigeru Chiba创建的。它已加入了开放源代码JBoss应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态"AOP"框架
12、面向切面编程AOP
1、对AOP的理解
概述:一般系统当中都会有一些系统服务,比如:日志、事务管理、安全等。这些被称之为交叉业务
这些交叉业务几乎是通用的,不管你是做银行账户转账,还是删除用户数据。日志、事务管理、安全这些都是要做的
如果在每一个业务过程当中,都放这些代码进行穿插的话,会出现两个问题:
- 交叉业务代码在多个业务流程中反复出现,显然这个交叉业务代码没有得到复用。并且修改这些交叉业务代码的话,需要修改多处
- 程序员无法专注核心代码的编写,在编写代码的同时还要处理这些交叉业务的代码
将与业务逻辑无关的代码独立抽取出来,形成一个单一的组件,然后以横向交叉的形式应用到业务流程当中的过程被称为AOP。
AOP的优点:
1、代码复用性强
2、可维护性高
3、开发人员可以更好的专注业务逻辑代码
2、 AOP的七大术语
- 连接点
连接点,描述的就是位置
- 切点
本质上就是方法
- 通知
通知就是增强代码
- 切面
切点 + 通知 = 切面
3、切点表达式
语法:execution([访问权限修饰符] 返回值类型 [全限定类名] 方法名(形式参数列表) [异常] )
访问权限修饰符:可选填写
返回值类型:必填,*表示任意类型
全限定类名:可选项,两个点 … 代表包下所有类 省略时 所有类
方法名:必填项, 表示所有方法 set表示所有的set方法
形式参数列表:必填项,()表示没有参数的方法 (…)参数类型和个数随意 (*)只有一个参数的方法 (※,String)第一个参数任意第二个指定
使用注解式开发的话必须要给切面类加上@Aspect
@Aspect:代表当前类是切面类
@Order:代表排序的顺序,数字越小优先级越高
@Pointcut:我们可以编写一个方法方法体内无任何实现就用于当作我们的通用切点
比如:
@Pointcut("execution(* com.包.类..*(..))")
public void test(){}
这就是通用切点;当我们需要调用切点的时候就可以不需要一遍又一遍的手敲
调用:
@AfterReturnning("test()")
public void call(){}
如果是外部类调用,只需要放入全限定类名的切面类方法即可
1、@Before:添加了该注释的代码,一旦该注释指定的类方法运行,则添加了该行注释的代码在指定类方法之前运行
2、@AfterReturning:在指定方法之后运行
3、@Around:范围最大的通知,在最前开始,最后结束
4、@AfterThrowing:指定的类方法如果遇到异常则做的操作
5、@After:指定类方法中最后运行的代码 等同try{}catch(){}finally{}中的 finally块
JoinPoint 连接点
JoinPoint对象的Signature.getName()可以获取到当前对象调用方法的名称
13、Spring事务的支持
概述:什么是事务,把多件事情组合起来一起操作,要么同时成功要么同时失败
Spring事务管理的两种方式
编程式事务
通过编写代码的方式来实现事务的管理
声明式事务
基于注解方式
基于XML配置方式
Spring事务管理API
PlatformTranscationManager
两个子类实现:
- DataSourceTranscationManager:支持mybatis、jdbcUtil等
- JtaTranscationManager:支持分布式事务管理器
<!-- 配置德鲁伊数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/t166"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="引用dataSource"/>
</bean>
<!--
导入命名空间
配置驱动事务管理器
-->
<tx:annotation-driven transactio-manager="txManager"/>
@Transactioonal注解的作用
如果该注解配置在类上面,就代表该类都使用事务,如果注解在方法上面就代表只有该方法需要使用事务
全注解式开发
@Configuration 代替spring配置文件
@ComponentScan 代表命名空间的包扫描
@EnableTransactionManager 开启事务管理器
@Bean 将该注解方法中的对象纳入Spring容器当中(先回运行完毕然后再将数据返回给Spring容器进行管理)
14、Spring管理Mybatis框架
依赖jar包项
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!-- spring必要依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!-- spring aop织入依赖 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
<!-- mybatis相关依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- mybatis与spring对接依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
1、创建context命名空间,开启全包扫描
<!-- 包扫描 -->
<context:component-scan base-package="扫描的包"/>
<!-- context放入属性参数jdbc.properties -->
<context:property-placeholder location="jdbc.properties"/>
<!-- dataSource绑定数据源 -->
<bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${jdbc.url}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- mapper包扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 包的位置 -->
<property name="backPackage" value="com.mapper"/>
</bean>
<!-- 创建SqlSessionFactory -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="configLocation" value="mybatis-config.xml"/>
<property name="typeAliasesPackage" value="com.pojo"/>
</bean>
<!-- 创建数据源事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 用注解的形式开启事务管理txManager -->
<tx:annotation-driven transcation-manager="txManager"/>
<context:component-scan base-package=“扫描的包”/>
<context:property-placeholder location=“jdbc.properties”/>
<tx:annotation-driven transcation-manager=“txManager”/>