Spring学习笔记
1.spring
◆目的:解决企业应用开发的复杂性
◆功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
◆范围:任何Java应用
Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。
下载地址:https://repo.spring.io/release/org/springframework/spring/
1.2.准备
1.创建项目
2导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
2.IOC设计思想(控制反转)
***自己的理解不深,可能有些方面理解错误 **
●**谁控制谁,控制什么:**传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?,当然是IoC 容器控制了对象;控制什么?,那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
- 为何是反转:没有 IoC 的时候我们都是在自己对象中主动去创建被依赖的对象,这是正转。但是有了 IoC 后,所依赖的对象直接由 IoC 容器创建后注入到被注入的对象中,依赖的对象由原来的主动获取变成被动接受,所以是反转。
- 哪些方面反转了:所依赖对象的获取被反转了。
比如
数据访问层(dao)中:各种对象(各种信息,用于客户需求),如下假设: 类1,类2中便是各种用户的需求,等待客户的服务人员(员工,程序员,…)拿出为客户服务,即各种业务
/*
userdao接口
*/
public interface userdao {
void getuserdao();
}
=====================================================================
/*
各种类,继承于userdao并需要实现其方法
*/
//类1:
public class userImpote implements userdao {
public void getuserdao() {
System.out.println("获取第一个用户");
}
}
----------------------------------------------------------------
//类2
public class userImpote1 implements userdao {
@Override
public void getuserdao() {
System.out.println("获取第二个用户");
}
}
业务层(service)中:类1中客户如果要获取信息(第一用户或者第二用户),每次都要从新nwe个对象,即( userdao user=new userImpote1(););;类2(IOC思想)中则是IoC是有专门一个容器来创建这些对象,此容器中有各种依赖对象,由原来的主动new对象变成现在的被动接受依赖对象(对象全部存放在
private userdao user;
public void getuserdao(userdao user) {
this.user=user;
}
)因此控制反转了,即由Ioc容器来控制对 象的创建,依赖的对象由原来的主动获取变成被动接受。
/*
userservice接口
*/
public interface userservice {
void getuserdao1();
}
================================================================
/*
类1:需要自己主动获取数据 new userImpote1,
*/
public class userserviceImpote implements userservice{
userdao user=new userImpote1();
@Override
public void getuserdao1() {
user.getuserdao();
}
}
----------------------------------------------
/*
类2:IOC
*/
public class userserviceImpote implements userservice{
private userdao user;
public void getuserdao(userdao user) {
this.user=user;
}
@Override
public void getuserdao1() {
user.getuserdao();
}
}
测试(用户):测试1中用户要获取dao层信息,每次都需要service层中从新new个对象;
测试2中用户要获取dao层信息,只需要service层中类2自动创建对应的对象
//测试1
public class mytest {
public static void main(String[] args) {
userservice users=new userserviceImpote();
users.getuserdao1();
}
}
-----------------------------------------
//测试2
public class mytest {
public static void main(String[] args) {
userservice users=new userserviceImpote();
((userserviceImpote) users).getuserdao(new userImpote1());
users.getuserdao1();
}
}
3.利用spring配置文件获取
spring配置文件
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
以下是创建对象,userImpote userImpote=new userImpote();
id=变量名,xlass= nwe userImpote
-->
<bean id="userImpote" class="com.gongfang.dao.userImpote"/>
<bean id="userImpote1" class="com.gongfang.dao.userImpote1"/>
<bean id="userserviceImpote" class="com.gongfang.service.userserviceImpote">
<!--
下面通过setUser注入方法获取 userImpote
private userdao user;
public void setUser(userdao user) {
this.user=user;
}
-->
<property name="user" ref="userImpote"/>
</bean>
</beans>
测试:
public class mytest1 {
public static void main(String[] args) {
//获取ApplicationContext对象拿到容器,获得spring配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("sp.xml");
//通过获得配置文件中的ben获得 userserviceImpote方法,此方法通过set注入对象
userserviceImpote userserviceImpote= (userserviceImpote) context.getBean("userserviceImpote");
userserviceImpote.getuserdao1();
}
}
*注意:spring官方是通过ApplicationContext对象拿到容器
ApplicationContext context = new ClassPathXmlApplicationContext("spring配置文件");
4.ioc创建对象方式
constructor-arg:通过构造函数注入。 则property:通过setxx方法注入。
-
通过set方法注入
<bean id="hello" class="com.gongfang.dao.helloword"> <property name="str" value="HelloSpring"/> </bean>
-
默认使用无参构造创建对象
-
使用有参构造函数创建对象
-
使用参数名赋值:
<bean id="hello" class="com.gongfang.dao.helloword"> <constructor-arg name="str" value="HelloSpring"/> </bean>
-
使用索引下标赋值:
<bean id="hello" class="com.gongfang.dao.helloword"> <constructor-arg index="0" value="HelloSpring"/> </bean>
-
类型赋值:
<bean id="hello" class="com.gongfang.dao.helloword"> <constructor-arg type="java.lang.String" value="HelloSpring"/> </bean>
-
5.Sping配置(applicationContext1.xml)
5.1.别名
<bean id="hello" class="com.gongfang.dao.helloword">
<constructor-arg index="0" value="HelloSpring"/>
</bean>
<!--别名,可以通过别名获取-->
<alias name="hello" alias="myhello"/>
5.2.ben配置
<!--
Helloword hello = new helloword();
id="变量名hello",class="new helloword()",name="别名(此别名比 alias 强大,可以设置多个别名能用 ", 空格 ;"区分开)"
-->
<bean id="hello" class="com.gongfang.dao.helloword" name="a,b c;d">
<!-- constructor-arg 根据构造函数注入 ,name ="helloword中的变量名",value="值" -->
<constructor-arg name="str" value="HelloSpring"/>
<!--
property 根据set注入
< property name="str" value="HelloSpring"/>
-->
</bean>
5.3.import
合并多个人的配置文件为一个
<import resource="applicationContext1.xml"/>
<import resource="applicationContext2.xml"/>
<import resource="applicationContext3.xml"/>
6.依赖注入(DI)
6.1.构造器注入
6.2.属性注入
string ,string[] ,List ,map ,set ,……
官方文档:(7.4.2)
https://www.docs4dev.com/docs/zh/spring-framework/4.3.21.RELEASE/reference/beans.html#beans-collection-elements
6.1.p,c 命令注入(扩展)
官方解释(7.4.2)
https://www.docs4dev.com/docs/zh/spring-framework/4.3.21.RELEASE/reference/beans.html#beans-p-namespace
注意:p:set属性来注入的;c:构造器来注入的,所以对象需要导入有参和无参构造器;都需要导入各自xml约束
<!--约束-->
xmlns:p="http://www.springframework.org/schema/p"
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="hello" class="com.gongfang.dao.helloword1" p:name="宋江" p:age="10"/>
</beans>
2.
<!--约束-->
xmlns:c="http://www.springframework.org/schema/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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
<bean id="hello" class="com.gongfang.dao.helloword1" p:name="宋江" p:age="18"/>
-->
<bean id="hello" class="com.gongfang.dao.helloword2" c:name="宋江" c:age="18"/>
</beans>
7.自动装配
1.byname: 查找容器中和自己对象set后面对应的ben,id=“对象set后面的值”
autowire="byName"
- autowire: 查找容器中和自己对象属性相同的ben,只需要class=""一致
autowire="byType"
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"
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">
<context:annotation-config/>
</beans>
-
**@Autowired ????*在属性和set上都可以使用,可以不用编写set方法,Autowired默认先按byType,如果发现找到多个bean,则,又按照byName方式比对,如果还有多个,则报出异常。
public class pople { @Autowired private miao miao; @Autowired @Nullable private dog dog; private String name;
-
@Nullable: 被标记的字段可以为null
-
@Qualifier(value =“xxx”): 当@Autowired 比较复杂,无法通过一个@Autowired 来装配完成时可以使用此注解来配合@Autowired 使用,指定一个唯一的bean对象
@Autowired
@Qualifier(value ="miao11")
private miao miao;
<bean id="miao11" class="miao"/>
<bean id="miao" class="miao"/>
- @Resource: 默认按 byName自动注入,如果找不到再按byType找bean,如果还是找不到则抛异常,无论按byName还是byType如果找到多个,则抛异常。
public class pople {
@Resource
private miao miao;
@Resource
private dog dog;
private String name;
- ……
9.使用注解开发
参考博客:https://www.cnblogs.com/hdfzj/articles/12401077.html
1.倒入支持
<?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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
指定要扫描的包
<context:component-scan base-package="包"/>
2.注解
属性注入:
-
@Component: 标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean。
-
**@component:**相当于
<property name="" value=""/>
-
衍生注解:web中按三层架构分层
- dao @Repository
- service @service
- controller @controller
功能相同,按照类注册bean
9.2.@Configuration
其中:@Configuration = spring配置文件;
@Bean及下代码 等价于:
<bean id="xxx" class="xxx">
...
</bean>
@Component 等价于
<property name="xxx" value="xxx"/>
@Value("") 等价于下面 value=""
<property name="str" value="HelloSpring"/>
@Component
public class helloword3 {
private String name;
public String getName() {
return name;
}
@Value("孙悟空")
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "helloword3{" +
"name='" + name + '\'' +
'}';
}
}
@Configuration
public class hello3user {
@Bean
public helloword3 getuser(){
return new helloword3();
}
}
测试
@Test
public <hellword3> void testhello3(){
ApplicationContext user = new AnnotationConfigApplicationContext(hello3user.class);
hellword3 getuser = (hellword3) user.getBean("getuser");
System.out.println(getuser);
}
10.代理模式
10.1静态代理
分析:
抽象角色:一般使用接口或抽象类解决
真实角色:被代理的角色
代理角色:代理真实角色
客户:访问代理对象的人
简单案例:租房
抽象角色(房):一个租房接口,用于他人租房
//租房
public interface fang {
public void zufang();
}
真是角色(房东):房东要租房,实现其租房接口
//房东要租房
public class fangdong implements fang {
@Override
public void zufang() {
System.out.println("我要出租房");
}
}
代理角色(中介):房东只想租房,把租房繁琐的事交给中介,中介帮助客户完成租房,从中抽取一定的报酬,(代码:中介需要拿到房东,并拿到租房,才能去租房)
//中介
//要租房就要实现租房接口
public class zhongjie implements fang{
//拿到房东(没有房东就没有租房的任务)
private fangdong fangdong;
public zhongjie() {
}
public zhongjie(com.gongfang.demo01.fangdong fangdong) {
this.fangdong = fangdong;
}
@Override
public void zufang() {
//房东租房
fangdong.zufang();
}
}
客户(要租房人):
public class my {
public static void main(String[] args) {
//房东要租房
fangdong fangdong=new fangdong();
//找中介,让中介帮房东租房
zhongjie zhongjie=new zhongjie(fangdong);
//自己要租房直接面对中介
zhongjie.zufang();
}
}
结果:
优点:
1.使操作业务时不用关注一些公共业务
2.公共业务交给代理,使业务分工
3.方便集中管理
缺点:
一个公共业务就会产生一个代理,使代码量容易增加,降低了开发效率
10.2.动态代理
动态代理,代理接口
1.接口
2.真实用户(房东)
3.自动生成代理类(要实现 InvocationHandler 接口)
//此类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
//代理的接口
// private Object teager;
private fang fang;
// public void setTeager(Object teager) {
// this.teager = teager;
// }
public void setFang(com.gongfang.demo02.fang fang) {
this.fang = fang;
}
//生成得到代理类
// public Object getProxy(){
// return Proxy.newProxyInstance(this.getClass().getClassLoader(),teager.getClass().getInterfaces(),this);
// }
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),fang.getClass().getInterfaces(),this);
}
//处理代理实例并返回结果
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Object invoke = method.invoke(teager, args);
// return invoke;
// }
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = method.invoke(fang, args);
return invoke;
}
}
4.客户
public class client {
public static void main(String[] args) {
//真实角色
fangdong fangdong=new fangdong();
//代理角色
ProxyInvocationHandler pir = new ProxyInvocationHandler();
pir.setFang(fangdong);
//动态代理代理的是接口,所以返回类型需是接口
fang proxy = (fang) pir.getProxy();
proxy.zufang();
}
}
11.spring AOP(面向切面编程)
思想:面向切面编程
AOP 领域中的特性术语:
- 通知(Advice): AOP 框架中的增强处理。通知描述了切面何时执行以及如何执行增强处理。
- 连接点(join point): 连接点表示应用执行过程中能够插入切面的一个点,这个点可以是方法的调用、异常的抛出。在 Spring AOP 中,连接点总是方法的调用。
- 切点(PointCut): 可以插入增强处理的连接点。
- 切面(Aspect): 切面是通知和切点的结合。
- 引入(Introduction):引入允许我们向现有的类添加新的方法或者属性。
- 织入(Weaving): 将增强处理添加到目标对象中,并创建一个被增强的对象,这个过程就是织入。
11.1.准备
1.导入依赖
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
2.导入AOP约束,sping配置文件
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
3.接口及角色
public interface user {
void add() ;
void delet();
void inster();
void select();
}
================================================================
public class user1 implements user {
@Override
public void add() {
System.out.println("增加了个用户");
}
@Override
public void delet() {
System.out.println("删除了个用户");
}
@Override
public void inster() {
System.out.println("改变了个用户");
}
@Override
public void select() {
System.out.println("查询了个用户");
}
}
4.日志
//前置日志
public class Log implements MethodBeforeAdvice {
//method 要执行的目标方法
//objects 参数
//o 执行目标对象
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了");
}
}
===========================================================================
//后置日志
public class Log1 implements AfterReturningAdvice {
//o 返回值
//o1 目标对象
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("执行了"+method.getName()+"方法,返回结果为"+o);
}
}
11.2.AOP实现方法1
- 使用API接口
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注册bean-->
<bean id="user1" class="com.gongfang.dao.user1"/>
<bean id="log" class="com.gongfang.LOG.Log"/>
<bean id="log1" class="com.gongfang.LOG.Log1"/>
<!--配置AOP ,导入AOP约束-->
<aop:config>
<!--切入点 , execution(要执行的位置)-->
<aop:pointcut id="pointcut" expression="execution(* com.gongfang.dao.user1.* (..))"/>
<!--执行环绕增加-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="log1" pointcut-ref="pointcut"/>
</aop:config>
</beans>
测试:
public class testaop {
public static void main(String[] args) {
ApplicationContext test = new ClassPathXmlApplicationContext("applicationContext1.xml");
//动态代理代理的是接口,所以返回类型需是接口
user user = (user) test.getBean("user1");
user.add();
}
}
结果:
11.3.AOP实现方法2
- 自定义方法
1.随便写个类,写些方法
public class rest {
public void befer(){
System.out.println("方法执行前");
}
public void arfer(){
System.out.println("方法执行后");
}
}
2.spring配置文件
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注册bean-->
<bean id="user1" class="com.gongfang.dao.user1"/>
<bean id="log" class="com.gongfang.LOG.Log"/>
<bean id="log1" class="com.gongfang.LOG.Log1"/>
<!-- 方式二:自定义类-->
<!--注册bean-->
<bean id="res" class="com.gongfang.rest.rest"/>
<aop:config>
<!-- 自定义切面,ref:要引用的类-->
<aop:aspect ref="res">
<!--切入点-->
<aop:pointcut id="pointcut" expression="execution(* com.gongfang.dao.user1.*(..))"/>
<!--通知-->
<aop:before method="befer" pointcut-ref="pointcut"/>
<aop:after method="arfer" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>
11.4.AOP实现方法3
- 使用注解实现
1、开启aop注解的自动代理
< aop:aspectj-autoproxy/>
2.指定要扫描的包
<context:component-scan base-package=“com.gongfang”/>
3、 AspectJ的AOP的注解:
-
@Component: 标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean
-
@Aspect:定义切面类的注解
-
@Pointcut:定义切入点的注解
-
通知类型:
@Before:前置通知
@AfterReturing:后置通知
@Around:环绕通知
@After:最终通知
@AfterThrowing:异常抛出通知.
实验:
接口
public interface user {
void add() ;
void delet();
void inster();
void select();
}
目标实现类接口
// 标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean。
@Component
public class user1 implements user {
@Override
public void add() {
System.out.println("增加了个用户");
}
@Override
public void delet() {
System.out.println("删除了个用户");
}
@Override
public void inster() {
System.out.println("改变了个用户");
}
@Override
public void select() {
System.out.println("查询了个用户");
}
}
applicationContext1.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 指定要扫描的包-->
<context:component-scan base-package="com.gongfang"/>
<!--开启注解-->
<aop:aspectj-autoproxy/>
</beans>
日志,切面类
// 标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean。
@Component
//@Aspect 切面类
@Aspect
public class log {
// @Before 通知 ;execution()切入点
@Before("execution(* com.gongfang.dao.user1.*(..))")
public void befor(){
System.out.println("方法执行前");
}
@After("execution(* com.gongfang.dao.user1.*(..))")
public void aftre(){
System.out.println("方法执行后");
}
}
12.整合mybatis
**官方中文文档:**http://mybatis.org/spring/zh/getting-started.html
1,什么是 MyBatis-Spring?
MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession
并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException
。 最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。
注意:
MyBatis-Spring 需要以下版本:
MyBatis-Spring | MyBatis | Spring Framework | Spring Batch | Java |
---|---|---|---|---|
2.0 | 3.5+ | 5.0+ | 4.0+ | Java 8+ |
1.3 | 3.4+ | 3.2.2+ | 2.1+ | Java 6+ |
12.1.准备:
1.导入要使用的依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<!--aop织入-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<!-- mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
</dependencies>
12.2.操作mybatis
1.查看mybatis学习笔记
连接数据库—–>编写实体类——-》编写mapper接口—–》构建 SqlSessionFactory——-》mapper.xml文件—–》mybatis核心配置文件——测试
构建SqlSessionFactory:
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class MybastisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//获取 SqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession实例
//SqlSession包含了面向数据库执行的所有方法
public static SqlSession gteSqlSession(){
SqlSession sqlSession= sqlSessionFactory.openSession();
return sqlSession;
}
}
2.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">
<!--绑定一个定一个对应的dao/mapper接口-->
<mapper namespace="">
</mapper>
3.mybatis核心配置文件及sql文件:db.properties:
<!--sql文件:db.properties-->
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/person?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone =UTC
username=root
password=123456
================================================================
<?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>
<!--引入一个外部配置文件-->
<properties resource="db.properties"/>
<!--给实体类起别名-->
<typeAliases>
<typeAlias type="com.gongfang.User.Student1" alias="student1"/>
</typeAliases>
<!-- 环境:配置mybatis的环境 -->
<environments default="development">
<!-- 环境变量:可以配置多个环境变量,比如使用多数据源时,就需要配置多个环境变量 -->
<environment id="development">
<!-- 事务管理器 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据源 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/gongfang/mapper/mapper.xml"/>
</mappers>
</configuration>
12.3.mybatis-spring 实现方式1
1.接口
package com.gongfang.mapper;
import com.gongfang.User.Student1;
import java.util.List;
public interface sqlmapper {
public List<Student1> getStudent1();
}
2.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">
<!--绑定一个定一个对应的dao/mapper接口-->
<mapper namespace="com.gongfang.mapper.sqlmapper">
<cache eviction="FIFO" flushInterval="6000" size="512" readOnly="true"/>
<select id="getStudent1" resultType="student1">
SELECT * from student1
</select>
</mapper>
目标实现类:
package com.gongfang.mapper;
import com.gongfang.User.Student1;
import org.mybatis.spring.SqlSessionTemplate;
import java.util.List;
//目标实现类
public class sqlmapperimp implements sqlmapper {
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
//好比mybatis中的测试
@Override
public List<Student1> getStudent1() {
sqlmapper mapper = sqlSession.getMapper(sqlmapper.class);
return mapper.getStudent1();
}
}
实体类:
package com.gongfang.User;
import lombok.Data;
import lombok.ToString;
@Data
public class Student1 {
private int id;
private String name;
private char sex;
@Override
public String toString() {
return "Student1{" +
"id=" + id +
", name='" + name + '\'' +
", sex=" + sex +
'}';
}
}
mybati配置文件 mybatis-config.xml:
<?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>
<typeAlias type="com.gongfang.User.Student1" alias="student1"/>
</typeAliases>
</configuration>
spring配置文件,用于和mybatis建立连接:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--mybatis中的数据库连接问件-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/person?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone =UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<!-- sqlSessionFactory:用于spring整合mybatis,与mybatis建立连接-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--绑定mybatis配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/gongfang/mapper/*.xml"/>
</bean>
<!--SqlSessionTemplate:就是mybatis中的sqlSession文件-->
<bean id="Template" class="org.mybatis.spring.SqlSessionTemplate">
<!--只能用构造方法注入sqlSessionFactory,因为SqlSessionTemplate没有set方法-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<!--注册bean-->
<bean id="sqmaip" class="com.gongfang.mapper.sqlmapperimp">
<property name="sqlSession" ref="Template"/>
</bean>
</beans>
测试:
public class testsqlmapper {
@Test
public void getStudent1() {
ApplicationContext res = new ClassPathXmlApplicationContext("spring-dao.xml");
//代理接口
sqlmapper sqmaip = (sqlmapper) res.getBean("sqmaip");
//打印
List<Student1> student1 = sqmaip.getStudent1();
for (Student1 s:
student1) {
System.out.println(s);
}
}
}
结果:
13.事务
- ACID原则:原子性,一致性,持久性,隔离性(幻读,脏读,不可重复读)
13.1.课前案例
这里我们来添加个用户同时删除这个添加的用户,一同执行,专门把删除用户的SQL语言写错,让程序最后执行会发现程序报错,但奇怪的是用户添加进去了,但没有删除,所以就造成了不一致性
1.数据表实体类
@Data
public class Student1 {
private int id;
private String name;
private char sex;
public Student1() {
}
public Student1(int id, String name, char sex) {
this.id = id;
this.name = name;
this.sex = sex;
}
@Override
public String toString() {
return "Student1{" +
"id=" + id +
", name='" + name + '\'' +
", sex=" + sex +
'}';
}
}
2.mybatis的mapper接口
import com.gongfang.User.Student1;
import java.util.List;
public interface sqlmapper {
//查询全部用户
public List<Student1> getStudent1();
//插入用户
public int adduser(Student1 name);
//删除用户
public int deleteuser(int id);
}
3.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">
<!--绑定一个定一个对应的dao/mapper接口-->
<mapper namespace="com.gongfang.mapper.sqlmapper">
<cache eviction="FIFO" flushInterval="6000" size="512" readOnly="true"/>
<select id="getStudent1" resultType="student1">
SELECT * from student1
</select>
<insert id="adduser" parameterType="Student1">
insert into student1(id,name,sex) values (#{id},#{name},#{sex})
</insert>
<!--这里专门把 delete 错写成 deletes -->
<delete id="deleteuser" parameterType="int">
deletes from student1 where id=#{id}
</delete>
</mapper>
4.目标实现类
import com.gongfang.User.Student1;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
//目标实现类
public class sqlmapperimp extends SqlSessionDaoSupport implements sqlmapper {
@Override
// 这里执行增加,删除,查询
public List<Student1> getStudent1() {
Student1 s=new Student1(8,"太始",'男');
SqlSession sqlSession = getSqlSession();
sqlmapper mapper = sqlSession.getMapper(sqlmapper.class);
mapper.adduser(s);
mapper.deleteuser(8);
return mapper.getStudent1();
}
@Override
public int adduser(Student1 name) {
SqlSession sqlSession = getSqlSession();
sqlmapper mapper = sqlSession.getMapper(sqlmapper.class);
return mapper.adduser(name);
}
@Override
public int deleteuser(int id) {
SqlSession sqlSession = getSqlSession();
sqlmapper mapper = sqlSession.getMapper(sqlmapper.class);
return mapper.deleteuser(id);
}
}
5.mybatis文件
<?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>
<typeAlias type="com.gongfang.User.Student1" alias="student1"/>
</typeAliases>
</configuration>
6.Spring配置文件
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/person?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone =UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<!-- sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--绑定mybatis配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/gongfang/mapper/*.xml"/>
</bean>
<!--SqlSessionTemplate:就是使用的sqlSession-->
<bean id="Template" class="org.mybatis.spring.SqlSessionTemplate">
<!--只能用构造方法注入sqlSessionFactory,因为SqlSessionTemplate没有set方法-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<bean id="sqmaip" class="com.gongfang.mapper.sqlmapperimp">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
</beans>
7.测试:
import com.gongfang.User.Student1;
import com.gongfang.mapper.sqlmapper;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class testsqlmapper {
@Test
public void getStudent1() {
ApplicationContext res = new ClassPathXmlApplicationContext("spring-dao.xml");
sqlmapper sqmaip = (sqlmapper) res.getBean("sqmaip");
List<Student1> student1 = sqmaip.getStudent1();
for (Student1 s:
student1) {
System.out.println(s);
}
}
}
8.结果:
结果运行报错,但 “太始” 被添加到了数据表中
13.2.开启事务
1.spring中开启事务
<!--开启事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
2.导入 tx 支持与 aop 支持
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
3.大体
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/person?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone =UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<!-- sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--绑定mybatis配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/gongfang/mapper/*.xml"/>
</bean>
<!--SqlSessionTemplate:就是使用的sqlSession-->
<bean id="Template" class="org.mybatis.spring.SqlSessionTemplate">
<!--只能用构造方法注入sqlSessionFactory,因为SqlSessionTemplate没有set方法-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<bean id="sqmaip" class="com.gongfang.mapper.sqlmapperimp">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<!-- =======================================================================================-->
<!--开启事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--结合aop事务织入,配置事务类-->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<!--给方法配置事务-->
<tx:attributes>
<!-- <tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="updete" propagation="REQUIRED"/>
<tx:method name="query" read-only="true"/>-->
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.gongfang.mapper.*.*(..))"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="pointcut"/>
</aop:config>
</beans>
4.结果:
程旭报错,用户没被添加数据表中,完成了一致性
14.总结spring
- 开源免费
- 轻量级,非入侵式的框架
- 控制反转(IOC) 面向切面编程(AOP)
- 支持事务处理及框架整合
spring是一个轻量级的 控制反转,面向切面编程的框架
本文地址:https://blog.csdn.net/weixin_46311020/article/details/111616138