Spring 5
文章目录
- Spring 学习概述
- IOC 容器
- (1)IOC 底层原理
- (2)IOC 接口(BeanFactory)
- (3)IOC 操作 Bean 管理(基于 xml)
- (4)IOC 操作 Bean 管理(基于注解)
- Aop
- JdbcTemplate
- 事务管理
- Spring5 新特性
1、Spring框架概述
- Spring 是轻量级的开源的JavaEE框架
- Spring 可以解决企业应用开发的复杂性
- Spring 有两个核心部分:IOC ,Aop
- IOC:控制反转,把创建对象过程交给Spring管理
- Aop:面向切面,不修改源代码进行功能增强
- Spring特点
- 方便解耦,简化开发
- Aop编程支持
- 方便程序测试
- 方便其他框架整合
- 方便进行事务的操作
- 降低API开发难度
2、IOC
IOC入门案例
User类
package com.atchan;
public class User {
public void add(){
System.out.println("add........");
}
}
Spring IOC 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">
<!--配置 User 对象创建-->
<!-- id:类的别名 class:类的全路径 -->
<bean id="User" class="com.atchan.User"></bean>
</beans>
测试类
package com.atchan.Test;
import com.atchan.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
public class TestUser {
@Test
public void userAdd(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean1.xml");
User user = applicationContext.getBean("User", User.class);
user.add();
}
}
2.1 IOC概念和原理
-
什么是IOC
- 控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理
- 使用IOC目的:为了降低耦合度
- 做入门案例就是 IOC 实现
-
IOC底层实现原理
- xml解析、工厂模式、反射
-
画图讲解IOC底层原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PyIaDTKB-1647143877489)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220220133704414.png)]
2.2 IOC(BeanFactory 接口)
-
IOC思想基于IOC容器完成,IOC的底层是对象工厂
-
Spring提供IOC容器实现的两种方式:(两个接口)
-
BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用
* 加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
-
ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人 员进行使用
* 加载配置文件时候就会把在配置文件对象进行创建
-
-
ApplicationContext 接口有实现类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ImY4xVEZ-1647143877491)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220221101128911.png)]
2.3 IOC的操作Bean管理(概念)
- 什么是Bean管理
- Bean管理指的是两个操作
- Spring对象创建
- Spring属性注入
- Bean管理操作有两种方式
- 基于xml配置文件方式的实现
- 基于注解方式实现
2.3.1 IOC 操作 Bean 管理(基于 xml 方式)
-
基于 xml 方式创建对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L2y4rgyQ-1647143877491)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220221110659920.png)]
- 在Spring配置文件中,使用bean标签,标签里面添加对应的属性,就可以实现对象的创建
- 在bean标签有很多属性,常用的属性
- id 属性:唯一标识
- class 属性:类全路径(包类路径)
- 创建对象时候,默认也是执行无参数构造方法完成对象创建
-
基于xml方式注入属性
- DI:依赖注入,就是属性注入
-
第一种注入方式:使用set方法进行注入
- 创建类,定义属性和对应的set方法
演示使用 set 方法进行注入属性
package com.atchan;
import java.math.BigDecimal;
public class Book {
private String name;
private BigDecimal price;
public void setName(String name) {
this.name = name;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public void show(){
System.out.println(name + "--" + price);
}
}
在 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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="book" class="com.atchan.Book">
<!--使用 property 完成属性注入
name:类里面属性名称
value:向属性注入的值
-->
<property name="name" value="Spring5"></property>
<property name="price" value="12.50"></property>
</bean>
</beans>
- 第二种注入方式:使用有参数构造进行注入
- 创建类,定义属性,创建属性对应有参数构造方法
演示使用 有参构造 方法进行注入属性
package com.atchan;
import java.math.BigDecimal;
public class Order {
private String name;
private BigDecimal price;
public Order(String name, BigDecimal price) {
this.name = name;
this.price = price;
}
public void show(){
System.out.println(name + "--" + price);
}
}
在 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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="order" class="com.atchan.Order">
<constructor-arg name="name" value="电脑"></constructor-arg>
<constructor-arg name="price" value="1000.00"></constructor-arg>
</bean>
</beans>
-
p 名称空间注入(了解)
-
使用 p 名称空间注入,可以简化基于 xml 配置方式 第一步 添加 p 名称空间在配置文件中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1e7TKikg-1647143877492)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220221112203549.png)]
-
第二步 进行属性注入,在 bean 标签里面进行操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SMpgP2TE-1647143877492)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220221112528803.png)]
-
2.3.2 IOC 操作 Bean 管理(xml 注入其他类型属性)
-
字面量
-
null 值
<!--null 值--> <property name="address"> <null/> </property>
-
属性值包含特殊符号
<!--属性值包含特殊符号 1 把<>进行转义 < > 2 把带特殊符号内容写到 CDATA --> <property name="address"> <value><![CDATA[<<南京>>]]></value> </property>
-
-
注入属性-外部 bean
- 创建两个类 service 类和 dao 类
- 在 service 调用 dao 里面的方法
- 在 spring 配置文件中进行配置
-
注入属性-内部 bean
-
一对多关系:部门和员工,一个员工属于一个部门,部门是一,员工是多
-
在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示
<?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--> <bean id="emp" class="com.atchan.bean.Emp"> <!--设置两个普通属性--> <property name="name" value="🐙⚪"></property> <property name="ender" value="女"></property> <!--设置对象类型属性--> <property name="dept" > <bean id="dept" class="com.atchan.bean.Dept"> <property name="name" value="安保部"></property> </bean> </property> </bean> </beans>
-
-
注入属性-级联赋值
-
写法一
<?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="emp" class="com.atchan.bean.Emp"> <!--设置两个普通属性--> <property name="name" value="李海涛"></property> <property name="ender" value="男"></property> <!--级联赋值--> <property name="dept" ref="dept"></property> </bean> <bean id="dept" class="com.atchan.bean.Dept"> <property name="name" value="保安队长"></property> </bean> </beans>
-
写法二
<?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="emp" class="com.atchan.bean.Emp"> <!--设置两个普通属性--> <property name="name" value="董金磊"></property> <property name="ender" value="男"></property> <!--级联赋值--> <property name="dept" ref="dept"></property> <property name="dept.name" value="看门狗"></property> </bean> <bean id="dept" class="com.atchan.bean.Dept"></bean> </beans>
-
-
注入数组类型属性
-
注入 List 集合类型属性
-
注入 Map 集合类型属性
-
创建类,定义数组、list、map、set 类型属性,生成对应 set 方法
package com.atchan.aggregate; import java.util.*; public class Studer { private String[] name; private List<String> list; private Map<String, String> map; private Set<String> set; public void setName(String[] name) { this.name = name; } public void setList(List<String> list) { this.list = list; } public void setMap(Map<String, String> map) { this.map = map; } public void setSet(Set<String> set) { this.set = set; } public void show(){ System.out.println(Arrays.toString(name)); System.out.println(list); System.out.println(map); System.out.println(set); } }
在 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:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/beans/spring-util.xsd "> <!--1 集合类型属性注入--> <bean id="studer" class="com.atchan.aggregate.Studer"> <!--数组类型属性注入--> <property name="name"> <array> <value>Java</value> <value>HTML</value> </array> </property> <!--list 类型属性注入--> <property name="list"> <list> <value>张三</value> <value>小三</value> </list> </property> <!--map 类型属性注入--> <property name="map"> <map> <entry key="JAVA" value="java"></entry> <entry key="PHP" value="php"></entry> </map> </property> <!--set 类型属性注入--> <property name="set"> <set> <value>css</value> <value>jquery</value> </set> </property> </bean> </beans>
-
-
在集合里面设置对象类型值
-
<!--创建多个 course 对象--> <bean id="course1" class="com.atguigu.spring5.collectiontype.Course"> <property name="cname" value="Spring5 框架"></property> </bean> <bean id="course2" class="com.atguigu.spring5.collectiontype.Course"> <property name="cname" value="MyBatis 框架"></property> </bean> <!--注入 list 集合类型,值是对象--> <property name="courseList"> <list> <ref bean="course1"></ref> <ref bean="course2"></ref> </list> </property>
-
把集合注入部分提取出来
-
在 spring 配置文件中引入名称空间 util
-
<?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:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> </beans>
-
使用 util 标签完成 list 集合注入提取
-
<?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:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <util:list id="bookList"> <value>易筋经</value> <value>九阴真经</value> <value>九阳神功</value> </util:list> <!--2 提取 list 集合类型属性注入使用--> <bean id="book" class="com.atguigu.spring5.collectiontype.Book"> <property name="list" ref="bookList"></property> </bean> </beans>
-
-
2.3.3 IOC 操作 Bean 管理(FactoryBean)
-
Spring 有两种类型的bean,一种普通bean,另外一种工厂bean(FactoryBean)
-
普通bean:在配置文件定义的bean类型就是返回类型
-
工厂bean:在配置文件定义bean类型可以返回和返回类型不一样
- 第一步 创建类,让这个类作为工厂 bean,实现接口 FactoryBean
- 第二步 实现接口里面的方法,在实现的方法中定义返回的 bean 类型
package com.atchan.factoryBean; import com.atchan.aggregate.Course; import org.springframework.beans.factory.FactoryBean; public class MyBean implements FactoryBean { //定义返回 bean @Override public Object getObject() throws Exception { Course course = new Course(); course.setName("abc"); return course; } @Override public Class<?> getObjectType() { return null; } @Override public boolean isSingleton() { return FactoryBean.super.isSingleton(); } }
在 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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myBean" class="com.atchan.factoryBean.MyBean"></bean>
</beans>
测试类
package com.atchan.Test;
import com.atchan.aggregate.Course;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
public class Test1 {
@Test
public void myBean(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("factory.xml");
Course course = applicationContext.getBean("myBean", Course.class);
System.out.println(course);
}
}
2.3.4 IOC 操作 Bean 管理(bean 作用域)
-
在Spring 里面,设置创建bean实例是单例还是多实例
-
在Spring 里面,默认情况下,bean是单实例对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JyzvdeL9-1647143877493)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220222140620922.png)]
-
如何设置单实例还是多实例
-
在Spring配置文件bean标签里面有属性(scope)用于设置单例还是多例实例
-
scope属性值
-
第一个值 默认值,singleton,表示是单例实例对象
-
第二个值 prototype,表示多例实例对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-86r3YGPs-1647143877493)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220222141045634.png)]
-
-
singleton和prototype的区别
-
第一 singleton 单实例,prototype 多实例
-
第二设置scope值是singleton的时候,加载Spring配置文件的时候就会创建单实例对象
设置scope值是prototype时候,不是在加载Spring配置文件的时候创建对象,在调用getBean方法时候创建多实例对象
-
-
2.3.5 IOC 操作 Bean 管理(bean 生命周期)
-
生命周期
- 从对象创建到对象销毁的过程
-
bean的生命周期
- (1)通过构造器创建bean实例(无参构造器)
- (2)为bean的属性设置值和对其他bean的引用(调用set方法)
- (3)调用bean的初始化方法(需要进行配置初始化的方法)
- (4)bean可以使用了(对象获取到)
- (5)当容器关闭时,调用bean的销毁方法(需要进行配置销毁的方法)
-
演示bean的生命周期
Orders类
package com.atchan; public class Orders { private String name; public Orders(){ System.out.println("第一步 执行无参数构造创建 bean 实例"); } public void setName(String name) { this.name = name; System.out.println("第二步 调用 set 方法设置属性值"); } //创建执行的初始化的方法 public void initMethod(){ System.out.println("第三步 执行初始化的方法"); } //创建执行的销毁的方法 public void destroyMethod() { System.out.println("第五步 执行销毁的方法"); } }
在 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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="orders" class="com.atchan.Orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="name" value="手机"></property>
</bean>
</beans>
Test1测试类
package com.atchan.Test;
import com.atchan.Orders;
import com.atchan.aggregate.Course;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
public class Test1 {
@Test
public void myBean(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("factory.xml");
Course course = applicationContext.getBean("myBean", Course.class);
System.out.println(course);
System.out.println(course);
}
@Test
public void testOrders(){
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean4.xml");
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean4.xml");
Orders orders = applicationContext.getBean("orders", Orders.class);
System.out.println("第四步 获取创建 bean 实例对象");
System.out.println(orders);
//手动让 bean 实例销毁
applicationContext.close();
}
}
-
bean的后置处理器,bean的生命周期
- (1)通过构造器创建bean实例(无参构造器)
- (2)为bean的属性设置值和对其他bean的引用(调用set方法)
- (3)把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
- (4)调用bean的初始化方法(需要进行配置初始化的方法)
- (5)把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization
- (6)bean可以使用了(对象获取到)
- (7)当容器关闭时,调用bean的销毁方法(需要进行配置销毁的方法)
-
演示添加后置处理器效果
Orders类
package com.atchan; public class Orders { private String name; public Orders(){ System.out.println("第一步 执行无参数构造创建 bean 实例"); } public void setName(String name) { this.name = name; System.out.println("第二步 调用 set 方法设置属性值"); } //创建执行的初始化的方法 public void initMethod(){ System.out.println("第三步 执行初始化的方法"); } //创建执行的销毁的方法 public void destroyMethod() { System.out.println("第五步 执行销毁的方法"); } }
实现BeanPostProcessor接口
package com.atchan; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPost implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("在初始化之前执行的方法"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("在初始化之后执行的方法"); return bean; } }
在 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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="orders" class="com.atchan.Orders" init-method="initMethod" destroy-method="destroyMethod"> <property name="name" value="手机"></property> </bean> <bean id="myBeanPost" class="com.atchan.MyBeanPost"></bean> </beans>
Test1测试类
package com.atchan.Test; import com.atchan.Orders; import com.atchan.aggregate.Course; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.testng.annotations.Test; public class Test1 { @Test public void myBean(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("factory.xml"); Course course = applicationContext.getBean("myBean", Course.class); System.out.println(course); System.out.println(course); } @Test public void testOrders(){ // ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean4.xml"); ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean4.xml"); Orders orders = applicationContext.getBean("orders", Orders.class); System.out.println("第四步 获取创建 bean 实例对象"); System.out.println(orders); //手动让 bean 实例销毁 applicationContext.close(); } }
2.3.6 IOC 操作 Bean 管理(xml 自动装配)
-
什么是自动装配
- 根据指定装配规则(属性名称或属性类型),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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 实现自动装配 bean标签autowire,配置自动装配 autowire属性常用两个值: byName:根据属性名称注入,注入值bean的id值和属性类型名称一样 byType:根据属性类型注入 --> <bean id="emp" class="com.atchan.autowire.Emp" autowire="byName"></bean> <bean id="dept" class="com.atchan.autowire.Dept"></bean> </beans>
-
根据属性类型自动注入
<?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标签autowire,配置自动装配 autowire属性常用两个值: byName:根据属性名称注入,注入值bean的id值和属性类型名称一样 byType:根据属性类型注入 --> <bean id="emp" class="com.atchan.autowire.Emp" autowire="byType"></bean> <bean id="dept" class="com.atchan.autowire.Dept"></bean> </beans>
-
2.3.7 IOC 操作 Bean 管理(外部属性文件)
-
直接配置数据库信息
-
配置德鲁伊连接池
-
引入德鲁伊jar包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yHyXiSm8-1647143877494)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220222184253382.png)]
-
直接配置数据库连接池
<?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 https://www.springframework.org/schema/context/spring-context.xsd"> <!--直接配置数据库连接池--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/book"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> </beans>
-
-
引入外部属性文件配置数据库连接池
-
创建外部属性文件,properties 格式文件,写数据库信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZHD9aL24-1647143877495)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220222184517419.png)]
-
把外部 properties 属性文件引入到 spring 配置文件中
-
引入命名空间
xmlns:context="http://www.springframework.org/schema/context"
<?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 https://www.springframework.org/schema/context/spring-context.xsd"> <!--直接配置数据库连接池--> <!--<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/book"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean>--> <!--引入外部属性文件--> <context:property-placeholder location="classpath:resources/jdbc.properties"></context:property-placeholder> <!--配置连接池--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${driverClassName}"></property> <property name="url" value="${url}"></property> <property name="username" value="${username}"></property> <property name="password" value="${password}"></property> </bean> </beans>
-
-
2.3.8 IOC 操作 Bean 管理(基于注解方式)
-
什么是注解
- 注解是代码的特殊标记,格式:@注解名称(属性名=属性值,属性名=属性值…)
- 使用注解,注解作用在类上,方法上,属性上
- 使用注解的目的:简化xml配置
-
Spring针对Bean管理中创建对象提供注解
-
@Component
-
@Service
-
@Controller
-
@Repository
上面的四个注解功能是一样的,都可以用来创建bean实例
-
-
基于注解方式实现对象创建
-
第一步引入依赖
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qDzb1lXd-1647143877495)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220222192345440.png)]
-
第二步开启组件扫描
<?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 https://www.springframework.org/schema/context/spring-context.xsd"> <!--开启组件扫描 1 如果扫描多个包,多个包使用逗号隔开 2 扫描包上层目录 --> <context:component-scan base-package="com.atchan.annotation"></context:component-scan> </beans>
-
第三步 创建类,在类上面添加创建对象注解
package com.atchan.annotation; import org.springframework.stereotype.Component; //在注解里面 value 属性值可以省略不写, //默认值是类名称,首字母小写 //Book -- book @Component public class Book { public void add(){ System.out.println("book..........."); } }
-
-
开启组件扫描细节配置
<?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 https://www.springframework.org/schema/context/spring-context.xsd"> <!--示例 1 use-default-filters="false" 表示现在不使用默认 filter,自己配置 filter context:include-filter ,设置扫描哪些内容 --> <context:component-scan base-package="com.atchan" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!--示例 2 下面配置扫描包所有内容 context:exclude-filter: 设置哪些内容不进行扫描 --> <context:component-scan base-package="com.atchan" > <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Component"/> </context:component-scan> </beans>
-
基于注解方式实现属性注入
-
@Autowired:根据属性类型进行自动装配
-
第一步 把 BookService和 BookDaoImpl对象创建,在 service 和 dao 类添加创建对象注解
-
第二步 在 service 注入 dao 对象,在 service 类添加 dao 类型属性,在属性上面使用注解
package com.atchan.service; import com.atchan.dao.BookDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class BookService { @Autowired private BookDao bookDao; public void show(){ System.out.println("BookService.........."); bookDao.add(); } }
-
package com.atchan.dao; import org.springframework.stereotype.Repository; @Repository public class BookDaoImpl implements BookDao{ @Override public void add() { System.out.println("BookDao.........."); } }
-
-
@Qualifier:根据名称注入
这个@Qualifier 注解的使用,和上面@Autowired 一起使用
package com.atchan.service; import com.atchan.dao.BookDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.Resource; @Service public class BookService { //定义 dao 类型属性 //不需要添加 set 方法 //添加注入属性注解 @Autowired //根据类型进行注入 @Qualifier(value = "bookDaoImpl") //根据名称进行注入 private BookDao bookDao; public void show(){ System.out.println("BookService.........."); bookDao.add(); } }
-
@Resource:可以根据类型注入,可以根据名称注入
package com.atchan.service; import com.atchan.dao.BookDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.Resource; @Service public class BookService { @Resource(name="bookDaoImpl") private BookDao bookDao; public void show(){ System.out.println("BookService.........." + name + "--" + num); bookDao.add(); } }
-
@Value:注入普通类型属性
package com.atchan.service; import com.atchan.dao.BookDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.Resource; @Service public class BookService { @Value("13") private String name; @Value("11") private Integer num; @Resource(name="bookDaoImpl") private BookDao bookDao; public void show(){ System.out.println("BookService.........." + name + "--" + num); bookDao.add(); } }
-
-
完全基于注解开发
-
创建配置类,替代xml配置文件
package com.atchan; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan(basePackages = {"com.atchan"}) public class SpringConfig { }
-
测试类
package com.atchan.Test; import com.atchan.Orders; import com.atchan.SpringConfig; import com.atchan.aggregate.Course; import com.atchan.annotation.Book; import com.atchan.autowire.Dept; import com.atchan.autowire.Emp; import com.atchan.service.BookService; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.testng.annotations.Test; public class Test1 { @Test public void bookService2(){ ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); BookService bookService = applicationContext.getBean("bookService", BookService.class); bookService.show(); } }
-
3、AOP(概念)
3.1 什么是AOP
-
面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各个部分降低耦合度,提高程序的可重用性,同时提高开发的效率
-
通俗描述就是:不修改源代码方式,在主干功能里面添加新功能
-
使用登录例子说明AOP
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BKScNtOG-1647143877496)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220223162223501.png)]
3.2 AOP(底层原理)
-
AOP底层使用动态代理
-
有两种情况动态代理
-
第一种 有接口情况,使用 JDK 动态代理
-
创建接口实现类代理对象,增强类的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KZVBYdjN-1647143877496)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220223162517439.png)]
-
-
第二种 没有接口情况,使用 CGLIB 动态代理
-
创建子类的代理对象,增强类的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CIzJPAVm-1647143877496)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220223162658563.png)]
-
-
-
3.3 AOP(JDK 动态代理)
-
使用JDK动态代理,使用Proxy类里面的方法创建代理对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yZJ9q1pI-1647143877497)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220223172030933.png)]
-
调用newProxyInstance方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wsQVW9ZC-1647143877498)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220223172144983.png)]
方法有三个参数:
- 第一个参数:类加载器
- 第二个参数,增强方法所在的类,这个类的实现接口,支持多个接口
- 第三个参数,实现这个接口InvocationHandler,创建代理对象,写增强的部分
-
-
编写JDK动态代理代码
-
创建接口,定义方法
package com.atchan.aop; public interface UserDao { Integer add(int a,int b); String update(String id); }
-
创建接口实现类
package com.atchan.aop; public class UserDaoImpl implements UserDao{ @Override public Integer add(int a, int b) { return a + b; } @Override public String update(String id) { return id; } }
-
使用 Proxy 类创建接口代理对象
package com.atchan.aop; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; public class JDKProxy { public static void main(String[] args) { //创建接口实现类代理对象 Class[] interfaces = {UserDao.class}; UserDao userDao = new UserDaoImpl(); UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao)); Integer integer = userDaoProxy.add(1, 2); System.out.println(integer); } } //创建代理对象代码 class UserDaoProxy implements InvocationHandler { //把创建的是谁的代理对象,把谁传递过来 //有参数构造传递 private Object obj; public UserDaoProxy(Object obj){ this.obj = obj; } //增强的逻辑 @Override public Object invoke(Object o, Method method, Object[] objects) throws Throwable { //方法前 System.out.println("方法执行前" + method.getName() + "传递的参数:" + Arrays.toString(objects)); //被增强的方法执行 Object invoke = method.invoke(obj, objects); //方法之后 System.out.println("方法之后执行...."+obj); return invoke; } }
-
3.4 AOP(术语)
- 连接点
- 类里面那些方法可以被增强,这些方法被称为连接点
- 切入点
- 实际被真正增强的方法,称为切入点
- 通知(增强)
- 实际增强的逻辑部分称为通知(增强)
- 通知的类型有多种
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知
- 切面
- 是动作
- 把通知应用到切入点的过程
- 是动作
3.5 AOP 操作(准备工作)
-
Spring框架一般都是基于AspenctJ实现AOP操作
- AspenctJ 不是 Spring组成部分,独立于AOP框架,一般把AspenctJ 和 Spring框架组合使用,进行AOP操作
-
基于AspenctJ 实现AOP操作
- 基于xml配置文件实现
- 基于注解方式实现(使用)
-
在项目工程里引入AOP相关依赖
-
切入点表达式
-
切入点表达式的作用:知道对那个类的方法进行增强
-
语法结构:execution([权限修饰符] [返回类型] [方法名称] ([参数列表]))
**举例1:**对对 com.atguigu.dao.BookDao 类里面的 add 进行增强
execution(* com.atguigu.dao.BookDao.add(…))
**举例 2:**对 com.atguigu.dao.BookDao 类里面的所有的方法进行增强
execution(* com.atguigu.dao.BookDao.* (…))
**举例 3:**对 com.atguigu.dao 包里面所有类,类里面所有方法进行增强
execution(* com.atguigu.dao.. (…))
-
3.6 AOP 操作(AspectJ 注解)
-
创建类,在类里面定义方法
package com.atchan.aop; import org.springframework.stereotype.Component; public class Book { public void add(){ System.out.println("add.............."); } }
-
创建增强类(编写增强逻辑)
package com.atchan.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; //增强的类 public class BookProxy { public void before(){ System.out.println("before.........."); } }
-
进行通知的配置
-
在 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: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.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 开启注解扫描 --> <context:component-scan base-package="com.atchan.aop"></context:component-scan> </beans>
-
使用注解创建 Book和 BookProxy 对象
-
Book类
package com.atchan.aop; import org.springframework.stereotype.Component; @Component public class Book { public void add(){ System.out.println("add.............."); } }
-
BookProxy 代理对象
package com.atchan.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; //增强的类 @Component @Aspect //生成代理对象 public class BookProxy { //前置通知 //@Before 注解表示作为前置通知 @Before("execution(* com.atchan.aop.Book.add(..))") public void before(){ System.out.println("before.........."); } }
-
在 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: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.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 开启注解扫描 --> <context:component-scan base-package="com.atchan.aop"></context:component-scan> <!-- 开启 Aspect 生成代理对象--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
-
-
配置不同类型的通知
-
在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
package com.atchan.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; //增强的类 @Component @Aspect //生成代理对象 public class BookProxy { //前置通知 //@Before 注解表示作为前置通知 @Before("execution(* com.atchan.aop.Book.add(..))") public void before(){ System.out.println("before.........."); } //后置通知(返回通知) @AfterReturning("execution(* com.atchan.aop.Book.add(..))") public void afterReturning(){ System.out.println("AfterReturning后置通知....."); } @After("execution(* com.atchan.aop.Book.add(..))") public void after(){ System.out.println("After最终通知....."); } @AfterThrowing("execution(* com.atchan.aop.Book.add(..))") public void afterThrowing(){ System.out.println("AfterThrowing异常通知....."); } @Around("execution(* com.atchan.aop.Book.add(..))") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("around环绕通知之前....."); proceedingJoinPoint.proceed(); System.out.println("around环绕通知之后....."); } }
-
-
相同的切入点抽取
- @Pointcut(value = “execution(* com.atchan.aop.Book.add(…))”)
public void pointDemo() {
}
package com.atchan.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; //增强的类 @Component @Aspect //生成代理对象 public class BookProxy { @Pointcut(value = "execution(* com.atchan.aop.Book.add(..))") public void pointDemo() { } //前置通知 //@Before 注解表示作为前置通知 @Before("pointDemo()") public void before(){ System.out.println("before.........."); } //后置通知(返回通知) @AfterReturning("pointDemo()") public void afterReturning(){ System.out.println("AfterReturning后置通知....."); } }
- @Pointcut(value = “execution(* com.atchan.aop.Book.add(…))”)
-
有多个增强类多同一个方法进行增强,设置增强类优先级
-
在增强类上面添加注解 @Order(数字类型值),数字类型值越小优先级越高
package com.atchan.aop; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Aspect @Order(1) public class PersonProxy { @Before("execution(* com.atchan.aop.Book.add())") public void test(){ System.out.println("test........"); } }
package com.atchan.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; //增强的类 @Component @Aspect //生成代理对象 @Order(3) public class BookProxy { @Pointcut(value = "execution(* com.atchan.aop.Book.add(..))") public void pointDemo() { } //前置通知 //@Before 注解表示作为前置通知 @Before("pointDemo()") public void before(){ System.out.println("before.........."); } }
-
-
完全使用注解开发
-
创建配置类,不需要创建 xml 配置文件
package com.atchan.aop; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; //声名配置类 @Configuration //扫描组件扫描 @ComponentScan(basePackages = {"com.atchan.aop"}) //开启 Aspect 生成代理对象 @EnableAspectJAutoProxy(proxyTargetClass = true) public class ConfigAop { }
-
3.7 AOP 操作(AspectJ 配置文件)
-
创建两个类,增强类和被增强类,创建方法
-
在 spring 配置文件中创建两个类对象
<!--创建对象--> <bean id="book" class="com.atguigu.spring5.aopxml.Book"></bean> <bean id="bookProxy" class="com.atguigu.spring5.aopxml.BookProxy"></bean>
-
在 spring 配置文件中配置切入点
<!--配置 aop 增强--> <aop:config> <!--切入点--> <aop:pointcut id="p" expression="execution(* com.atguigu.spring5.aopxml.Book.buy(..))"/> <!--配置切面--> <aop:aspect ref="bookProxy"> <!--增强作用在具体的方法上--> <aop:before method="before" pointcut-ref="p"/> </aop:aspect> </aop:config>
4、JdbcTemplate(概念和准备)
-
什么是JdbcTemplate
- 是Spring框架对JDBC进行了封装,使用JdbcTemplate方便实现对数据库的操作
-
准备工作
-
引入jar包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WruemhWz-1647143877498)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220225123400729.png)]
-
在 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: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 https://www.springframework.org/schema/context/spring-context.xsd"> <!--直接配置数据库连接池--> <!--<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/book"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean>--> <!--引入外部属性文件--> <context:property-placeholder location="classpath:resources/jdbc.properties"></context:property-placeholder> <!--配置连接池--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${driverClassName}"></property> <property name="url" value="${url}"></property> <property name="username" value="${username}"></property> <property name="password" value="${password}"></property> </bean> <!--配置 JdbcTemplate 对象,注入 DataSource--> <!--JdbcTemplate--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <!--注入dataSource--> <property name="dataSource" ref="dataSource"></property> </bean> </beans>
-
-
创建 service 类,创建 dao 类,在 dao 注入 jdbcTemplate 对象
-
配置文件
<!-- 组件扫描 --> <context:component-scan base-package="com.atchan.jdbcTemplate"></context:component-scan>
-
Service
package com.atchan.jdbcTemplate.service; import com.atchan.jdbcTemplate.dao.BookDao; import com.atchan.jdbcTemplate.entity.Book; import org.springframework.beans.factory.annotation.Autowired; @org.springframework.stereotype.Service public class Service { @Autowired private BookDao bookDao; }
-
Dao
package com.atchan.jdbcTemplate.dao; import com.atchan.jdbcTemplate.entity.Book; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository public class BookDaoImpl implements BookDao{ @Autowired private JdbcTemplate jdbcTemplate; }
-
-
4.1 JdbcTemplate 操作数据库(添加)
- 对应数据库创建实体类
package com.atchan.jdbcTemplate.entity;
public class Book {
private Integer userId;
private String userName;
private String ustatus;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUstatus() {
return ustatus;
}
public void setUstatus(String ustatus) {
this.ustatus = ustatus;
}
}
- 编写 service 和 dao
- 在 dao 进行数据库添加操作
- 调用 JdbcTemplate 对象里面 update 方法实现添加操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6rjBzSCA-1647143877499)(file://C:/Users/admin/AppData/Roaming/Typora/typora-user-images/image-20220226165549150.png?lastModify=1645689846)]
有两个参数
第一个参数:sql 语句
第二个参数:可变参数,设置 sql 语句值
package com.atchan.jdbcTemplate.dao;
import com.atchan.jdbcTemplate.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class BookDaoImpl implements BookDao{
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void add(Book book) {
String sql = "insert into t_book (user_id,username,ustatus) values (?,?,?)";
int update = jdbcTemplate.update(sql, book.getUserId(), book.getUserName(), book.getUstatus());
System.out.println(update);
}
}
测试类
package com.atchan.jdbcTemplate.dao;
import com.atchan.jdbcTemplate.entity.Book;
import com.atchan.jdbcTemplate.service.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class BookDaoTest {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("jdbcTemplate.xml");
Service service = applicationContext.getBean("service", Service.class);
Book book = new Book();
@Test
public void add() {
book.setUserId(4);
book.setUserName("张三");
book.setUstatus("a");
service.addBook(book);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PlXFhd0H-1647143877499)(file://C:/Users/admin/AppData/Roaming/Typora/typora-user-images/image-20220226165904737.png?lastModify=1645689846)]
4.2 JdbcTemplate 操作数据库(修改和删除)
-
修改
@Override public void update(Book book) { String sql = "update t_book set username=?,ustatus=? where user_id = ?"; int update = jdbcTemplate.update(sql,book.getUserName(),book.getUstatus(),book.getUserId()); System.out.println(update); }
-
删除
@Override public void delete(Integer id) { String sql = "delete from t_book where user_id = ?"; int update = jdbcTemplate.update(sql, id); System.out.println(update); }
4.3 JdbcTemplate 操作数据库(查询返回某个值)
-
查询表里面有多少条记录,返回是某个值
-
使用 JdbcTemplate 实现查询返回某个值代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rqH08DbD-1647143877500)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220226170605203.png)]
-
有两个参数
-
第一个参数:sql 语句
-
第二个参数:返回类型 Class
@Override public Integer selectCount() { String sql = "select count(*) from t_book"; Integer books = jdbcTemplate.queryForObject(sql, Integer.class); return books; }
-
-
4.4 JdbcTemplate 操作数据库(查询返回对象)
-
场景:查询图书详情
-
JdbcTemplate 实现查询返回对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ODKyFM86-1647143877500)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220226171254526.png)]
- 有三个参数
- 第一个参数:sql 语句
- 第二个参数:RowMapper 是接口,针对返回不同类型数据,使用这个接口里面实现类完成 数据封装
- 第三个参数:sql 语句值
@Override public Book findBookInfo(Integer id){ String sql = "select user_id userId,username,ustatus from t_book where user_id=?"; Book book = jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<Book>(Book.class),id); return book; }
- 有三个参数
4.5 JdbcTemplate 操作数据库(查询返回集合)
-
场景:查询图书列表分页…
-
调用 JdbcTemplate 方法实现查询返回集合
- 有三个参数
- 第一个参数:sql 语句
- 第二个参数:RowMapper 是接口,针对返回不同类型数据,使用这个接口里面实现类完成 数据封装
- 第三个参数:sql 语句值
@Override public List<Book> findAllBook() { String sql = "select user_id,username,ustatus from t_book"; List<Book> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Book.class)); return query; }
4.6 JdbcTemplate 操作数据库(批量操作)
-
批量操作:操作表里面多条记录
-
JdbcTemplate 实现批量添加操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3xp089pp-1647143877501)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220226180022350.png)]
-
有两个参数
- 第一个参数:sql 语句
- 第二个参数:List 集合,添加多条记录数据
@Override public void batchAddBook(List<Object[]> batchArgs){ String sql = "insert into t_book (user_id,username,ustatus) values (?,?,?)"; int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs); System.out.println(Arrays.toString(ints)); }
//批量添加测试 @Override public void batchAddBook(List<Object[]> batchArgs){ String sql = "insert into t_book (user_id,username,ustatus) values (?,?,?)"; int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs); System.out.println(Arrays.toString(ints)); }
-
-
JdbcTemplate 实现批量修改操作
@Override public void batchUpdateBook(List<Object[]> batchArgs){ String sql = "update t_book set username=?,ustatus=? where user_id = ?"; int[] ints = jdbcTemplate.batchUpdate(sql,batchArgs); System.out.println(Arrays.toString(ints)); }
@Test public void batchUpdateBook(){ List<Object[]> list = new ArrayList<>(); Object[] o1 = {"java1","j1",5}; Object[] o2 = {"mysql2","m2",6}; Object[] o3 = {"php3","p3",7}; list.add(o3); list.add(o2); list.add(o1); service.batchUpdateBook(list); }
-
JdbcTemplate 实现批量删除操作
@Override public void batchDeleteBook(List<Object[]> batchArgs) { String sql = "delete from t_book where user_id = ?"; int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs); System.out.println(Arrays.toString(ints)); }
@Test public void batchDeleteBook(){ List<Object[]> list = new ArrayList<>(); Object[] o1 = {5}; Object[] o2 = {6}; list.add(o2); list.add(o1); service.batchDeleteBook(list); }
5、事务操作(事务概念)
-
什么是事务
- 事务是数据库操作的最基本单元,逻辑上的一组操作,要么都成功 要么都失败
- 典型场景:银行转账
- 李四 转账 100 元 给 张三
- 李四 少 100,张三 多 100
-
事务四个特性(ACID)
- 原子性
- 一致性
- 隔离性
- 持久性
-
事务操作(搭建事务操作环境)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Uhx0EBYv-1647143877501)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220227120539394.png)]
-
创建数据库表,添加记录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-htlt2hKe-1647143877501)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220227120624019.png)]
-
创建 service,搭建 dao,完成对象创建和注入关系
-
service 注入 dao,在 dao 注入 JdbcTemplate,在 JdbcTemplate 注入 DataSource
package com.atchan.jdbcTemplate.dao; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import javax.annotation.Resource; @Repository public class UserDaoImpl implements UserDao{ @Resource JdbcTemplate jdbcTemplate; @Override public void addMoney() { String sql = "update t_account set money=money-? where id=?"; jdbcTemplate.update(sql, 100, 1); } @Override public void updateMoney() { String sql = "update t_account set money=money+? where id=?"; jdbcTemplate.update(sql, 100, 2); } }
package com.atchan.jdbcTemplate.service; import com.atchan.jdbcTemplate.dao.UserDao; import org.springframework.stereotype.Service; import javax.annotation.Resource; @Service public class UserService { @Resource UserDao userDao; public void account(){ userDao.addMoney(); userDao.updateMoney(); } }
-
-
上面代码,如果正常执行没有问题的,但是如果代码执行过程中出现异常,有问题
package com.atchan.jdbcTemplate.service; import com.atchan.jdbcTemplate.dao.UserDao; import org.springframework.stereotype.Service; import javax.annotation.Resource; @Service public class UserService { @Resource UserDao userDao; public void account(){ userDao.addMoney(); //模拟异常 int i = 1 / 0; userDao.updateMoney(); } }
-
上面问题如何解决呢?
- 使用事务进行解决
-
事务操作过程
package com.atchan.jdbcTemplate.service; import com.atchan.jdbcTemplate.dao.UserDao; import org.springframework.stereotype.Service; import javax.annotation.Resource; @Service public class UserService { @Resource UserDao userDao; public void account(){ try { //第一步开启事务 //第二步进行业务操作 userDao.addMoney(); //模拟异常 int i = 1 / 0; userDao.updateMoney(); //第三步如果没有异常 提交事务 }catch (Exception e){ e.printStackTrace(); //第四步出现异常回滚事务 } } }
-
-
5.1 事务操作(Spring 事务管理介绍)
-
事务添加到JavaEE三层架构里的Service层(业务逻辑层)
-
在Spring进行事务管理操作
- 有两种方式:编程式事务管理 和 声明式事务管理
-
声明式事务管理
- 基于注解方式(使用)
- 基于xml配置文件方式
-
在Spring进行声明式事务管理,底层用的是AOP原理
-
Spring事务管理API
-
提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oVe4DgjD-1647143877501)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220227152847037.png)]
-
5.2 事务操作(注解声明式事务管理)
-
在 spring 配置文件配置事务管理器
<!--创建事务管理器--> <bean id="TransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--注入数据源--> <property name="dataSource" ref="dataSource"/> </bean>
-
在 spring 配置文件,开启事务注解
-
在 spring 配置文件引入名称空间 tx
<!--开启事务注解--> <tx:annotation-driven transaction-manager="TransactionManager"></tx:annotation-driven>
-
-
在Service类上(或者方法上)添加事务注解
- @Transactional,这个注解可以添加在类 或 方法上
- 如果把这个注解添加到类上,这个类的所有方法都会添加上事务
- 如果把这个注解添加到方法上,为这个方法添加事务
package com.atchan.jdbcTemplate.service; import com.atchan.jdbcTemplate.dao.UserDao; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; @Service @Transactional public class UserService { @Resource UserDao userDao; public void account() { userDao.addMoney(); //模拟异常 int i = 1 / 0; userDao.updateMoney(); } }
5.3 事务操作(声明式事务管理参数配置)
-
在 service 类上面添加注解@Transactional,在这个注解里面可以配置事务相关参数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zqss4IAx-1647143877502)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220227181209083.png)]
-
propagation:事务传播行为
-
多事务方法直接进行调用,这个过程中事务 是如何进行管理的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8JS7Y2lu-1647143877502)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220227181350261.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fRFiVHJF-1647143877503)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220227181430005.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UB92edj3-1647143877503)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220227181537584.png)]
-
ioslation:事务隔离级别
-
事务有特性成为隔离性,多事务操作之间不会产生影响,不考虑隔离性会产生很多问题
-
有三个问题:脏读,不可重复度,幻读
-
脏读:一个未提交事务读取到另一个未提交事务的数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BpSZeBrt-1647143877503)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220227191822661.png)]
-
不可重复读:一个未提交的事务读取到了另一个已提交事务的数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hq5HRvre-1647143877504)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220227192203485.png)]
-
幻读:一个未提交的事务读取到了另一个已提交事务添加的数据
-
解决:通过设置事务隔离级别,解决读问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TNrDx0M1-1647143877504)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220227192412324.png)]
-
-
timeout:超时时间
- 事务需要在一定时间内进行提交,如果不提交进行回滚
- 默认值是-1,设置时间以秒为单位计算
-
readOnly:是否只读
- 读:查询操作,写:添加、修改、删除操作
- readOnly默认值是false,表示可以查询、可以增删改操作
- 设置 readOnly 值是 true,设置成 true 之后,只能查询
-
rollbackFor:回滚
- 设置出现那些异常进行事务回滚
-
noRollbackFor:不回滚
- 设置出现哪些异常不进行事务回滚
-
-
-
5.4 事务操作(XML 声明式事务管理)
-
在 spring 配置文件中进行配置
- 第一步 配置事务管理器
- 第二步 配置通知
- 第三步 配置切入点和切面
<!--1 创建事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--注入数据源--> <property name="dataSource" ref="dataSource"></property> </bean> <!--2 配置通知--> <tx:advice id="txadvice"> <!--配置事务参数--> <tx:attributes> <!--指定哪种规则的方法上面添加事务--> <tx:method name="accountMoney" propagation="REQUIRED"/> <!--<tx:method name="account*"/>--> </tx:attributes> </tx:advice> <!--3 配置切入点和切面--> <aop:config> <!--配置切入点--> <aop:pointcut id="pt" expression="execution(* com.atguigu.spring5.service.UserService.*(..))"/> <!--配置切面--> <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/> </aop:config>
5.5 事务操作(完全注解声明式事务管理)
-
创建配置类,使用配置类替代 xml 配置文件
package com.atchan.jdbcTemplate.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; @Configuration //配置类 @ComponentScan(basePackages = "com.atchan.jdbcTemplate") //组件扫描 @EnableTransactionManagement //开启事务 public class txConfig { //创建数据库连接池 @Bean public DruidDataSource getMyDruidDataSource(){ DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/user_db?serverTimezone=GMT"); dataSource.setUsername("root"); dataSource.setPassword("root"); return dataSource; } //创建 JdbcTemplate 对象 @Bean public JdbcTemplate getMyJdbcTemplate(DataSource dataSource){ //到 ioc 容器中根据类型找到 dataSource JdbcTemplate jdbcTemplate = new JdbcTemplate(); //注入 dataSource jdbcTemplate.setDataSource(dataSource); return jdbcTemplate; } //创建事务管理器 @Bean public DataSourceTransactionManager getMyDataSourceTransactionManager(DataSource dataSource){ DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); transactionManager.setDataSource(dataSource); return transactionManager; } }
6、Spring5 框架新功能
6.1 整个 Spring5 框架的代码基于 Java8,运行时兼容 JDK9,许多不建议使用的类和方 法在代码库中删除
6.2 Spring 5.0 框架自带了通用的日志封装
-
Spring5 已经移除 Log4jConfigListener,官方建议使用 Log4j2
-
Spring5 框架整合 Log4j2
-
第一步 引入 jar 包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fHxL14KW-1647143877504)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220228131440644.png)]
-
第二步 创建 log4j2.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?> <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <!--Configuration后面的status用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,可以看到log4j2内部各种详细输出--> <configuration status="INFO"> <!--先定义所有的appender--> <appenders> <!--输出日志信息到控制台--> <console name="Console" target="SYSTEM_OUT"> <!--控制日志输出的格式--> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </console> </appenders> <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效--> <!--root:用于指定项目的根日志,如果没有单独指定Logger,则会使用root作为默认的日志输出--> <loggers> <root level="info"> <appender-ref ref="Console"/> </root> </loggers> </configuration>
-
6.3 Spring5 框架核心容器支持@Nullable 注解
-
@Nullable 注解可以使用在方法上,属性上,参数上,表示方法返回可以为空,属性值可以为空,参数值可以为空
-
注解用在方法上,方法返回值可以为空
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GbQochOp-1647143877505)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220228131955530.png)]
-
注解使用在方法参数里面,方法参数可以为空
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FnnkOiTz-1647143877505)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220228132057196.png)]
-
注解使用在属性上面,属性值可以为空
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G2ClLCei-1647143877505)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220228132151587.png)]
6.4 Spring5 核心容器支持函数式风格 GenericApplicationContext
@Test
public void testGenericApplicationContext(){
//函数式风格创建对象,交给 spring 进行管理
//1 创建 GenericApplicationContext 对象
GenericApplicationContext genericApplicationContext = new GenericApplicationContext();
//2 调用 context 的方法对象注册
genericApplicationContext.refresh();
genericApplicationContext.registerBean("user", User.class,() -> new User());
//3 获取在 spring 注册的对象
User user = (User) genericApplicationContext.getBean("user");
System.out.println(user);
}
6.5 Spring5 支持整合 JUnit5
-
整合 JUnit4
-
第一步 引入 Spring 相关针对测试依赖
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pP3V8XIj-1647143877506)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220228164508767.png)]
-
第二步 创建测试类,使用注解方式完成
package com.atchan.jdbcTemplate.test; import com.atchan.jdbcTemplate.config.txConfig; import com.atchan.jdbcTemplate.service.UserService; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.testng.annotations.Test; @RunWith(SpringJUnit4ClassRunner.class) //单元测试框架 //@ContextConfiguration("classpath:bean1.xml") //加载配置文件 @ContextConfiguration(classes = {txConfig.class}) //加载配置文件 public class JTest4 { @Autowired private UserService userService; @Test public void test1(){ userService.account(); } }
-
-
Spring5 整合 JUnit5
-
第一步 引入 JUnit5 的 jar 包
-
第二步 创建测试类,使用注解完成
@ExtendWith(SpringExtension.class) @ContextConfiguration("classpath:bean1.xml") public class JTest5 { @Autowired private UserService userService; @Test public void test1() { userService.accountMoney(); } }
-
使用一个复合注解替代上面两个注解完成整合
@SpringJUnitConfig(locations = "classpath:bean1.xml") public class JTest5 { @Autowired private UserService userService; @Test public void test1() { userService.accountMoney(); } }
-
7、Spring5 框架新功能(Webflux)
-
SpringWebflux 介绍
-
是Spring5添加的新模块,用于web开发的,功能和SpringMVC类似的,Webflux使用当前一种比较流行响应式编程出现的框架
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4IqUr8Ka-1647143877506)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220228182246164.png)]
-
使用传统web框架,比如SpringMVC,这些基于Servlet容器,Webflux是一种异步非阻塞的框架,异步非阻塞的框架在Servlet3.1之后才支持,核心基与Reactor的相关API实现的
-
什么是异步非阻塞
- 异步和同步
- 非阻塞和阻塞
- 上面都是针对对象不一样
- **异步和同步针对调用者:**调用者发送请求,如果等着对方回应之后才去做其他事情就是同步,如果发送请求之后不等着对方回应就去做其他事情就是异步
- **阻塞和非阻塞针对被调用者:**被调用者收到请求后,做完请求任务之后才给出反馈就是阻塞,受到请求之后马上给出反馈然后再去做事情就是非阻塞
-
Webflux特点:
- 第一 非阻塞式:在有限的资源下,提高系统吞吐量和伸缩性,以Reactor为基础实现响应式编程
- 第二 函数式编程:Spring5框架基于Java8,Webflux使用Java8函数式编程方式实现路由请求
-
比较SpringMVC
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CzePIBmk-1647143877507)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220228183522710.png)]
- 第一 两个框架都可以使用注解方式,都运行在 Tomet 等容器中
- 第二 SpringMVC 采用命令式编程,Webflux 采用异步响应式编程
-
-
响应式编程(Java实现)
-
什么是响应式编程:
响应式编程是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。 电子表格程序就是响应式编程的一个例子。单元格可以包含字面值或类似"=B1+C1"的公 式,而包含公式的单元格的值会依据其他单元格的值的变化而变化
-
Java8及其之前版本
-
提供的观察者模式两个类Observer 和 Observable
package com.example.spring_webflux.reactor8; import java.util.Observable; public class ObserverDemo extends Observable { public static void main(String[] args) { ObserverDemo observerDemo = new ObserverDemo(); //添加观察者 observerDemo.addObserver((o,arg)->{ System.out.println("发生变化!"); }); observerDemo.addObserver((o,arg)->{ System.out.println("手动被观察者通知,准备改变"); }); //数据变化 observerDemo.setChanged(); //通知 observerDemo.notifyObservers(); } }
-
-
响应式编程(Reactor实现)
-
响应式编程操作中,Reactor是满足Reactive规范框架
-
Reactor有两个核心类,Mono和Flux,这两个类实现接口Publisher,提供丰富操作符,Flux对象实现发布者,返回N个元素;Mono实现发布者,返回0个或1个元素
-
Flux和Mono都是数据流的发布者,使用Flux和Mono都可以发出三种数据信号:元素值、错误信号、完成信号,错误信号和完成信号都代表终止信号,终止信号用于告诉订阅者数据流结束了,错误信号终止数据流同时把错误信息传递给订阅者
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Is2HOkCO-1647143877508)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220228195129608.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XZXGuua2-1647143877508)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220228195143159.png)]
-
代码演示Flux和Mono
-
第一步导入依赖
<dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-core</artifactId> <version>3.3.22.RELEASE</version> </dependency>
-
第二步编写代码
package com.example.spring_webflux.reactor8; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class TestReactor { public static void main(String[] args) { //just方法直接声明 Flux.just(1,2,3,4); Mono.just(1); //其他方法 Integer[] arr = {1,2,3,5,89}; Flux.fromArray(arr); List<Integer> list = Arrays.asList(arr); Flux.fromIterable(list); Stream<Integer> stream = list.stream(); Flux.fromStream(stream); } }
-
-
三种信号特点
- 错误信号和完成信号都是终止符号,不能共存
- 如果没有发送任何元素值,而是发送错误信号和完成信号,表示空数据流
- 如果没有错误信号,没有完成信号,表示是无限数据流
-
调用just或者其他方法只是声明数据流,数据流并没有发出,只有进行订阅之后才能触发数据流,不订阅什么都不会发生
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I07c37FG-1647143877509)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220228200909047.png)]
-
操作符
-
对数据流进行一道道操作,称为操作符,不如流水线的一道道工序
-
第一map 元素映射新元素
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FobWFNq4-1647143877509)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220228201127782.png)]
-
第二 flatMap 元素映射为流
-
把每个元素转换流,把转换之后多个流合并大的流
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8aqFtsAg-1647143877510)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220228201204838.png)]
-
-
-
-
-
SpringWebflux 执行流程和核心 API
SpringWebflux基于Reactor,默认使用Netty,Netty 是高性能的NIO框架,异步非阻塞的框架
-
Netty
-
BIO
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ytloyprX-1647143877512)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220301130542898.png)]
-
NIO
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tIOCSpxT-1647143877513)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220301130558610.png)]
-
-
SpringWebflux执行过程和SpringMVC相似的
-
SpringWebflux 核心控制器 DispatchHandler,实现接口 WebHandler
-
接口 WebHandler 有一个方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P6h43psL-1647143877514)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220301130722921.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dHf1sXlr-1647143877514)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220301130743552.png)]
-
-
-
7、总结
- IOC容器
- IOC底层实现原理(工厂、反射等)
- IOC接口((BeanFactory)
- IOC操作Bean管理(基于xml)
- IOC操作Bean管理(基于注解)
- AOP
- AOP底层实现原理:动态代理,有接口(JDK动态代理),没有接口(CGLIB动态代理)
- 术语:切点、通知(增强)、切面
- 基于AspectJ实现AOP操作
- JdbcTemplate
- 使用 JdbcTemplate 实现数据库 curd 操作
- 使用 JdbcTemplate 实现数据库批量操作
- 事务管理
- 事务概念
- 重要概念(传播行为和隔离级别)
- 基于注解实现声明式事务管理
- 完全注解方式实现声明式事务管理
- Spring5 新功能
-
整合日志框架
-
@Nullable 注解
-
函数式注册对象
-
整合 JUnit5 单元测试框架
-
SpringWebflux 使用
Id>
reactor-core
3.3.22.RELEASE
```-
第二步编写代码
package com.example.spring_webflux.reactor8; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class TestReactor { public static void main(String[] args) { //just方法直接声明 Flux.just(1,2,3,4); Mono.just(1); //其他方法 Integer[] arr = {1,2,3,5,89}; Flux.fromArray(arr); List<Integer> list = Arrays.asList(arr); Flux.fromIterable(list); Stream<Integer> stream = list.stream(); Flux.fromStream(stream); } }
-
三种信号特点
- 错误信号和完成信号都是终止符号,不能共存
- 如果没有发送任何元素值,而是发送错误信号和完成信号,表示空数据流
- 如果没有错误信号,没有完成信号,表示是无限数据流
-
调用just或者其他方法只是声明数据流,数据流并没有发出,只有进行订阅之后才能触发数据流,不订阅什么都不会发生
[外链图片转存中…(img-I07c37FG-1647143877509)]
-
操作符
-
对数据流进行一道道操作,称为操作符,不如流水线的一道道工序
-
第一map 元素映射新元素
[外链图片转存中…(img-FobWFNq4-1647143877509)]
-
第二 flatMap 元素映射为流
-
把每个元素转换流,把转换之后多个流合并大的流
[外链图片转存中…(img-8aqFtsAg-1647143877510)]
-
-
-
-
-
SpringWebflux 执行流程和核心 API
SpringWebflux基于Reactor,默认使用Netty,Netty 是高性能的NIO框架,异步非阻塞的框架
-
Netty
-
BIO
[外链图片转存中…(img-ytloyprX-1647143877512)]
-
NIO
[外链图片转存中…(img-tIOCSpxT-1647143877513)]
-
-
SpringWebflux执行过程和SpringMVC相似的
-
SpringWebflux 核心控制器 DispatchHandler,实现接口 WebHandler
-
接口 WebHandler 有一个方法
[外链图片转存中…(img-P6h43psL-1647143877514)]
[外链图片转存中…(img-dHf1sXlr-1647143877514)]
-
-
-
7、总结
- IOC容器
- IOC底层实现原理(工厂、反射等)
- IOC接口((BeanFactory)
- IOC操作Bean管理(基于xml)
- IOC操作Bean管理(基于注解)
- AOP
- AOP底层实现原理:动态代理,有接口(JDK动态代理),没有接口(CGLIB动态代理)
- 术语:切点、通知(增强)、切面
- 基于AspectJ实现AOP操作
- JdbcTemplate
- 使用 JdbcTemplate 实现数据库 curd 操作
- 使用 JdbcTemplate 实现数据库批量操作
- 事务管理
- 事务概念
- 重要概念(传播行为和隔离级别)
- 基于注解实现声明式事务管理
- 完全注解方式实现声明式事务管理
- Spring5 新功能
- 整合日志框架
- @Nullable 注解
- 函数式注册对象
- 整合 JUnit5 单元测试框架
- SpringWebflux 使用