目录
6.3、其余request、session、application都在web中使用
0、写在前面
Spring5的下载:官网(spring.io)下载稳定版本(GA)
spring5下载完成:
1、Spring
spring优点
- Spring是一个开源的免费框架(容器)
- Spring是一个轻量级的、非入侵式的框架
- IOC控制反转、AOP面向切面编程
- 支持事务的处理、对框架整合
Spring就是一个轻量级的控制反转和面向切面变成的框架。
2、Spring组成
- Spring Core:框架的最基础部分,提供 IoC 容器,对 bean 进行管理。
- Beans、Core、Context、Expression
- Spring Context:基于 bean,提供上下文信息,扩展出JNDI、EJB、电子邮件、国际化、校验和调度等功能。
- Spring DAO:提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码,还提供了声明性事务管理方法。
- Spring ORM:提供了常用的“对象/关系”映射APIs的集成层。 其中包括JPA、JDO、Hibernate、MyBatis 等。
- Spring AOP:提供了符合AOP Alliance规范的面向方面的编程实现。
- Spring Web:提供了基础的 Web 开发的上下文信息,可与其他 web 进行集成。
- Spring Web MVC:提供了 Web 应用的 Model-View-Controller 全功能实现。
3、Spring Boot
- 一个快速开发的脚手架
- 基于Spring Boot可以快速的开发耽搁微服务
- 约定大于配置
- Spring Cloud基于SpringBoot实现
4、Spring配置
4.1、别名
<alias name="accountService" alias="as"></alias>
4.2、bean的配置
<!--
在spring的配置文件中使用bean标签,配以id和class属性后,且没有其他属性和标签时。
id:bean的唯一标识符,x相当于对象名
class:bean对象所属的权限定类型 包名类名
name:bean的别名,可以取多个,可以通过逗号空格分号分割
采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。
-->
<bean id="accountService10" class="com.lh.spring.service.impl.AccountServiceImpl" name="accS,assS1 assS2;assS3"></bean>
<bean id="accountDao" class="com.lh.spring.dao.impl.AccountDaoImpl"></bean>
4.3、import
一般用于团队开发使用,可以将多个配置文件导入合并为一个。
xml的正常名称:applicationContect.xml
5、依赖注入
5.1、构造函数注入
5.2、set方法注入(***)
依赖:bean对象的创建依赖容器
注入:bean对象所有属性由容器注入
- 普通注入:value
- bean注入:ref
- 空值注入:<null/>
- 数组:<array>
- property注入:<props>
- list: <list>
- set: <set>
- map: <entry>
5.3、p/c空间注入
我们可以使用p空间和c空间注入
注意:p和c空间不能直接使用,需要导入xml约束
xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
6、Bean的作用域
- bean对象默认是单例
- bean标签的scope属性: 作用:用于指定bean的取值范围 取值: 常用:单例和多例
- singleton:单例(默认)
- prototype:多例
- request:作用于web应用的请求范围
- session:作用于web应用的会话范围
- global-session::作用于集群环境的会话范围(全局会话范围),当不是集群时,他就是session
6.1、单例模式(Spring默认)
容器中一个类只有一个对象
<bean id="person" class="cn.crane.bean.Person" c:name="name" c:age="34 scope=singleton>
6.2、原型模式
每次从容器中get()时,都会产生一个新对象。
<bean id="person" class="cn.crane.bean.Person" c:name="name" c:age="34 scope=prototype>
6.3、其余request、session、application都在web中使用
7、Bean的自动装配
7.1、自动装配是Spring满足bean依赖的一种方式
Spring会在上下文中自动寻找,并自动给bean装配属性
Spring三种装配方式
- 在xml中显示配置
- 在java中显示配置
- 隐式的自动装配bean(****)
7.2、ByName自动装配
之前
<bean id="people" class="TEst.People"> <property name="name" value="xiaoli"></property> <property name="cat" ref="cat"></property> <property name="dog" ref="dog"></property> </bean> <bean id="dog" class="TEst.Dog"></bean> <bean id="cat" class="TEst.Cat"></bean>
- 需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法后面的值一致。
- 会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid。
setDog----dog----id="dog"。setCat ----cat------id="cat" 。
<bean id="people" class="TEst.People" autowire="byName"> <property name="name" value="xiaoli"></property> </bean> <bean id="dog" class="TEst.Dog"></bean> <bean id="cat" class="TEst.Cat"></bean>
7.3、byType自动装配
- 需要保证所有bean的class 唯一,并且这个bean需要和自动注入的属性的类型一致。
- 会自动在容器上下文中查找,和自己对象属性类型相同的bean,必须保证容器中类型全局唯一。
<bean id="people" class="TEst.People" autowire="byType"> <property name="name" value="xiaoli"></property> </bean> <bean id="dogaa" class="TEst.Dog"></bean> <bean id="cataaa" class="TEst.Cat"></bean>
7.4、注解自动装配
jdk1.5支持注解,spring2.5支持注解开发
使用注解须知:
1、导入约束(.../context)
2、配置注解的支持(<contetx:annotation-config/>)
<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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/beans/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/context/spring-aop.xsd"> <!--开启注解支持--> <contetx:annotation-config/> </bean>
public class People {
//如果显示定义了Autowired的rerequired属性为false,说明这个属性可以为null,否则不允许为空
@Autowired(required = false)
private Cat cat;
private Dog dog;
private String name;
//表示name可以为空,为空时不报错
public People(@Nullable String name){
this.name = name;
}
}
* 用于注入数据: * 他们的作用和在xml配置文件中bean标签中写一个<property>标签一样 * @Autowired: * 作用:自动按照类型注入,只要容器中有唯一一个bean对象类型和要注入的变量类型匹配,就可以注入成功 * 如果IOC容器中没有任何bean的类型和要注入的变量的类型匹配,报错 * 如果IOC容器中有多个类型匹配时: * 出现位置: * 可以是变量上,也可以方法上 * 细节:在使用注解注入时,set方法不是必须的 * @Qualifier: * 作用:在按照类中注入的基础之上再按照名称注入。他在给类成员注入时不能单独使用。但是再给方法参数注入时可以。 * 属性:value:用于指定注入bean的id * @Resource * 作用:直接按照bean的id注入,他可以独立使用 * 属性:name,用于指定bean的id * 以上三个注解都只能注入其他bean类型的数据,而基本数据类型和String类型无法使用上述注解实现。 * 另外,集合类型的注入只能通过XML实现。 * @Value: * 作用:用于注入基本类型和String类型的数据 * 属性:value:用于指定数据的值,他可以使用spring的spEl(spring的el表达式) * spEL写法: ${表达式}
8、使用注解开发
在Spring4之后,要使用注解开发,必须保证aop的包导入了
使用注解需要导入context约束,增加注解的支持。
8.1、bean
8.2、属性如何注入
8.3、衍生注解
8.4、自动装配
8.5、作用域
8.6、小结
9、使用Java的方式配置Spring
我们现在完全不使用spring的xml配置了,全权交给Java来做
JavaConfig是spring的一个子项目,在Spring 4之后成为一个核心功能
1、 实体类
2、配置类
3、测试类
这种存java配置方式,在springboot随处可见
10、代理模式
为什么使用代理模式,因为这是AOP底层
10.1、静态代理
/**
* 租房
*/
public interface Rent {
}
/**
* 房东
*/
public class Host implements Rent{
public void rent(){
System.out.println("房东要出租房子");
}
}
/**
* 代理
*/
public class Proxy implements Rent{
Host host = new Host();
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
public void rent(){
seeHouse();
host.rent();
hetong();
fare();
}
public void seeHouse(){
System.out.println("中介带你看房");
}
public void hetong(){
System.out.println("中介跟你签合同");
}
public void fare(){
System.out.println("中介收中介费");
}
}
public class Client {
public static void main(String[] args) {
//房东要出租房子
Host host = new Host();
//代理,中介帮房东出租房子,有一些附加操作
Proxy proxy = new Proxy(host);
//直接找代理
proxy.rent();
}
}
【静态代理实战(在所有方法上加个日志)】
public interface UserService {
public void add();
public void delete();
public void update();
public void query();
}
package designpattern;
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("增加了一个用户");
}
@Override
public void delete() {
System.out.println("删除了一个用户");
}
@Override
public void update() {
System.out.println("更新了一个用户");
}
@Override
public void query() {
System.out.println("查询了一个用户");
}
}
package designpattern;
public class UserProxy implements UserService {
private UserServiceImpl userService;
public void setUserService(UserServiceImpl userService) {
this.userService = userService;
}
@Override
public void add() {
log("add");
userService.add();
}
@Override
public void delete() {
log("delete");
userService.delete();
}
@Override
public void update() {
log("update");
userService.update();
}
@Override
public void query() {
log("query");
userService.query();
}
public void log (String msg){
System.out.println("【debug】使用了一个"+msg+"方法");
}
}
10.2、动态代理
public class MyInvokeHandler implements InvocationHandler {
//真实类(被代理类),被代理类接口
Object target;
public void setTarget(Object target) {
this.target = target;
}
//获取代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),this);
}
//调用方法
//处理代理实例,并返回结果
//调用 getProxy 方法会自动调用invoke方法,因为传入InvocationHandler
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object result = method.invoke(target,args);
return result;
}
public void log (String msg){
System.out.println("执行了"+msg+"方法");
}
}
public class ClientProxy {
public static void main(String[] args) {
//真实角色
UserServiceImpl userService = new UserServiceImpl();
//代理角色,不存在
MyInvokeHandler myInvokeHandler = new MyInvokeHandler();
//设置要代理的对象
myInvokeHandler.setTarget(userService);
//生成动态代理类
UserService proxy = (UserService)myInvokeHandler.getProxy();
proxy.add();
}
}
11、AOP
11.1、AOP理解
1、为什么用aop
1、为了方便
看一个国外很有名的大师说,编程的人都是“懒人”,因为他把自己做的事情都让程序做了。用了aop能让你少写很多代码,这点就够充分了吧。
2、为了更清晰的逻辑
可以让你的业务逻辑去关注自己本身的业务,而不去想一些其他的事情,这些其他的事情包括:安全,事物,日志等。
- 通知(Advice):就是你想要的功能,也就是上面说的 安全,事物,日志等。你给先定义好把,然后在想用的地方用一下。
- 连接点(JoinPoint):就是spring允许你使用通知的地方,那可真就多了,基本每个方法的前,后(两者都有也行),或抛出异常时都可以是连接点,spring只支持方法连接点.其他如aspectJ还可以让你在构造器或属性注入时都行,不过那不是咱关注的,只要记住,和方法有关的前前后后(抛出异常),都是连接点。
- 切入点(Pointcut):上面说的连接点的基础上,来定义切入点,你的一个类里,有15个方法,那就有几十个连接点了对把,但是你并不想在所有方法附近都使用通知(使用叫织入,以后再说),你只想让其中的几个,在调用这几个方法之前,之后或者抛出异常时干点什么,那么就用切点来定义这几个方法,让切点来筛选连接点,选中那几个你想要的方法。
- 切面(Aspect):切面是通知和切入点的结合。现在发现了吧,没连接点什么事情,连接点就是为了让你好理解切点,搞出来的,明白这个概念就行了。通知说明了干什么和什么时候干(什么时候通过方法名中的before,after,around等就能知道),而切入点说明了在哪干(指定到底是哪个方法),这就是一个完整的切面定义。
- 引入(introduction):允许我们向现有的类添加新方法属性。这不就是把切面(也就是新方法属性:通知定义的)用到目标类中吗。
- 目标(target):引入中所提到的目标类,也就是要被通知的对象,也就是真正的业务逻辑,他可以在毫不知情的情况下,被咱们织入切面。而自己专注于业务本身的逻辑。
- 代理(proxy):怎么实现整套aop机制的,都是通过代理,这个一会给细说。
- 织入(weaving):把切面应用到目标对象来创建新的代理对象的过程。有3种方式,spring采用的是运行时,为什么是运行时,后面解释。
关键就是:切点定义了哪些连接点会得到通知
3、我所理解的aop原理
spring用代理类包裹切面,把他们织入到Spring管理的bean中。也就是说代理类伪装成目标类,它会截取对目标类中方法的调用,让调用者对目标类的调用都先变成调用伪装类,伪装类中就先执行了切面,再把调用转发给真正的目标bean。
现在可以自己想一想,怎么搞出来这个伪装类,才不会被调用者发现(过JVM的检查,JAVA是强类型检查,哪里都要检查类型)。
1、实现和目标类相同的接口,我也实现和你一样的接口,反正上层都是接口级别的调用,这样我就伪装成了和目标类一样的类(实现了同一接口,咱是兄弟了),也就逃过了类型检查,到java运行期的时候,利用多态的后期绑定(所以spring采用运行时),伪装类(代理类)就变成了接口的真正实现,而他里面包裹了真实的那个目标类,最后实现具体功能的还是目标类,只不过伪装类在之前干了点事情(写日志,安全检查,事物等)。
这就好比,一个人让你办件事,每次这个时候,你弟弟就会先出来,当然他分不出来了,以为是你,你这个弟弟虽然办不了这事,但是他知道你能办,所以就答应下来了,并且收了点礼物(写日志),收完礼物了,给把事给人家办了啊,所以你弟弟又找你这个哥哥来了,最后把这是办了的还是你自己。但是你自己并不知道你弟弟已经收礼物了,你只是专心把这件事情做好。
顺着这个思路想,要是本身这个类就没实现一个接口呢,你怎么伪装我,我就压根没有机会让你搞出这个双胞胎的弟弟,那么就用第2种代理方式,创建一个目标类的子类,生个儿子,让儿子伪装我
2、生成子类调用,这次用子类来做为伪装类,当然这样也能逃过JVM的强类型检查,我继承的吗,当然查不出来了,子类重写了目标类的所有方法,当然在这些重写的方法中,不仅实现了目标类的功能,还在这些功能之前,实现了一些其他的(写日志,安全检查,事物等)。
这次的对比就是,儿子先从爸爸那把本事都学会了,所有人都找儿子办事情,但是儿子每次办和爸爸同样的事之前,都要收点小礼物(写日志),然后才去办真正的事。当然爸爸是不知道儿子这么干的了。这里就有件事情要说,某些本事是爸爸独有的(final的),儿子学不了,学不了就办不了这件事,办不了这个事情,自然就不能收人家礼了。
4、总结
前一种兄弟模式,spring会使用JDK的java.lang.reflect.Proxy类,它允许Spring动态生成一个新类来实现必要的接口,织入通知,并且把对这些接口的任何调用都转发到目标类。
后一种父子模式,spring使用CGLIB库生成目标类的一个子类,在创建这个子类的时候,spring织入通知,并且把对这个子类的调用委托到目标类。
相比之下,还是兄弟模式好些,他能更好的实现松耦合,尤其在今天都高喊着面向接口编程的情况下,父子模式只是在没有实现接口的时候,也能织入通知,应当做一种例外。
Spring AOP概念理解 (通俗易懂)_qukaiwei的博客-CSDN博客_spring中aop的概念
11.2、AOP在spring中作用
11.3、使用Spring实现AOP
业务逻辑 和 增强的代码分开实现
通过xml 织入关系
public interface UserService {
public Boolean add();
public void delete();
public void update();
public void query();
}
public class UserServiceImpl implements UserService {
@Override
public Boolean add() {
System.out.println("增加了一个用户");
return true;
}
@Override
public void delete() {
System.out.println("删除了一个用户");
}
@Override
public void update() {
System.out.println("更新了一个用户");
}
@Override
public void query() {
System.out.println("查询了一个用户");
}
}
/**
* 前置增强
*/
public class Log implements MethodBeforeAdvice {
/**
*
* @param method 要执行目标对象方法
* @param args 参数
* @param target 目标
* @throws Throwable
*/
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName() +"被执行了");
}
}
/**
* 后置增强
*/
public class AfterLog implements AfterReturningAdvice {
/**
*
* @param returnValue 返回值
* @param method 代理对象的方法
* @param args 方法参数
* @param target 代理对象
* @throws Throwable
*/
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了"+method.getName()+"返回结果为:"+returnValue);
}
}
<?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="designpattern.after.UserServiceImpl"></bean>
<bean id="log" class="designpattern.after.Log"></bean>
<bean id="afterLog" class="designpattern.after.AfterLog"></bean>
<!--配置aop 前提是导入aop约束-->
<aop:config>
<!-- 切入点 expression:表达式,execution(要执行的位置!* * * * *)
修饰符 返回值 类名 方法名 参数 *: UserServiceImpl类中所有方法(..):方法可以有任意参数 -->
<aop:pointcut id="pointcut" expression="execution(* designpattern.after.UserServiceImpl.*(..))"/>
<!-- 执行环绕增强
将log/afterLog 切入到pointcut上,具体到指定的方法-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"></aop:advisor>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"></aop:advisor>
</aop:config>
</beans>
总结:使用切面aspect(类) 中的通知advice (方法) 在切入点pointcut (待增强的方法处)
public class DiyPointcut {
public void after(){
System.out.println("方法之后执行");
}
public void before(){
System.out.println("方法之前执行");
}
}
<bean id="diy" class="designpattern.after.DiyPointcut"></bean>
<aop:config>
<aop:aspect ref="diy">
<aop:pointcut id="pointcut" expression="execution(* designpattern.after.UserServiceImpl.*(..))"/>
<aop:after method="after" pointcut-ref="pointcut"></aop:after>
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
</aop:aspect>
</aop:config>
12、整合mybatis
12.1、mybatis步骤
@Data
public class User {
private int id;
private String name;
private String pwd;
}
<?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>
<typeAliases>
<package name="mybatis.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false"/>
<property name="username" value="rot"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper class="mybatis.mapper.UserMapper"></mapper>
</mappers>
</configuration>
public interface UserMapper {
public List<User> selectUser();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mybatis.mapper.UserMapper">
<select id="selectUser" resultType="user">
select * from mybatis.user;
</select>
</mapper>
public class Mytest {
@Test
public void test() throws IOException {
String resources = "mybatis-config.xml";
InputStream is = Resources.getResourceAsStream(resources);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession(true);
UserMapper userMapper = session.getMapper(UserMapper.class);
List<User> users = userMapper.selectUser();
for (User u:users) {
System.out.println(u);
}
}
}
问题1:org.apache.ibatis.binding.BindingException: Type interface mybatis.mapper.UserMapper is not known to the MapperRegistry.
因为需要在配置文件mybatis-config.xml中引入mapper.xml
<mappers>
<mapper class="mybatis.mapper.UserMapper"></mapper>
</mappers>
问题2:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): mybatis.mapper.UserMapper.selectUser
此时运行后没有在target里生成UserMapper.xml文件
方法:在pom中添加
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
13、Mybatis-Spring整合
Spring万物皆注入
1、创建spring-dao.xml文件:spring来管理datasource、sqlsessionfactory、sqlsession、将mapper.xml、mybatis-config.xml也放到spring容器里。
2、实际上mybatis-config.xml可以省略,但开发中习惯将两项:别名管理alias和设置setting放到mybatis配置文件中。
3、现在可以直接从spring容器拿到sqlsession等。之前需要new。
4、mybatis测试时需要先获取sqlSession在获取Mapper,而spring中直接从容器中拿mapper即可。
5、spring中多个一个实现类,即UserMapper的实现类。因为有了实现类就可以交给spring管理,以bean的形式存在。
6、正常可以使用applicationContext.xml,该文件作为做外层文件,可以包含spring-dao.xml、spring-web.xml等。
13.1、入门
1、添加依赖
2、 创建bean:sqlSessionFactory
<?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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- DataSource:使用spring数据源代替mytabis, druid/c3p0/dbcp
这里使用spring提供的jdbc org.springframework.jdbc.datasource-->
<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/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8"></property>
<property name="username" value="root"></property>
<property name="password" value="12345678"></property>
</bean>
<!-- sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!-- 绑定mybatis配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!-- <property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"></property>-->
<!-- 代替mybatis文件里的 <mappers> 标签 -->
<property name="mapperLocations" value="classpath:mybatis/mapper/UserMapper.xml"></property>
</bean>
<!-- SqlSessionTemplate 就是我们使用的sqlSession,只是名字起的不一样 -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>
</beans>
public class UserMapperImpl implements UserMapper{
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public List<User> selectUser() {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> users = userMapper.selectUser();
return users;
}
}
public class Mytest {
@Test
public void test() throws IOException {
//加载配置文件
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-dao.xml");
UserMapper userMapper = (UserMapper)applicationContext.getBean("userMapperImpl");
List<User> users = userMapper.selectUser();
for (User u:users
) {
System.out.println(u);
}
}
14、SqlSessionDaoSupport
使用继承父类代替sqlSession的注入:
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
@Override
public List<User> selectUser() {
return getSqlSession().getMapper(UserMapper.class).selectUser();
}
}
<bean id="userMapperImpl2" class="mybatis.mapper.UserMapperImpl2">
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
15、声明式事务
编程式事务
声明式事务
以织入的方式配置事务
spring-dao.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: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.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- DataSource:使用spring数据源代替mytabis, druid/c3p0/dbcp
这里使用spring提供的jdbc org.springframework.jdbc.datasource-->
<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/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8"></property>
<property name="username" value="root"></property>
<property name="password" value="12345678"></property>
</bean>
<!-- sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!-- 绑定mybatis配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!-- <property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"></property>-->
<!-- 代替mybatis文件里的 <mappers> 标签 -->
<property name="mapperLocations" value="classpath:mybatis/mapper/UserMapper.xml"></property>
</bean>
<!-- SqlSessionTemplate 就是我们使用的sqlSession,只是名字起的不一样 -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>
<bean id="userMapperImpl" class="mybatis.mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"></property>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 结合AOP 实现事务织入 -->
<tx:advice id="txAdvie" transaction-manager="transactionManager">
<!-- 配置事务通知 -->
<!-- 配置事务传播通知 -->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="query" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置事务接入-->
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* mybatis.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvie" pointcut-ref="txPointcut"></aop:advisor>
</aop:config>
</beans>
保证事务生效
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
@Override
public List<User> selectUser() {
User user = new User(2,"wang","1234");
addUser(user);
deleteUser(2);
return getSqlSession().getMapper(UserMapper.class).selectUser();
}
@Override
public int addUser(User user) {
return getSqlSession().getMapper(UserMapper.class).addUser(user);
}
@Override
public int deleteUser(int id) {
return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mybatis.mapper.UserMapper">
<select id="selectUser" resultType="user">
select * from mybatis.user;
</select>
<insert id="addUser" parameterType="user">
insert into mybatis.user(id,name,pwd) values (#{id},#{name},#{pwd})
</insert>
<delete id="deleteUser" parameterType="int">
deletes from mybatis.user where id = #{id}
</delete>
</mapper>