spring
Spring官网 https://spring.io/
1.入门案例 1.1、导包
一个普通的入门案例不需要太多的包,这几个基础包就够了。
1.2、编写配置文件
xml的头文件约束(网址)要与导的spring jar包版本一致
http://www.springframework.org/schema/beans/spring-beans.xsd
1 2 3 4 5 6 7 8 <?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 ="user" class ="com.gec.domain.User" > </bean > </beans >
1.3、测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.gec.test;import com.gec.domain.User;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class test { @Test public void test () { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.application.xml" ); User user = (User) applicationContext.getBean("user" ); System.out.println(user); } }
1.2、通过class在IOC中找对象
2、控制反转 举个栗子:
请注意你并没有“主动”去创造橙汁 ,橙汁是由饮品店创造的,而不是你,然而也完全达到了你的要求,甚至比你创造的要好上那么一些。
将我们创建对象的方式反转了,以前创建对象方式是由开发人员自己完成的,包括后面学习的依赖关系也是由自己注入。
使用Spring之后,对象的创建以及依赖关系可以由spring完成创建以及注入
2.1、依赖注入 指 Spring 创建对象的过程中,将对象依赖属性(简单值,集合,对象)通过配置设值给该对象
注入方式:
Set方法注入
构造方法注入
字段注入
注入类型:
值类型注入 (8大基本数据类型)
引用类型注入 (将依赖对象注入)
3、spring容器介绍 3.1beanFactory
spring的最原始接口,原始接口的实现类功能最为单一和薄弱
beanFactory接口实现类的特点:每次在获得对象的时候,才会去创建对象
1 2 3 4 5 6 7 8 @Test public void fun3 () { BeanFactory ApplicationContext = new XmlBeanFactory(new ClassPathResource("applicationContext.xml" )); UserService service = (UserService) ApplicationContext.getBean("userService" ); service.addUser(); }
3.2.ApplicationContext 每次容器启动时,就会创建容器中配置的所有对象,并且该接口功能更加丰富和强大。 ApplicationContext接口有两个实现类:
加载配置文件:
从类路径下加载配置文件:ClassPathXmlApplicationContext
从硬盘绝对路径下加载配置文件:FileSystemXmlApplicationContext(“d:/xxx/yyy/xxx”)
4、Spring配置详解 4.1、bean元素基础
Bean元素:使用该元素描述需要Spring容器管理的对象
Class属性:被管理对象的完整类名
name属性:给被管理的对象起个名字。获得对象时根据该名称获得对象 可以重复,可以使用特殊字符
【经验小结】:开发中,尽量使用name属性
4.2、Spring容器中创建对象的方式 4.2.1.无参构造方式 (*****)
4.2.2.静态工厂(了解)
注意:createUser是在User类中自定义的方法
4.2.3、实例工厂(了解)
4.3bean元素进阶 1.scope属性
Sigleton 默认值(单例):也就是拿到的对象都是同一个。单例对象.被标识为单例的对象在spring容器中只会存在一个实例。
Prototype 多例:被标识为多例的对象,每次获得才会创建,每次创建都是新的对象
request: web环境下.对象与request生命周期一致.
Session : web环境下,对象与session生命周期一致.
【经验小结】 : 开发中scope属性什么时候用singleton,什么时候用prototype呢?
实际中,绝大多数都用默认的singleton,在整合Struts2框架的时候,scope必须配置为prototype多例的
2、生命周期 Spring生命周期方法
配置一个方法作为生命周期初始化方法,spring会在对象创建之后立即调用
Init-method
配置一个方法作为生命周期的销毁方法,spring容器在关闭并销毁所有容器中的对象之前调用
destroy-method
思考:** 为什么销毁方法看不到?**
3.spring中分模块配置
也就是将多个spring配置文件整合在一起
5.Spring中的属性注入 1.set方法注入 属性必须要有set的方法
结果显示:
l复杂类型
数组
List
Map
Properties
2.构造方法注入 默认情况下,Spring 容器在创建对象的时候,使用无参构造创建 ,我们可以通过设置构造方法的方式告诉Spring容器使用构造方法去创建对象!
constructor-arg 标签用来定义spring框架注入属性值的时候使用构造函数
name 属性:填写你要注入的属性字段名
value 属性:填写你要注入的属性字段对应的值
index 属性:用来控制构造函数中参数的顺序 (默认从0开始)
type 属性:用来控制构造函数中参数的类型
基本数据类型
引用类型-对象
复杂类型
数组
List
Map
Properties
构造方法注入分类:
1.默认情况
1 2 3 4 5 6 7 8 9 10 11 public class User { private Integer id; private String username; public User (String username, Car car) { System.out.println("User(String username, Car car)...." ); this .username = username; this .car = car; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 <bean name ="myCar" class ="com.shop.domain.Car" > <property name ="carname" value ="保时捷" > </property > </bean > <bean name ="user" class ="com.shop.domain.User" > <constructor-arg name ="username" value ="tom" > </constructor-arg > <constructor-arg name ="car" ref ="myCar" > </constructor-arg > </bean >
观察打印结果:
3构造方法重载
通过index 属性设置(避免“值”给了错“属性”,区分第一个构造方法)
观察打印结果:
4、重构方法2
也还是通过下标设置属性(还要再加上type=”integer”,区分第一个构造函数)
观察打印结果:
5、p名称空间注入 1.引入xml约束头文件
2.在备案元素中配置
基本数据类型
引用类型-对象
复杂类型
数组
List
Map
Properties
6.spel注入
注意:
=================================================
基本数据类型
引用类型-对象
复杂类型
数组
List
Map
Properties
【注意】:spel注入,对象类型不能使用#{}方式注入
7、复杂类型注入 Spring中使用DI注入复杂类型 准备工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class CollectionBean { private Object[] arr; private List list; private Map map; private Properties pro; public Object[] getArr() { return arr; } public void setArr (Object[] arr) { this .arr = arr; }
1、Array数组类型 往数组注入单个值
1 2 3 4 <bean name ="cb" class ="com.shop.test.CollectionBean" > <property name ="arr" value ="杰克" > </property > </bean >
1 2 3 4 5 6 7 8 @Test public void fun1 () { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml" ); CollectionBean bean = (CollectionBean) ac.getBean("cb" ); System.out.println(bean); }
往数组注入多个值
1 2 3 4 5 6 7 8 9 10 11 12 13 <property name ="arr" > <array > <value > 杰克</value > <value > 旺财</value > <ref bean ="user3" /> </array > </property > <property name ="arr" value ="杰克 旺财" > </property >
1 2 3 4 5 6 7 8 @Test public void fun1 () { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml" ); CollectionBean bean = (CollectionBean) ac.getBean("cb" ); System.out.println(bean); }
2.List 集合 往list注入单个值
1 2 3 <bean name ="cb2" class ="com.shop.test.CollectionBean" > <property name ="list" value ="小黄" > </property > </bean >
1 2 3 4 5 6 7 8 @Test public void fun2 () { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml" ); CollectionBean bean = (CollectionBean) ac.getBean("cb2" ); System.out.println(bean); }
传入多个值
1 2 3 4 5 6 7 8 9 <property name ="list" > <list > <value > 旺财</value > <value > 阿黄</value > <value > 潘金莲</value > <ref bean ="user3" /> </list > </property >
1 2 3 4 5 6 7 8 @Test public void fun2 () { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml" ); CollectionBean bean = (CollectionBean) ac.getBean("cb2" ); System.out.println(bean); }
3、Map 1 2 3 4 5 6 7 8 9 10 <bean name ="cb3" class ="com.shop.test.CollectionBean" > <property name ="map" > <map > <entry key ="url" value ="http://localhost:8080" > </entry > <entry key ="car" value-ref ="car" > </entry > <entry key-ref ="user" value-ref ="user3" > </entry > </map > </property > </bean >
1 2 3 4 5 6 7 8 @Test public void fun3 () { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml" ); CollectionBean bean = (CollectionBean) ac.getBean("cb3" ); System.out.println(bean); }
4.Properties 1 2 3 4 5 6 7 8 9 <bean name ="cb4" class ="com.shop.test.CollectionBean" > <property name ="pro" > <props > <prop key ="url" > http://localhost:3306</prop > <prop key ="name" > 旺财</prop > </props > </property > </bean >
1 2 3 4 5 6 7 8 @Test public void fun4 () { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml" ); CollectionBean bean = (CollectionBean) ac.getBean("cb4" ); System.out.println(bean); }
5、String数据 1 2 3 4 5 <bean name ="collection" class ="com.gec.domain.Collection" > <property name ="str" value ="cc bb" /> </bean >
8、注解开发IOC 注解是JDK1.5之后才有的新特性
JDK1.5之后内部提供的三个注解
@Deprecated 意思是“废弃的,过时的 ”
@Override 意思是“重写、覆盖 ”
@SuppressWarnings 意思是“压缩警告 ”
在Spring框架注解操作一共针对以下几方面:
IOC 控制反转
DI 依赖注入
AOP 面向切面
注解存在意义:
使用注解取代xml配置!!!!!!!!!!
1、搭建使用注解环境 1.导包
不然会报一下异常
2.引入xm头文件约束
3.扫描包
1 2 3 4 5 <context:component-scan base-package ="com.shop.domain" > </context:component-scan > <context:component-scan base-package ="com.shop" > </context:component-scan >
不然会报出一下异常
【开发小结】:
1. 使用注解方式开发,必须要先开启注解扫描,否则直接报错
2. Spring4以上版本,玩儿注解,需要添加aop包,目前课上使用的最新Spring5.1.2
2.IOC其他注解介绍 1.@Componment (作用在类上)
2.Spring中提供@Componment)的三个衍生注解(目前功能是一致的)
* @Controller –作用在WEB层
* @Service - 作用在业务层
* @Repository – 作用于持久层(dao层)
说明:使用这三个注解是为了让开发人员更明白注解类本身 的用途,Spring后续版本可能会对其增强.
1 2 3 @Scope(scopeName="prototype") @Scope(scopeName="singleton")
3、注解实现DI 说明:使用注解方式,可以不用提供set方法
如果注入的是普通类型,可以使用Value注解
1 2 3 4 public class User { @Value(value="jack") private Stirng name; }
注意int 类型注入也要加入双引号
2.如果注入的是对象类型,可以使用如下注解
@AutoWired – 默认按类型自动装配
1 2 3 4 5 6 7 8 9 @Component(value = "car") public class Car { private String name; private String color; public String getName () { return name; }
1 2 3 4 5 6 7 8 9 10 @Repository(value="userservice") public class User { @Value(value="jack") private String name; private int age; @Autowired private Car car; public String getName () { return name; }
@Qualifier - 强制使用名称注入
说明 :AutoWired和Qualifier都是spring框架提供的
@Resource是Java程序提供的,只不过被sprin框架所支持 - 相当于@AutoWired和@Qualifier一起使用
1 2 3 4 5 6 7 public class User { @Value(value="jack") private String name; private int age; @Resource(name="car2") private Car car;
@Resource和@service 当你需要定义某个类为一个bean,则在这个类的类名前一行使用@Service(“XXX”),就相当于讲这个类定义为一个bean,bean名称为XXX;
当需要在某个类中定义一个属性,并且该属性是一个已存在的bean,要为该属性赋值或注入时在该属性上一行使用@Resource(name=”xxx”),相当于为该属性注入一个名称为xxx的bean。
===================================================================================================
Spring不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource、@PostConstruct以及@PreDestroy。 @Resource的作用相当于@Autowired,只不过**@Autowired按byType自动注入,而 @Resource默认按 byName自动注入**罢了。@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。 @Resource装配顺序
1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常 2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常 3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常 4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
Aop 2.AOP 1.AOP概述(掌握) 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP(面向对象编程)的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
经典应用:事务管理、性能监视、安全检查、缓存 、日志等
Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码
AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,
AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入
2、AOP思想简单分析 假如在Service层增加事务:开启事务,提交事务。但是不修改原有的Service层代码。
第一种方案是继承这个了类,但是这种方法的耦合性高,因为用到了继承
1 2 3 4 5 6 7 8 public class UserService { public void addUser () { System.out.println("添加用户" ); } }
利用继承实现切面加入事务,但是耦合度极高,因为用了继承
1 2 3 4 5 6 public class Demo extends UserService { void addUser () }
第二种:AOP
3.AOP中专业术语(重点) **1.Target(目标类):**需要被代理的类。例如:ProductService
**2.joinPoint (连接点):**所谓连接点,就是那些可能被spring拦截的点(方法) ef:(上面的void addUser()方法)
**3.pointCut(切入点):**已经被增强的连接点(方法)
**4.advice(通知/增强):**那些增强的代码
**5.weaving(织入):**是指把增强advice应用到目标对象target来创建新的代理(proxy)的过程
6.poxy :代理类
**7.Aspectj(切面):**切入点pointcut和通知advice的结合
4、AOP栗子 1、导入架包 spring核心包(4个+一个commons-logging-1.2.jar(spring4.1以后才需要))
spring中AOP核心jar包(两个aop+aspects)
第三方依赖包AOP jar包(两个:aopalliance+weaver)
spring-framework-3.0.2.RELEASE-dependencies\org.aopalliance\com.springsource.org.aopalliance\1.0.0\com.springsource.org.aopalliance-1.0.0.jar
spring-framework-3.0.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE\com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar 这个包 是注解开发AOP的时候用的 ,测试的时候不导这个包也能跑
最终jar图:
2、导入约束
完整约束
1 2 3 4 5 6 7 8 9 10 11 12 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns ="http://www.springframework.org/schema/beans" xmlns:context ="http://www.springframework.org/schema/context" xmlns:aop ="http://www.springframework.org/schema/aop" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd " >
3、准备目标类(target) 1 2 3 4 5 6 7 8 public class UserService { public void addUser () { System.out.println("添加用户" ); } public void updateUser () { Syste.out.pritln("更新用户" ); } }
4、准备通知(增强) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class MyAdvie { public void before () { System.out.println("开启事务" ); } public void afterReturning () { System.out.println("提交事务。。。" ) } public Object around (ProceeedingJoinPoint pjp) throw Throwable { System.out.println("这是环绕通知之前的部分...." ); Object proceed = pjp.proceed(); System.out.println("这是环绕通知之后的部分..." ); return proceed; } public void afterException () { System.out.println("不好了,出事情了" ); } public void after () { System.out.println("出现异常,也会继续执行" ); } }
5、织入 将通知(增强)织入到目标类中
1.配置目标类 1 <bean name ="productservice" class =”com.shop,aa,ProductService "> </bean >
2.配置通知 1 <bean name ="mydvice" class ="com.shop.aa.Myadvice" > </bean >
3.织入配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <bean name ="productservice" class ="com.shop.weaving.ProductService" > </bean > <bean name ="myadvice" class ="com.shop.weaving.MyAdvice" > </bean > <aop:config > <aop:pointcut expression ="execution(public void com.shop.weaving.ProductService.addProduct())" id ="pc" /> <aop:aspect ref ="myadvice" > <aop:before method ="before" pointcut-ref ="pc" /> <aop:after method ="afterReturning" pointcut-ref ="pc" /> <aop:around method ="around" pointcut-ref ="pc" /> <aop:after-throwing method ="afterException" pointcut-ref ="pc" /> <aop:after method ="after" pointcut-ref ="pc" /> </aop:aspect > </aop:config > </beans >
4.测试 1 2 3 4 5 6 7 8 9 10 11 12 13 public class TestDemo1 { @Test public void test1 () { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml" ); UserService userService = (UserService) applicationContext.getBean("userService" ); userService.addUser(); } }
5.执行结果:
6、 aop:pointcut多种写法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <aop:pointcut expression ="execution(public void com.shop.weaving.ProductService.addProduct())" id ="pc" /> 1.public void com.shop.weaving.ProductService.addProduct() 2.void com.shop.weaving.ProductService.addProduct() 3.* com.shop.weaving.ProductService.addProduct() 4.* com.shop.weaving.ProductService.*Product() 5.* com.shop.weaving.ProductService.addProduct(..) 6.* com.shop.weaving.*Service.addProduct(..) 7.* com.shop.weaving.*Service.*Product(..)
注意: 以下四个切入点标签的书写顺序,会影响到切入的顺序
1 2 3 4 5 6 <aop:before method ="before" pointcut-ref ="us" /> <aop:after-returning method ="after" pointcut-ref ="us" /> <aop:after-throwing method ="thowe" pointcut-ref ="us" /> <aop:after method ="after" pointcut-ref ="us" /> <aop:around method ="arround" pointcut-ref ="us" />
5、切入点表达式解析 1 2 3 <aop:pointcut id ="pc" expression ="execution(public void com.shop.target.UserService.addUser())" > </aop:pointcut >
1 2 3 4 5 6 7 8 public void com.shop.target.UserService.addUser() * void com.shop.target.UserService.addUser() * com.shop.target.UserService.addUser() * com.shop.target.UserService.*() * com.shop.target.UserService.*(..) * com.shop.target.*Service.*(..) * com.shop.target..*Service.*(..)
6、通知/增强详解 1.通知介绍 1.前置通知(before)
2.后置通知(after-returning)
3.环绕通知(around)
4.异常拦截通知(afterException)
5.后置通知(最终通知)(after)
目标方法运行之后调用
无论是否出现异常,都会被调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public class MyAdvice { public void before () { System.out.println("开启事务" ); } public void afterReturning () { System.out.println("提交事务。。。" ); } public Object around (ProceedingJoinPoint pjp) thr ows Throwable { System.out.println("这是环绕通知之前的部分...." ); Object proceed = pjp.proceed(); System.out.println("这是环绕通知之后的部分..." ); return proceed; } public void afterException () { System.out.println("不好了,出事情了" ); } public void after () { System.out.println("出现异常,也会继续执行" ); } }
通知(增强)的类型:
1.前置通知
before
2.后置通知
after-returning
3.最终通知
after
**4.异常抛出通知 **
after-throwing
**5.环绕通知 **
around
2.通知/增强测试 1 2 3 4 5 6 7 8 9 10 11 public class UserService { public void addUser () { int i=1 /0 ; System.out.println("添加用户" ); } public void updatUser () { System,out.println("删除用户。。。" ); } }
afterException() 如果在代码运行过程中发生了异常,将会被此通知拦截
1 2 3 4 5 6 7 public class MyAdvice { public void afterException () { System.out.println("不好了,出事情了" ); } }
1 2 3 4 5 6 7 8 9 10 11 <aop:config > <aop:pointcut id ="pc" expression ="execution(public void com.shop.target.UserService.addUser())" > </aop:pointcut > <aop:aspect ref ="myAdvice" > <aop:after-throwing method ="afterException" pointcut-ref ="pc" > </aop:after-throwing > </aop:aspect > </aop:config >
打印观察测试:
后置通知 (after-returning)
(目标方法运行之后调用)
(如果出现异常则不会调用)
后置通知(最终通知)(after)
目标方法运行之后调用
(无论是否出现异常,都会被调用)
观察打印结果:
3.通知/增强(advice)参数 Joinpoint参数(重点)
**getTarget() **获得被代理的目标对象
getSignature().getName() 获取被代理目标类 中的目标方法
7、注解开发AOP 导包就不多说了跟原来xml开发一样
1、applicationContext.xml中添加扫描包的xml头文件约束(content)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:aop ="http://www.springframework.org/schema/aop" 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/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd " > <context:component-scan base-package ="com.gec" /> <aop:aspectj-autoproxy > </aop:aspectj-autoproxy >
2.通知类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.gec.Service;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.springframework.stereotype.Component;@Component @Aspect public class Demo { @Before(value = "execution(public void com.gec.Service.UserService.addUser())") public void before () { System.out.println("开启事务" ); } @After(value="execution(* com.gec.Service.UserService.*User())") public void after () { System.out.println("提交事务" ); } }
3.连接点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com.gec.Service;import org.springframework.stereotype.Component;@Component("userService") public class UserService { public void addUser () { System.out.println("添加用户" ); } public void updateUser () { System.out.println("gengxing用户" ); } }
4、测试
1 2 3 4 5 6 7 @Test public void test2 () { ApplicationContext applicationContent = new ClassPathXmlApplicationContext("applicationContent2.xml" ); UserService userService = (UserService) applicationContent.getBean("userService" ); userService.addUser(); }
5、结果
idea 小插曲 ctrl+F+F12:打开一个新的窗口显示类结构
JDBCTemplete spring中提供了一个可以操作数据库的对象.对象封装了jdbc技术.
JDBCTemplate => JDBC模板对象
与DBUtils中的QueryRunner非常相似.
1、构建环境 1.导包 2、编写测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 package com.gec.test;import com.mchange.v2.c3p0.ComboPooledDataSource;import org.junit.Test;import org.springframework.jdbc.core.JdbcTemplate;import java.beans.PropertyVetoException;import java.sql.Connection;import java.sql.SQLException;public class test { @Test public void test () throws PropertyVetoException, SQLException { ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver" ); comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mybatis" ); comboPooledDataSource.setUser("root" ); comboPooledDataSource.setPassword("root" ); Connection connection = comboPooledDataSource.getConnection(); System.out.println(connection); JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(comboPooledDataSource); String sql= "update user set username =100 where id= 1" ; int update = jdbcTemplate.update(sql); System.out.println(update); } }
3、执行结果:
2、JDBCTemplate整合spring 1、导包(就不多bb了,跟上面一样)
2、创建用到的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package com.gec.domain;public class User { int id; String username; String password; public int getId () { return id; } public void setId (int id) { this .id = id; } public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } public String getPassword () { return password; } public void setPassword (String password) { this .password = password; } @Override public String toString () { return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + '}' ; } }
UserDao就h只有一个方法findAll(),,连JdbcTemplate jdbcTemplate;都没有,所以即不再这里写了,能猜得出来长什么样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package com.gec.dao;import com.gec.domain.User;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.RowMapper;import java.sql.ResultSet;import java.sql.SQLException;import java.util.List;public class UserDaoImpl implements UserDao { JdbcTemplate jdbcTemplate; @Override public List<User> findAll () { String sql= "select * from user" ; List<User> list = jdbcTemplate.query(sql, new RowMapper<User>() { @Override public User mapRow (ResultSet resultSet, int i) throws SQLException { User user = new User(); user.setId(resultSet.getInt("id" )); user.setUsername(resultSet.getString("username" )); user.setPassword(resultSet.getString("password" )); return user; } }); return list; } public void setJdbcTemplate (JdbcTemplate jdbcTemplate) { this .jdbcTemplate = jdbcTemplate; } }
2、编写applicationContext.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:aop ="http://www.springframework.org/schema/aop" 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/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd " > <bean name ="c3p0" class ="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name ="driverClass" value ="com.mysql.jdbc.Driver" /> <property name ="jdbcUrl" value ="jdbc:mysql://localhost:3306/mybatis" /> <property name ="user" value ="root" /> <property name ="password" value ="root" /> </bean > <bean name ="jdbctemplate" class ="org.springframework.jdbc.core.JdbcTemplate" > <property name ="dataSource" ref ="c3p0" /> </bean > <bean name ="UserDaoImpl" class ="com.gec.dao.UserDaoImpl" > <property name ="jdbcTemplate" ref ="jdbctemplate" /> </bean > </beans >
3、测试
1 2 3 4 5 6 7 8 9 10 @Test public void test6 () throws PropertyVetoException, SQLException { ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml" ); UserDaoImpl userDaoImpl = (UserDaoImpl) classPathXmlApplicationContext.getBean("UserDaoImpl" ); List<User> list = userDaoImpl.findAll(); for (User user : list) { System.out.println(user); } }
结果:
一套下来没什么bug,成就感很高
3、事务 1、介绍 事务特性:acid:原子性**(Atomicity)、一致性 (Consistency)、隔离性 (Isolation)、持久性 (Durability)**
事务并发问题:
2、Spring中事务介绍 spring封装了事务管理代码
事务操作:
事务的隔离级别
1 读未提交
2 读已提交
4 可重复读
8 串行化
事务操作对象:
因为在不同平台,操作事务的代码各不相同.spring提供了一个接口
PlatformTransactionManager 接口
事务传播行为:
3、spring整合事务 spring + jdbctemplate+transaction
方式一: (模板方式),不推荐使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 <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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" > <bean name ="dataSource" class ="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name ="driverClass" value ="com.mysql.jdbc.Driver" > </property > <property name ="jdbcUrl" value ="jdbc:mysql://localhost:3306/gz1960" > </property > <property name ="user" value ="root" > </property > <property name ="password" value ="12345" > </property > </bean > <bean name ="dataSourceTransactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name ="dataSource" ref ="dataSource" > </property > </bean > <bean name ="template" class ="org.springframework.transaction.support.TransactionTemplate" > <property name ="transactionManager" ref ="dataSourceTransactionManager" > </property > </bean > <bean name ="jdbcTemplate" class ="org.springframework.jdbc.core.JdbcTemplate" > <property name ="dataSource" ref ="dataSource" > </property > </bean > <bean name ="accountDao" class ="com.shop.dao.impl.AccountDaoImpl" > <property name ="jdbcTemplate" ref ="jdbcTemplate" > </property > </bean > <bean name ="accountService" class ="com.shop.service.impl.AccountServiceImpl" > <property name ="accountDao" ref ="accountDao" > </property > <property name ="tt" ref ="template" > </property > </bean > </beans >
4.在Service中调用模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public class AccountServiceImpl implements AccountService { private AccountDao accountDao; private TransactionTemplate tt; @Override public void transfer (Integer from, Integer to, double money) { tt.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult (TransactionStatus arg0) { accountDao.lostMoney(from, money); int i = 1 /0 ; accountDao.addMoney(to, money); } }); } public AccountDao getAccountDao () { return accountDao; } public void setAccountDao (AccountDao accountDao) { this .accountDao = accountDao; } public TransactionTemplate getTt () { return tt; } public void setTt (TransactionTemplate tt) { this .tt = tt; } }
方式二: 利用AOP切入
1.第一步导包
6个IOC(核心)包,4个AOP包、1个spring JdbcTemplate包、2个事务包、1个mysql驱动包、1个c3p0连接池包
2、创建需要的类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package com.gec.domain;public class User { int id; String username; int money; public int getId () { return id; } public void setId (int id) { this .id = id; } public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } public int getMoney () { return money; } public void setMoney (int money) { this .money = money; } @Override public String toString () { return "User{" + "id=" + id + ", username='" + username + '\'' + ", money=" + money + '}' ; } }
dao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 package com.gec.dao;import com.gec.domain.User;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.RowMapper;import java.sql.ResultSet;import java.sql.SQLException;import java.util.List;public class UserDaoImpl implements UserDao { JdbcTemplate jdbcTemplate; public void setJdbcTemplate (JdbcTemplate jdbcTemplate) { this .jdbcTemplate = jdbcTemplate; } @Override public int increase (int money, int from_userid) { String sql= "update account set money=? where id=? " ; int update = jdbcTemplate.update(sql, money, from_userid); System.out.println(sql); return update; } @Override public int decrease (int money, int from_userid) { String sql= "update account set money=? where id=? " ; int update = jdbcTemplate.update(sql, money, from_userid); System.out.println(sql); return update; } @Override public User findByid (int id) { String sql= " select * from account where id= ? " ; List<User> list = jdbcTemplate.query(sql, new RowMapper<User>() { @Override public User mapRow (ResultSet resultSet, int i) throws SQLException { User user = new User(); user.setId(resultSet.getInt(1 )); user.setUsername(resultSet.getString(2 )); user.setMoney(resultSet.getInt(3 )); return user; } }, id); if (list.size()>0 ){ return list.get(0 ); } return null ; } }
Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.gec.Service;import com.gec.dao.UserDao;import com.gec.domain.User;public class UserServiceImpl implements UserService { UserDao userDao; public void setUserDao (UserDao userDao) { this .userDao = userDao; } @Override public void zhuanqian (int id1, int id2, int money) { User dUser = userDao.findByid(id1); User iUser = userDao.findByid(id2); userDao.decrease(dUser.getMoney()-100 ,1 ); userDao.increase(dUser.getMoney()+100 ,2 ); } }
3、配置xml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:aop ="http://www.springframework.org/schema/aop" 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/aop http://www.springframework.org/schema/aop/spring-aop-4.2.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 " >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 <bean name ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name ="dataSource" ref ="c3p0" /> </bean > <tx:advice id ="mydavice" transaction-manager ="transactionManager" > <tx:attributes > <tx:method name ="zhuanqian" isolation ="READ_UNCOMMITTED" propagation ="REQUIRED" read-only ="false" /> </tx:attributes > </tx:advice > <aop:config > <aop:pointcut id ="pc" expression ="execution(* com.gec.Service.UserServiceImpl.zhuanqian(..))" /> <aop:advisor advice-ref ="mydavice" pointcut-ref ="pc" /> </aop:config > <bean name ="user" class ="com.gec.domain.User" /> <bean name ="c3p0" class ="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name ="driverClass" value ="com.mysql.jdbc.Driver" /> <property name ="jdbcUrl" value ="jdbc:mysql://localhost:3306/mybatis" /> <property name ="user" value ="root" /> <property name ="password" value ="root" /> </bean > <bean name ="jdbctemplate" class ="org.springframework.jdbc.core.JdbcTemplate" > <property name ="dataSource" ref ="c3p0" /> </bean > <bean name ="UserDaoImpl" class ="com.gec.dao.UserDaoImpl" > <property name ="jdbcTemplate" ref ="jdbctemplate" /> </bean > <bean name ="UserServiceImpl" class ="com.gec.Service.UserServiceImpl" > <property name ="userDao" ref ="UserDaoImpl" /> </bean >
配置事务通知
4、测试 1 2 3 4 5 6 7 8 9 @Test public void test2 () { ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext2.xml" ); UserService userService = (UserService) classPathXmlApplicationContext.getBean("UserServiceImpl" ); userService.zhuanqian(1 ,2 ,100 ); }
方式三: 注解方式实现
1、导包
使用的包,与xml开发一致
2、xml中配置
头文件约束:基本上一致,看看有没有context约束,有就不理,没有就加上,用于扫描事务。
开启事务扫描
1 <tx:annotation-driven transaction-manager ="transactionManager" />
完整的xml中的配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 <?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: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" > <bean name ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name ="dataSource" ref ="c3p0" /> </bean > <tx:annotation-driven transaction-manager ="transactionManager" /> <bean name ="c3p0" class ="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name ="driverClass" value ="com.mysql.jdbc.Driver" /> <property name ="jdbcUrl" value ="jdbc:mysql://localhost:3306/mybatis" /> <property name ="user" value ="root" /> <property name ="password" value ="root" /> </bean > <bean name ="jdbctemplate" class ="org.springframework.jdbc.core.JdbcTemplate" > <property name ="dataSource" ref ="c3p0" /> </bean > <bean name ="UserDaoImpl" class ="com.gec.dao.UserDaoImpl" > <property name ="jdbcTemplate" ref ="jdbctemplate" /> </bean > <bean name ="UserServiceImpl" class ="com.gec.Service.UserServiceImpl" > <property name ="userDao" ref ="UserDaoImpl" /> </bean > </beans >
3、在类中添加注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class UserServiceImpl implements UserService { UserDao userDao; public void setUserDao (UserDao userDao) { this .userDao = userDao; } @Override @Transactional(isolation = Isolation.READ_UNCOMMITTED,propagation = Propagation.REQUIRED,readOnly = true) public void zhuanqian (int id1, int id2, int money) { User dUser = userDao.findByid(id1); User iUser = userDao.findByid(id2); userDao.decrease(dUser.getMoney()-100 ,1 ); userDao.increase(dUser.getMoney()+100 ,2 ); } }
注意:这个注解可以放在类,可以放在方法上
Mybatis整合
mybatis是使用核心对象SqlSession操作数据库
要获得SqlSession实例,就需要SqlSessionFactory
而SqlSessionFactory是SqlSessionFactoryBulider依据Mybatis核心配置文件中数据源、sql映射文件等信息构建的。
以前我们使用mybatis,就需要我们自己手动编写代码去创建这些对象,现在:让Spring容器帮我们去管理(创建对象)
初级整合: 1、导包
2、创建需要用到的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 package com.gec.domain; public class User { int id; String username; String money; public User() { } public User(int id, String username, String money) { this.id = id; this.username = username; this.money = money; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getMoney() { return money; } public void setMoney(String money) { this.money = money; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", money='" + money + '\'' + '}'; } }
mapper
1 2 3 4 5 6 7 8 9 10 11 12 13 package com.gec.mapper;import com.gec.domain.User;import org.apache.ibatis.annotations.Param;import org.mybatis.spring.SqlSessionTemplate;import java.util.List;public interface UserMapper { List<User> findAll () ; User findOne (@Param(value = "id") int id) ; }
1 2 3 4 5 6 7 8 9 10 11 12 <?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.gec.mapper.UserMapper" > <select id ="findAll" resultType ="com.gec.domain.User" > SELECT * from user; </select > <select id ="findOne" resultType ="com.gec.domain.User" > SELECT * from user where id= #{id} ; </select > </mapper >
Dao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package com.gec.dao;import com.gec.domain.User;import com.gec.mapper.UserMapper;import org.mybatis.spring.SqlSessionTemplate;import java.util.List;public class UserDao { SqlSessionTemplate sqlSessionTemplate; public void setSqlSessionTemplate (SqlSessionTemplate sqlSessionTemplate) { this .sqlSessionTemplate = sqlSessionTemplate; } public void addUser (User user) { String sql= "insert into " ; } public List<User> selectlist () { List<User> list = sqlSessionTemplate.selectList("com.gec.mapper.UserMapper.findAll" ); return list; } public User selectone (int i) { UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class); User user = mapper.findOne(1 ); return user; } }
3、创建spring配置文件
1、导入头文件约束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?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: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/context http://www.springframework.org/schema/context/spring-context.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" ></beans >
mybatis.config.xml
1 2 3 4 5 6 7 <?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 >
2、将需要的创建对象交给IOC
配置数据源
spring和myabtis整合,不再使用jdbc默认连接池技术,使用 一些第三方的数据连接池技术
常见的有dbcp、C3p0 、Proxool等连接池技术
导入dbcp连接池的jar包
让spring管理dbcp数据连接池
配置SqlSessionFactoryBean
mybaits中SqlSessionFactory使用SqlsessionFactoryBulider构建
整合后,使用SqlSessionFactoryBean
配置SqlSessionTemplete
传统mybatis开发,使用SqlSession,有了SqlSession可以帮助我们操作数据库
而在Spring整合mybatis后,Spring框架封装了SqlSession类,提供了一个SqlSessionTemplete
SqlSessionTemplete特点:
实现了SqlSession
融合spring并简化部分流程化工作
保证和当前spring中事务自动相关联
自动管理会话生命周期(关闭、提交、回滚)
【开发小结】:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <bean name ="basicDataSource" class ="org.apache.commons.dbcp.BasicDataSource" > <property name ="driverClassName" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/mybatis?Unicode=true& characterEncoding=utf-8" /> <property name ="username" value ="root" /> <property name ="password" value ="root" /> </bean > <bean name ="sqlSessionFactory" class ="org.mybatis.spring.SqlSessionFactoryBean" > <property name ="dataSource" ref ="basicDataSource" /> <property name ="configLocation" value ="classpath:mybatis.config.xml" > </property > <property name ="mapperLocations" > <list > <value > classpath:com/gec/mapper/UserMapper.xml</value > </list > </property > </bean > <bean id ="sqlsession" class ="org.mybatis.spring.SqlSessionTemplate" > <constructor-arg name ="sqlSessionFactory" ref ="sqlSessionFactory" /> </bean > <bean name ="userDao" class ="com.gec.dao.UserDao" > <property name ="sqlSessionTemplate" ref ="sqlsession" /> </bean >
【开发总结】:
4、测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @Test public void test () { ApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml" ); UserDao userDao = (UserDao) ApplicationContext.getBean("userDao" ); List<User> list = userDao.selectlist(); for (User user : list) { System.out.println(user); } } @Test public void test2 () { ApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml" ); UserDao userDao = (UserDao) ApplicationContext.getBean("userDao" ); User selectone = userDao.selectone(1 ); System.out.println(selectone); }
**【开发小结】:**使用spring整合之后,可以将数据源、SqlSessionFactoryBean、SqlSessionTemplete都交给spring管理,简化了开发
中级整合: 根据上面初级整合修改。
由于每一个对dao层类都需要添加一个sqlSessionTemplate成员变量,并且IOC中注入,相对较麻烦,所以对sqlSessionTemplate进行改进
,通过引入Spring-mybatis包中的SqlSessionDaoSupport类 。
1 2 3 4 5 public SqlSession getSqlSession () { return this .sqlSession; }
我们只要将自己的类继承这个类 ,那么就可以使用使用它的getSession()获取session
1 2 3 public class UserDao2 extends SqlSessionDaoSupport{ }
有get方法就有set方法,需要进行set才能get.
通过上面的源码可以看出,通过传入一个sqlSessionFactory,它会new sqlSessionTemplate给sqlSessionTemplate,所以
将SqlSessionFactoryBean注入给它
1 2 3 <bean name ="userDao" class ="com.gec.dao.UserDao" > <property name ="sqlSessionFactory" ref ="sqlSessionFactory" /> </bean >
Dao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class UserDao extends SqlSessionDaoSupport { public List<User> selectOne () { List<User> list = this .getSqlSession().selectList("com.gec.mapper.UserMapper.findAll" ); return list; } }
【开发小结】:之前我们需要在dao的实现类中,提供sqlSessionTemplete的set方法,并将sqlTemp注入到dao实现类中。
现在只需要让自己的类继承SqlSessionSupport,然后将SqlFac注入进来,就可以直接使用get()方法获取SqlSessionTemp (SqlSession),不需要创建sqlsession,也不需要提供setter方法
高级整合;
使用sqlsession内部的方法,都是写死的字符串来获取,很容易产生错误且错误还不易被发觉
每次都要在Dao中getMapper一下,繁琐,能不能让spring帮我们去getMapper操作,自己只提供一个接口呢?
根据中级的基础上再次改进。去掉Dao层,因为Dao是多余的,就只是单纯为了拿到UserMapp。
如果将UserMap交给IOC那么就可以删掉UserDao.
所以Spring提供了MapperFactoryBean直接注入映射器
使用MapperFactoryBean注入映射器
mapperFactoryBean特点:
继承了SqlSessionDaoSupport
所以有传给它一个sqlSession工厂,来获取sqlSession
1 2 3 4 5 6 7 <bean name ="userDao" class ="org.mybatis.spring.mapper.MapperFactoryBean" > <property name ="mapperInterface" value ="com.gec.mapper.UserMapper" /> <property name ="sqlSessionFactory" ref ="sqlSessionFactory" /> </bean >
直接将UserMapper交给了MapperFactoryBean类。
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 @Test public void test () { ApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml" ); UserMapper userDao = (UserMapper) ApplicationContext.getBean("userDao" ); List<User> list = userDao.findAll(); for (User user : list) { System.out.println(user); } }
再次改进
因为以上方法配置多个mapper的时候,比较麻烦,每一个都有写。所以,这时候,spring提供可以直接通过package名,指定扫描该package下的所有,mapper接口,直接注册为MapperFactoryBean
1 2 3 4 5 <bean class ="org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name ="basePackage" value ="cn.gec.mapper" > </property > </bean >
这个时候就不知道,springIOC会给每个mapper接口取什么名字,这个时候,可以通过一下方法看到取得名字
我们可以通过getBeanDefinitionNames()获取所有的bean名称
1 2 3 4 5 6 7 8 9 @Test public void test2 () { ApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml" ); String[] names = ApplicationContext.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } }
给的名字是类的名字,但是是首字母是小写
根据spring的名字进行测试
1 2 3 4 5 6 7 8 9 10 11 @Test public void test3 () { ApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml" ); UserMapper userDao = (UserMapper) ApplicationContext.getBean("userMapper" ); List<User> list = userDao.findAll(); for (User user : list) { System.out.println(user); } }
测试结果: