Spring5学习笔记
一、Spring框架概念
1、Spring是轻量级的开源的JavaEE框架
2、spring可以解决企业应用开发的复杂性
3、spring有两个核心部分:IOC 和Aop
3.1 IOC:控制反转(由IOC来管理对象的创建过程)
3.2 Aop:面向切面(不修改源代码进行功能的增强)
4、spring特点
4.1 方便解耦,简化开发
用IOC来降低耦合性
4.2 Aop编程支持
4.3 方便程序测试
4.4 方便和其他框架进行整合
4.5 方便进行事务操作
4.6 降低API开发难度
二、组成(7个模块)
三、拓展
- 3.1、Spring Boot
- 一个快速开发的脚手架
- 基于SpringBoot可以快速开发单个微服务
- 预定大于配置!
- 3.2 、Spring Cloud Spring Cloud是基于Spring Boot实现的
- 3.3、Spring 和 SpringMvc 是学习 SpringBoot的前提
四、IOC理论推导
- 4.1、推导
- 在以前的业务中,用户的需求更改会影响我们原来的代码,修改代码量十分大,切代价昂贵!我们可以利用一个Set接口,然后来让用户选择需要的业务对象注入。
- 之前,程序是主动创建所需业务对象,控制权在程序猿手上,使用了set接口后,主动权释放给用户,程序创建业务对象变为被动式接受创建。
- 这种思想,从本质上解决了问题,降低了系统耦合性,可以更加专注在业务的实现上
- 4.2、本质
- 控制反转Ioc(Inversion of Control),是一种设计思想,DI(依赖注入)是实现Ioc的一种方式;
- 也有人认为DI只是IOC的另一种说法。没有Ioc的程序,对象创建和对象依赖完全在程序中;
- 当有了ID后,对象的创建转移给第三方;
- 4.3、采用XML方式配置
java里面创建一个对象是通过 类名 对象名 = new 类名()
IOC 则是由bean创建,由class指向类
<?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="hello" class="com.spring.pojo.Hello">
<property name="str" value="spring"></property>
</bean>
</beans>
实例化:
- context表示对象的上下文,()里面则是所需创建的类
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Hello hello=(Hello)context.getBean("hello");
- 4.4、如何配置
- 用户更改需求,不再需要通过程序修改代码,而是自己去修改配置文件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" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userdaoImpl" class="com.spring.dao.UserDaoImpl"></bean>
<bean id="userdaoOrecallImpl" class="com.spring.dao.UserDaoOrecalImpl"></bean>
<bean id="userServerceImpl" class="com.spring.serverve.UserServerceImpl">
<property name="userDao" ref="userdaoOrecallImpl"></property>
</bean>
</beans>
注意:如果依赖注入的不是具体类型的简单类型值,而是某个引用类型,应该用ref
- 4.5、对象的创建过程
三种方式
1)、通过下标赋值创建(有参)对象
<bean id="User" class="com.spring.pojo.User">
<constructor-arg index="0" value="liyiwe">
</constructor-arg>
</bean>
2)、通过类型赋值创建(有参)对象,不推荐,因为只能赋值一个参数
<bean id="User" class="com.spring.pojo.User">
<constructor-arg type="java.lang.String" value="zzz">
</constructor-arg>
</bean>
3)、通过参数名创建(有参)对象
<bean id="User" class="com.spring.pojo.User">
<constructor-arg name="name" value="sss">
</constructor-arg>
</bean>
注意:其实在bean创建的时候对象就已经创建,也就是配置xml的时候就创建了对象。
五、spring配置
- 5.1、别名
如果添加了别名,我们也可以通过别名获取这个对象
<alias name="User" alias="BUser"></alias>
- 5.2、Bean配置
1) name(相当于别名,可以同时取多个,用逗号分或者分号开即可)
<bean id="User" class="com.spring.pojo.User" name="user1">
<constructor-arg name="name" value="sss">
</constructor-arg>
</bean>
- 5.3、import
这个import一般用在团队开发,就是有多个人员在同时写多个bean时,可以用以下代码实现将多个bean合到一个bean里面,即aoolicationcontext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="beans1.xml"></import>
<import resource="beans.xml"></import>
</beans>
注意:如果导入的bean的id相同,后导入的bean会先将先导入的bean覆盖,并且会继承它的别名。
六、DI依赖注入
- 6.1 构造器注入
<!-- p相当于property-->
<bean id="user" class="com.spring.pojo.User" p:name="请i将" p:age="18"></bean>
<!-- c相当于构造器注入,所以类必须有构造函数-->
<bean id="user2" class="com.spring.pojo.User" c:name="sss" c:age="18"></bean>
- 6.2 set注入
- 依赖注入
- 依赖:bean对象的创建依赖于容器
- 注入:bean对象中的所有属性,由容器注入
- 环境搭建
<!--导入jar包-->
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.9</version>
</dependency>
</dependencies>
- 实体类
public class Address {
private String address;
public class Student{
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
- bean.xml配置文件
<bean id="address" class="com.spring.pojo.Address">
<property name="address" value="请将的家"></property>
</bean>
<bean id="student" class="com.spring.pojo.Student">
<!-- 普通值注入-->
<property name="name" value="qingjiang"></property>
<!-- bean注入-->
<property name="address" ref="address"></property>
<!-- 数组注入-->
<property name="books">
<array>
<value>红楼梦</value>
<value>水浒传</value>
<value>三国演义</value>
</array>
</property>
<!-- list注入-->
<property name="hobbys">
<list>
<value>听歌</value>
<value>敲代码</value>
</list>
</property>
<!-- map注入-->
<property name="card">
<map>
<entry key="身份证" value="123123123"></entry>
<entry key="银行卡" value="sdfasdfasd"></entry>
</map>
</property>
<!-- set注入-->
<property name="games">
<set>
<value>LOL</value>
<value>BOB</value>
</set>
</property>
<!-- null注入-->
<property name="wife">
null></null>
</property>
<!-- props注入-->
<property name="info">
<props>
<prop key="性别">男</prop>
<prop key="年龄">18</prop>
</props>
</property>
</bean>
- 测试对象
public class Mytest {
public static void main(String[] args) {
ApplicationContext context =new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.toString());}}
- 6.3 拓展
P命名空间和C命名空间
<?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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- p相当于property-->
<bean id="user" class="com.spring.pojo.User" p:name="请i将" p:age="18"> </bean>
<!-- c相当于构造器注入,所以类必须有构造函数-->
<bean id="user2" class="com.spring.pojo.User" c:name="sss" c:age="18"></bean>
</beans>
注意:P命名空间和C命名空间不能直接使用,需要导入相应的xml约束!
xmlns:c="http://www.springframework.org/schema/c"
- 测试
public class Mytest {
ApplicationContext context =new ClassPathXmlApplicationContext("userbean.xml");
User user=context.getBean("user2", User.class);
System.out.println(user.toString());
}
}
七、bean的作用域
Scope Description
singleton (默认)将每个 Spring IoC 容器的单个 bean 定义范围限定为单个对象实例。
prototype 将单个 bean 定义的作用域限定为任意数量的对象实例。
request 将单个 bean 定义的范围限定为单个 HTTP 请求的生命周期。也就是说,每个 HTTP 请求都有一个在单个 bean 定义后面创建的 bean 实例。仅在可感知网络的 Spring ApplicationContext中有效。
session 将单个 bean 定义的范围限定为 HTTP Session的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
application 将单个 bean 定义的范围限定为ServletContext的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
websocket 将单个 bean 定义的范围限定为WebSocket的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
- 7.1 单例模式(Spring默认机制) 所有创建的对象都指向同一个bean对象
<bean id="user11" class="com.spring.pojo.User" scope="singleton"></bean>
- 7.2 原型模式: 每次从容器中get的时候,都会产生一个新对象
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
- 7.3 其余的erquest、session、application这些个作用域只有在web开发中才能使用!
八、Bean的自动装配
- 自动装配式Spring满足bean依赖的一种方式!
- Spring会在上下文中自动寻找,并自动给bean装配属性!
- 在Spring中有三种装配方式
- 1)在xml中显示的配置
<bean id="cat" class="com.spring.pojo.Cat"></bean>
<bean id="dog" class="com.spring.pojo.Dog"></bean>
<bean id="people" class="com.spring.pojo.People">
<property name="name" value="qing"></property>
<property name="cat" ref="cat"></property>
<property name="dog" ref="dog"></property>
</bean>
- 2)在java中显示配置
- 3)隐式的自动装配bean 重要
- 8.1 测试
环境搭建:一个人两个宠物 - 8.2 ByName自动装配
<!-- byname会根据bean的id,自动通过类里面的set方法去寻找对应的对象注入-->
<bean id="people" class="com.spring.pojo.People" autowire="byName">
</bean>
8.3 ByType自动装配
<!-- bytype会在容器上下文中查找,和自己对象属性类型相同的bean-->
<bean id="people" class="com.spring.pojo.People" autowire="byType">
</bean>
注意:
byname的时候,需要保证所有的beanid唯一,并且保证这个id和需要自动注入的属性set方法里面的一致
bytype的时候,同样需要保证所有的class唯一,并且保证这个class和需要自动注入的属性set方法里面的一致
- 8.4 使用注解实现自动装配
jdk1.5支持的注解,Spring2.5就支持注解了!
要使用注解须知:
- **1、导入约束
<artifactId>spring-05-autowrite</artifactId>
- 2、配置注解的支持**
- @Autowired
- 直接在属性上使用即可! 也可以在set方式上使用!
- 使用Autowired我们可以不写set方法,前提是你这个自动装配的属性在IOC(Spring)容器上存在,切符合bytype命名规则(前提是唯一)!
public class People {
@Autowired(@reuqierd = false)
private Dog dog;
@Autowired
private Cat cat;
- 假如有多个相同类的bean,可以在使用注解时用如下的@Qualifier设置value来指定的特定beanid,不然就会报错
@Autowired
@Qualifier(value="dog222")
- 拓展:
java也有原生的自动装配,同样是要符合byname或者bytype的命名规则(前提是唯一)
@Resource
private Cat cat;
有多个相同类型的beanid或者类型是,可以使用name来指定特定的beanid
@Resource(name='cat22')
private Cat cat;
- 小结:
- @Resource 和 Autowired 的区别:
- ~都是自动装配的,都可以放在属性字段上
- ~@Autowired通过byname的方式实现
- ~@Resource默认通过byname的方式实现,如果找不到可以通过bytype的方式实现,都找不到就报错!
九、使用注解开发
bean
- 属性如何注入
//组件,相当于在xml那边的<bean id='user',class =,,,>
@Component
public class User {
private String name;
- 衍生的注解
- @Component有几个衍生的注解,我们在web开发中,会按照mvc三层架构分层!
- dao:@Repository
- service: @Service
- controller: @Controller
这四个注解的功能都是一样的,都是代表某个类注册到spring中,自动装配bean
自动装配
@Autowired : 自动装配通过类型,名字
@Nullable :字段标记了这个注解,说明这个字段可以为null
@Resource :自动装配通过名字,类型。
- 作用域
@Component
@Scope("prototype")
public class User{}
- 小结
- xml与注解:
- xml更加万能,适用于任何场合!维护简单方便
- 注解不是自己类使用不了,维护相对复杂!
- xm与注解最佳实践:
- xml用来管理bean
- 注解只负责属性的注入
注意:我们在使用的过程中,只需要注意一个问题,那就是必须让注解生效,需要开启注解
<!--开启注解-->
<context:annotation-config/>
<context:component-scan base-package="com.spring"></context:component-scan>
10、使用java的方式配置Spring
- 实体类:
@Component
public class User {
@Value("sss")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- 配置类
@Configuration
//Configuration本身也是一个Compotement,会被spring容器托管,所以也可以使用Compotement的一些东西
@Import(SpringConfig2.class)
@ComponentScan("com.spring")
//下面这段类似于<beans> <bean id=user class="com.spring.pojo.User"</beans>
public class SpringConfig {
@Bean
public User user(){
return new User();
}
}
- 测试类:
public class MyTest {
public static void main(String[] args) {
//如果完全使用配置类来做,就只能同构AnnotationConfigApplicationContext去做
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
User user=context.getBean("user",User.class);
System.out.println(user.getName());
}
}
11、代理模式
- 代理模式是SpringAOP的底层
- 代理模式分类:
- 静态代理
- 动态代理 - 11.1 静态代理
角色分析:
抽象角色:一般会使用接口或者抽象类来解决
真实角色:被代理的角色
代理角色:代理真实角色的角色,代理后,我们一般会做一些附属操作
客户:访问代理角色的角色
代理步骤:
1、接口:
2、真实角色:
3、代理角色:
4、访问角色:
代理模式的好处:
可以使真实角色的操作更加纯粹!不用去关注一些公共的业务!
公共也就交给代理角色!实现了业务的分工!
公共业务发生拓展的时候,方便集中管理!
缺点:
一个真实角色就会产生一个代理角色,代码里翻倍!
- 11.2 动态代理
动态代理和静态代理角色一样
动态代理的代理类是动态生成的,不是我们写好的
动态代理分为两大类:
基于接口实现的动态代理:
基于接口-JKD 动态代理
基于类:cglib
java字节码实现:javasist
基于
需要了解两个类: Proxy:代理,InvocationHandler:调用处理程序
动态代理的好处:
可以使真实角色的操作更加纯粹!不用去关注一些公共的业务!
公共也就交给代理角色!实现了业务的分工!
公共业务发生拓展的时候,方便集中管理!
一个动态代理类代理的是一个接口,一般就是对应的一类
一个动态代理类可以代理多个类,只要是实现
12、AOP
- 12.1 什么是APO?
- AOP(Aspect Oriented Programming) 意味:面向切面编程,通过预编译方式和运行期间动
- 态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是
- Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部
- 分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
- 12.2 Aop在Spring中的作用
提供声明式事务:允许用户自定义切面
SpringAop中,通过Adivice定义横切逻辑,Spring中支持5中类型的Advice:
- 11.3 使用Spring实现AOP
- 重点:使用AOP织入,需要导入一个依赖包
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
- 方式一:使用Spring的API接口
- 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">
<bean id="log" class="com.spring.log.Log"></bean>
<bean id="afterlog" class="com.spring.log.AfterLog"></bean>
<bean id="userService" class="com.spring.service.UserServiceImpl"></bean>
<!--配置方式一,使用原生的API配置-->
<!--配置AOP,要配置AOP的约束-->
<aop:config>
<!--切入点,expression表达式 execution 切入位置,或者说代理位置-->
<aop:pointcut id="pointcut" expression="execution(* com.spring.service.UserServiceImpl.*(..))"/>
<!--执行环绕增加,理解为生成代理类-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"></aop:advisor>
<aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"></aop:advisor>
/aop:config>
</beans>
- 接口:
public interface UserService {
public abstract void add();
public abstract void delete();
public abstract void update();
public abstract void query();
}
- 真实角色:
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("查找了一个用户");
}
}
- 日志类:
public class Log implements MethodBeforeAdvice {
//method 执行的方法
//args 参数
//target 目标
@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 {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"执行了"+method.getName()+"方法,"+"返回结果:"+returnValue);
}
}
- xml配置
<bean id="log" class="com.spring.log.Log"></bean>
<bean id="afterlog" class="com.spring.log.AfterLog"></bean>
<bean id="userService" class="com.spring.service.UserServiceImpl"></bean>
<!--配置方式一,使用原生的API配置-->
<!--配置AOP,要配置AOP的约束-->
<aop:config>
<!--切入点,expression表达式 execution 切入位置,或者说代理位置-->
<aop:pointcut id="pointcut" expression="execution(* com.spring.service.UserServiceImpl.*(..))"/>
<!--执行环绕增加,理解为生成代理类-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"></aop:advisor>
<aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"></aop:advisor>
</aop:config>
- 测试类:
public class Mytest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理的是接口
UserService userService = (UserService) context.getBean("userService");
userService.add();
}
}
- 方式二:自定义AOP
跟方式一类似,就是在日志和xml改变,将日志全部集成一个自定义类
- 自定义类:
public class Diy {
private void before(){
System.out.println("=====方法执行前=====");
}
private void after(){
System.out.println("=====方法执行后=====");
}
}
- 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">
<bean id="log" class="com.spring.log.Log"></bean>
<bean id="afterlog" class="com.spring.log.AfterLog"></bean>
<bean id="userService" class="com.spring.service.UserServiceImpl"></bean>
<bean id="diy" class="com.spring.diy.Diy"></bean>
<!--配置方式一,使用原生的API配置-->
<!--配置AOP,要配置AOP的约束-->
<aop:config>
<!--切入面-->
<aop:aspect id="diy" ref="diy">
<!--切入点,expression表达式 execution 切入位置,或者说代理位置-->
<aop:pointcut id="pointcut" expression="execution(* com.spring.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
<aop:after method="after" pointcut-ref="pointcut"></aop:after>
</aop:aspect>
</aop:config>
</beans>
- 方式三:使用注解
- diy类:
@Aspect
public class AnnotationPoincut {
@Before("execution(* com.spring.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("===方法执行前===");
}
@After("execution(* com.spring.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("===方法执行后===");
}
@Around("execution(* com.spring.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("===环绕前===");
Signature signature = joinPoint.getSignature();//获得签名
System.out.println("signature"+signature);
Object proceed = joinPoint.proceed();
System.out.println("===环绕后===");
}
}
- xml配置:
<bean id="log" class="com.spring.log.Log"></bean>
<bean id="afterlog" class="com.spring.log.AfterLog"></bean>
<bean id="userService" class="com.spring.service.UserServiceImpl"></bean>
<bean id="diy" class="com.spring.diy.Diy"></bean>
<!--配置方式,注解-->
<bean id="annotationpoincut" class="com.spring.diy.AnnotationPoincut"></bean>
<!--开启注解-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
- 测试类
12、整合Mybatis
- 12.1步骤:
- 导入相关jar包
- junit
- mybatis
- msql数据库
- spring
- aop
- mybatis-spring【new】
- 编写配置文件
- 测试
- 12.2 整合Mybatis
- 环境搭建
<properties>
<maven.compiler.source>10</maven.compiler.source>
<maven.compiler.target>10</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.9</version>
</dependency>
<!-- mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<!-- mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!-- juit依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
- 实体类
@Alias("User")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
}
- 接口类
public interface UserMapper {
List<User> getUserlist();
}
- 实现类
public class UserMapperImpl implements UserMapper {
//这里的SqlSessionTemplate相当于Mybatis的Sqlseesion
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public List<User> getUserlist() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.getUserlist();
}
}
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {
@Override
public List<User> getUserlist() {
SqlSession sqlSession=getSqlSession();
return sqlSession.getMapper(UserMapper.class).getUserlist();
}
}
- 数据库xml实现
<?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.spring.dao.UserMapper">
<select id="getUserlist" resultType="User" useCache="true">
select * from user
</select>
</mapper>
- 数据库核心配置文件
<?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代表mybatis核心配置-->
<configuration>
<!-- <typeAliases>-->
<!-- <typeAlias alias="User" type="com.spring.pojo.User"></typeAlias>-->
<!-- </typeAliases>-->
<!-- 开启驼峰命名-->
<!--因为整合了spring,所以数据源由spring-dao文件配置,这里主要设置别名扫描,mapper扫描和settring设置-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<package name="com.spring.pojo"/>
</typeAliases>
<mappers>
<package name="com.spring.dao"/>
</mappers>
</configuration>
- spring-dao配置文件,其实就是applicationconfig配置文件
<?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">
<!--datasource-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!--SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--绑定mybatis-config.xml-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
</bean>
<!--方式一,通过SqlSession注入实现-->
<!--SqlsessionTemplate就是我们使用的sqlsession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>
<bean id="UserMapperImpl" class="com.spring.dao.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"></property>
</bean>
<!--方式二,通过继承SqlSessionDatasupport自动获接得Sqlsession-->
<bean id="UserMapperImpl2" class="com.spring.dao.UserMapperImpl2">
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
</beans>
- 测试类
ublic class Mytest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
UserMapper userMapper = context.getBean("UserMapperImpl",UserMapper.class);
for (User user : userMapper.getUserlist()) {
System.out.println(user);
}
}
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
UserMapper userMapper = context.getBean("UserMapperImpl2",UserMapper.class);
for (User user : userMapper.getUserlist()) {
System.out.println(user);
}
}
}
13、声明式事务
-13.1 回顾事务
- 事务的ACID原则
- 原子性
- 一致性
- 隔离性
- 持久性
- 13.2 spring中的事务管理
- 声明式事务
- 编程式事务
- 环境搭建:
- 导包
- 实体类
- 接口类
public interface UserMapper {
List<User> getUserlist();
int update(User user);
int add(User user);
int delete(int id);
}
```
- 实现类
public class UserMapperImpl implements UserMapper {
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public List<User> getUserlist() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> list=mapper.getUserlist();
mapper.add(new User(10,"123","123"));
mapper.add(new User(1,"123","123"));
return list;
}
@Override
public int update(User user) {
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
int n=mapper.update(user);
if (n>0)
return 1;
return 0;
}
@Override
public int add(User user) {
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
int n=mapper.add(user);
if (n>0)
return 1;
return 0;
}
@Override
public int delete(int id) {
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
int n=mapper.delete(id);
if (n>0)
return 1;
return 0;
}
}
- mapper.xml文件
<?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.spring.dao.UserMapper">
<select id="getUserlist" resultType="User" useCache="true">
select * from user
</select>
<update id="update" parameterType="User">
update user set name=#{name},pwd=#{pwd} where id=#{id}
</update>
<delete id="delete" parameterType="int">
delete from user where id=#{id}
</delete>
<insert id="add" parameterType="User">
insert into user (id,name,pwd) values (#{id},#{name},#{pwd})
</insert>
</mapper>
- 数据库核心配置文件
<?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代表mybatis核心配置-->
<configuration>
<!-- <typeAliases>-->
<!-- <typeAlias alias="User" type="com.spring.pojo.User"></typeAlias>-->
<!-- </typeAliases>-->
<!-- 开启驼峰命名-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<package name="com.spring.pojo"/>
</typeAliases>
<mappers>
<package name="com.spring.dao"/>
</mappers>
</configuration>
- 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-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!--SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--绑定mybatis-config.xml-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
</bean>
<!--方式一,通过SqlSession注入实现-->
<!--SqlsessionTemplate就是我们使用的sqlsession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>
<bean id="UserMapperImpl" class="com.spring.dao.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"></property>
</bean>
<!--方式二,通过继承SqlSessionDatasupport自动获接得Sqlsession-->
<bean id="UserMapperImpl2" class="com.spring.dao.UserMapperImpl2">
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
<!--开启事务,配置事务数据源-->
<bean id="transactionManage" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务-->
<tx:advice id="txAdvice" transaction-manager="transactionManage">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--切面织入事务-->
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.spring.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"></aop:advisor>
</aop:config>
</beans>
- 测试类:
public class Mytest {
@Test
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
UserMapper mapper = (UserMapper) context.getBean("UserMapperImpl");
for (User user : mapper.getUserlist()) {
System.out.println(user);
}
}
}