Spring框架概述
1、Spring是轻量级的开源的JavaEE框架
2、Spring可以解决企业应用开发的复杂性
3、Spring有两个核心功能
(1)IOC:控制反转,把创建对象过程交给Spring进行管理
(2)Aop:面向切面,不修改源代码进行功能增强
4、Spring特点
(1)方便解耦,简化开发
(2)Aop编程支持
(3)方便程序测试
(4)方便和其他框架进行整合
(5)方便进行事务操作
(6)降低API开发难度
IOC
1、什么是IOC
(1)控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理
(2)使用IOC目的:为了降低耦合度
2、IOC底层原理
xml解析、工厂模式、反射
工厂模式
class UserFactory {
public static UserDao getDao(){
return new UserDao();
}
}
IOC过程
第一步:xml配置文件,配置创建的对象
<bean id="dao" class="com.example.UserDao"></bean>
第二步:有service类和dao类,创建工厂类
class UserFactory {
public static UserDao getDao() {
String classValue = class属性值; //xml解析(dog4j解析)
Class clazz = Class.forName(classValue); //通过反射创建对象
return (UserDao) clazz.newInstance();
}
}
IOC(接口)
1、IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
2、Spring提供IOC容器实现两种方式:(两个接口)
(1)BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用
加载配置文件时不会创建对象,在获取对象(使用)才去创建对象
(2)ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用
加载配置文件时就会在配置文件对象进行创建
3、ApplicationContext接口有实现类
FileSystemXmlApplicationContext
ClassPathXmlApplicationContext
IOC操作Bean管理
1、什么是Bean管理
Bean管理指的是两个
(1)Spring创建对象
(2)Spring注入属性
2、Bean管理操作有两种方式
(1)基于xml配置文件方式实现
(2)基于注解方式实现
基于xml方式创建对象
<bean id="dao" class="com.example.UserDao"></bean>
- 在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
- 在bean标签有很多属性,介绍常用的属性
- id属性:唯一标识
- class属性:类全路径(包类路径)
- 创建对象的时候,默认也是执行无参构造方法
基于xml方式注入属性
- DI:依赖注入,就是注入属性
第一种注入方式,使用set方法进行注入
<bean id="book" class="com.examole.Book">
<property name="bname" value="易筋经"></property>
<property name="bauthor" value="达摩老祖"></property>
</bean>
使用property完成属性注入
name:类里面属性名称
value:向属性注入的值
第二种注入方式,使用有参构造进行注入
(1)创建类,定义属性,创建属性对应有参构造方法
(2)在Spring配置文件中进行配置
<bean id="orders" class="spring5.Order">
<constructor-arg name="oname" value="computer"/>
<constructor-arg name="address" value="china"/>
</bean>
p名称空间注入
(1)使用p名称空间注入,可以简化基于xml配置方式
第一步,添加p名称空间在配置文件中
第二步,进行属性注入,在bean标签里面进行操作
<bean id="order" class="spring5.Book" p:bname="computer" p:bauthor="china"></bean>
IOC操作Bean管理(xml注入其他类型属性)
1、字面量
(1)null值
<property name="address">
<null/>
</property>
(2)属性值包含特殊符号
1、把<>进行转义<>
2、把带特殊符号内容写到CDATA
<property name="address">
<value><![CDATA[<<南京>>]]></value>
</property>
注入属性:外部bean
(1)创建两个类service类和dao类
(2)在service调用dao里面的方法
(3)在spring配置文件中进行配置
<bean id="userService" class="com.example.spring5.service.UserService">
<!--注入userDao对象
name属性:类里面属性名称
ref属性:创建userDao对象bean标签id值
-->
<property name="userDao" ref="userDaoImpl"></property>
</bean>
<bean id="userDaoImpl" class="com.example.spring5.dao.UserDaoImpl"></bean>
注入属性——内部bean
(1)一对多关系:部门和员工
(2)在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示
(3)在spring配置文件中进行配置
<bean id="emp" class="com.example.spring5.bean.Emp">
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property>
<property name="dept">
<bean id="dept" class="com.example.spring5.bean.Dept">
<property name="dname" value="安保部"></property>
</bean>
</property>
</bean>
注入属性——级联赋值
<bean id="emp" class="com.example.spring5.bean.Emp">
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property>
<property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.example.spring5.bean.Dept">
<property name="dname" value="安保部"></property>
</bean>
第二种写法
<bean id="emp" class="com.example.spring5.bean.Emp">
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property>
<property name="dept" ref="dept"></property>
<property name="dept.dname" value="技术部"></property>
</bean>
<bean id="dept" class="com.example.spring5.bean.Dept">
<property name="dname" value="安保部"></property>
</bean>
IOC操作Bean管理(xml注入集合属性)
1、注入数组类型属性
2、注入List集合类型属性
3、注入Map集合类型
<bean id="stu" class="com.example.spring5.collectiontype.Stu">
<property name="courses">
<array>
<value>java课程</value>
<value>数据库课程</value>
</array>
</property>
<property name="list">
<list>
<value>张三</value>
<value>小三</value>
</list>
</property>
<property>
<map>
<entry key="JAVA" value="java"></entry>
<entry key="PHP" value="php"></entry>
</map>
</property>
<property>
<set>
<value>MySQL</value>
<value>Redis</value>
</set>
</property>
</bean>
在集合里面设置对象类型值
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
把集合注入部分提取出来
(1)在Spring配置文件中引入名称空间util
(2)使用util标签完成list集合注入提取
<util:list id="bookList">
<value>java</value>
<value>cpp</value>
</util:list>
<property name="list" ref="booklist"></property>
IOC操作Bean管理(FactoryBean)
1、Spring有两种bean,一种普通bean,另外一种工厂bean(FactoryBean)
2、普通bean:在配置文件中定义bean类型就是返回类型
3、工厂bean:在配置文件定义bean类型可以和返回类型不一样
第一步,创建类,让这个类作为工厂bean,实现接口FactoryBean
第二步,实现接口里面的方法,在实现的方法中定义返回的bean类型
public class MyBean implements FactoryBean<Book> {
public Book getObject() throws Exception {
Book book = new Book();
book.setBname("abc");
return book;
}
public Class<?> getObjectType() {
return null;
}
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
}
bean作用域
1、在Spring里面,设置创建bean实例是单实例还是多实例
2、在Spring里面,默认情况下,bean是单实例对象
3、如何设置单实例还是多实例
(1)在spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例
(2)scope属性值
第一个值 默认值,singleton,表示单实例对象
第二个值prototype,表示是多实例对象
(3)singleton和prototype
第一 singleton单实例,prototype多实例
第二 设置scope值是singleton时,加载spring配置文件时就会创建单实例对象
设置scope值是prototype时,不是在加载spring配置文件时创建对象,在调用getBean方法时创建多实例对象
request
session
bean生命周期
1、生命周期
从生命创建到对象销毁的过程
2、bean生命周期
(1)通过构造器创建bean实例(无参数构造)
(2)为bean的属性设置值和对其他bean引用(调用set方法)
(3)调用bean的初始化的方法(需要进行配置初始化的方法) init-method=""
(4)bean可以使用了(对象获取到了)
(5)当容器关闭时,调用bean的销毁方法(需要进行配置销毁的方法)destory-method=""
context.close()
bean的后置处理器
bean生命周期有七步
(1)通过构造器创建bean实例(无参数构造)
(2)为bean的属性设置值和对其他bean引用(调用set方法)
(3)把bean实例传递给bean后置处理器的方法postProcessBeforeInitialization
(4)调用bean的初始化的方法(需要进行配置初始化的方法) init-method=""
(5)把bean实例传递给bean后置处理器的方法postProcessAfterInitialization
(6)bean可以使用了(对象获取到了)
(7)当容器关闭时,调用bean的销毁方法(需要进行配置销毁的方法)destory-method=""
添加后置处理器
(1)创建类,实现接口BeanPostProcessor,创建后置处理器
(2)<bean id="myBeanPost" class="com.example.spring5.MyBeanPost"></bean>
xml自动装配
1、什么是自动装配?
根据指定装配规则(属性名称或者属性类型),spring自动将匹配的属性值进行注入
(1)根据属性名称自动注入
bean标签属性autoware,配置自动装配
autoware属性常用两个值:
byName根据属性名称注入,注入值bean的id值和类属性名称一样
byType根据属性类型注入
autowire="byName"
(2)根据属性类型自动注入
autowire="byType"
外部属性文件
1、直接配置数据库信息
2、引入外部属性文件配置数据库连接池
(1)创建外部属性文件,properties格式文件,写数据库信息
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/userdb
prop.username=root
prop.password=root
(2)把外部properties属性文件引入到spring配置文件中
-
引入context名称空间
-
在spring配置文件使用标签引入外部属性文件
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DtuidDataSource">
<property name="dirverClassName" value="${prop.driverClass}"></property>
<property name="url" value="${prop.url}"></property>
<property name="username" value="${prop.userName}"></property>
<property name="password" value="${prop.password}"></property>
</bean>
IOC操作Bean管理(基于注解方式)
1、什么是注解
(1)注解是代码特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值。。。)
(2)使用注解,注解作用在类上面,方法上面,属性上面
(3)使用注解目的:简化xml配置
2、Spring针对Bean管理中创建对象提供注解
(1)@Component
(2)@Service
(3)@Controller
(4)@Repository
- 上面四个注解功能是一样的,都可以用来创建bean实例
3、基于注解方式实现对象创建
第一步 引入依赖
第二步 开启组件扫描
1、如果扫描多个包,多个包使用逗号隔开
2、扫描包上层目录
<context:component-scan base-package="com.examole"></context:component-scan>
第三步 创建类,在类上面添加创建对象注解
在注解里面value属性值可以省略不写
默认值是类名称,首字母小写
4、开启组件扫描细节配置
示例:
use-default-filters="false"
表示现在不使用默认filter,自己配置filter
context:include-filter
设置扫描哪些内容
<context:component-scan base-package="com.example" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
示例:
下面配置扫描包所有内容
context:exclude-filter
:设置哪些内容
<context:component-scan base-package="com.example" use-default-filters="false">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
5、基于注解方式实现属性注入
(1)@Autowired
根据属性类型进行自动装配
第一步把service和dao对象创建,在service和dao类添加创建对象注解
第二步 在service注入dao对象,在service类添加dao类型属性,在属性上面使用注解,不需要添加set方法
(2)@Qualifier
根据属性名称进行注入
这个@Qualifier注解的使用,和上面@Autowired一起使用
@Autowired
@Qualifier(value=“userDaoImpl”)
(3)@Resource
可以根据类型注入,可以根据名称注入
@Resource 根据类型注入
@Resource(name=“userDaoImpl”) 根据名称注入
private UserDao userDao;
(4)@Value
注入普通类型属性
@Value(value=“abc”)
private String name;
6、完全注解开发
(1)创建配置类,替代xml配置文件
@Configuration //作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"spring5"})
public class SpringConfig {
}
(2)编写测试类
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
context.getBean("userService",UserService.class);
AOP
1、什么是AOP
(1)面向切面编程
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率
(2)通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
2、AOP底层使用动态代理
(1)有两种情况动态代理
第一种 有接口情况,使用JDK动态代理
创建接口实现类的代理对象,增强类的方法
第二种 没有接口情况,使用CGLIB动态代理
创建子类的代理对象,增强类的方法
3、JDK动态代理
使用Proxy类里面的方法创建代理对象
(1)调用newProxyInstance方法
方法有3个参数:
第一:类加载器
第二:增强方法所在的类,这个类实现的接口,支持多个接口
第三:实现这个接口InvocationHandler,创建代理对象,写增强的方法
(2)编写JDK动态代理代码
一、创建接口,定义方法
public interface UserDao {
int add(int a, int b);
String update(String id);
}
二、创建接口实现类,实现方法
public class UserDaoImpl implements UserDao{
public int add(int a, int b) {
return a+b;
}
public String update(String id) {
return id;
}
}
三、使用Proxy类创建接口代理对象
public class JDKProxy {
public static void main(String[] args) {
//创建接口实现类代理对象
Class[] interfaces = {UserDao.class};
UserDaoImpl userDao = new UserDaoImpl();
UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
int res = dao.add(1, 2);
System.out.println(res);
System.out.println(dao.update("abc"));
}
}
//创建代理对象代码
class UserDaoProxy implements InvocationHandler{
//1、把创建的是谁的代理对象,把谁传递过来
//有参数构造传递
private Object obj;
public UserDaoProxy(Object obj){
this.obj = obj;
}
//增强的逻辑
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法之前
System.out.println("方法之前执行..." + method.getName() + "传递的参数..." + Arrays.toString(args));
//被增强的方法执行
Object res = method.invoke(obj, args);
//方法之后
System.out.println("方法之后执行..." + obj);
return res;
}
AOP术语
1、连接点
类里面哪些方法可以被增强,这些方法称为连接点
2、切入点
实际被增强的方法,称为切入点
3、通知(增强)
(1)实际增强的逻辑部分称为通知(增强)
(2)通知有多种类型
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知
4、切面
是动作
把通知应用到切入点过程
AOP操作
1、Spring框架一般基于AspectJ实现AOP操作
什么是AspectJ?
- AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作
2、基于AspectJ实现AOP操作
(1)基于xml配置文件实现
(2)基于注解方式实现(使用)
3、在项目工程里面引入AOP相关依赖
4、切入点表达式
(1)切入点表达式的作用:知道对哪个类里面的哪个方法进行增强
(2)语法结构:
Execution(【权限修饰符】【返回类型】【类全路径】【方法名称】(【参数列表】))
例:对com.example.dao.BookDao类里面的add进行增强
execution(* com.example.dao.BookDao.add(..))
例:对com.example.dao.BookDao类里面的所有方法进行增强
execution(* com.example.dao.BookDao.*(..))
例:对com.example.dao包里面所有类,类里面所有方法进行增强
execution(* com.example.dao.*.*(..))
AspectJ注解
1、创建类,在类里面定义方法
public class User {
public void add(){
System.out.println("add.....");
}
}
2、创建增强类(编写增强逻辑)
在增强类里面,创建方法,让不同方法代表不同通知类型
public class UserProxy {
//前置通知
public void before(){
System.out.println("before....");
}
}
3、进行通知的配置
(1)在spring配置文件中,开启注解扫描
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UtbdNRv9-1642483402610)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210812145544485.png)]
(2)使用注解创建User和UserProxy对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-08osHbdt-1642483402611)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210812145010581.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cok1ykXC-1642483402612)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210812145035552.png)]
(3)在增强类上面添加注解@Aspect
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pzny78CO-1642483402613)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210812145142744.png)]
(4)在spring配置文件中开启生成代理对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MYJ6kvpM-1642483402615)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210812145600274.png)]
4、配置不同类型的通知
(1)在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HctbuLpY-1642483402615)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210812150030623.png)]
@After最终通知
@AfterReturning后置通知(返回通知)
@AfterThrowing
@Around
public void around(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("环绕之前......");
//被增强的方法执行
proceedingJoinPoint.proceed();
System.out.println("环绕之后......");
}
5、公共切入点抽取
@Pointcut(value="execution(* com.example.spring5.aop.*.*)")
public void pointdemo(){
}
@Before(value="pointdemo()")
6、有多个增强类用对同一个方法进行增强,设置增强类优先级
(1)在增强类上面添加注解@Order(数字类型值),数字类型值越小优先级越高
@Order(1)
AspectJ配置文件
1、创建两个类,增强类和被增强类,创建方法
2、在spring配置文件中创建两个类对象
<bean id="book" class="com.example.spring5.aop.Book"></bean>
<bean id="bookProxy" class="com.example.spring5.aop.BookProxy"></bean>
3、在spring配置文件中配置切入点
<aop:config>
<!--切入点-->
<aop:pointcut id="p" expression="execution(* com.example.spring5.aop.Book.buy(..))"/>
<!--配置切面-->
<aop:aspect ref="bookProxy">
<!--增强作用在具体的方法上-->
<aop:before method="before" pointcut-ref="p"/>
</aop:aspect>
</aop:config>
7、完全使用注解开发
创建配置类,不需要创建xml配置文件
@Configuration
@ComponentScan(basePackages={“com.example”})
@EnableAspectJAutoProxy(proxyTargetClass = true)
JdbcTemplate
1、概念:Spring框架对JDBC进行封装,使用JdbcTemplate方便实现对数据库操作
2、准备工作
(1)引入相关jar包(相关依赖)
(2)在spring配置文件配置数据库连接池
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///user"></property>
<property name="username" value="root"></property>
<property name="password" value="westos"></property>
</bean>
(3)配置JdbcTemplate对象,注入DataSource
<bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
(4)创建service类,创建dao类,在dao注入jdbcTemplate对象
配置文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HNbheVN2-1642483402615)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210812235121396.png)]
- Service
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6yS4BEik-1642483402617)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210812235214067.png)]
- Dao
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U1ouvVTN-1642483402618)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210812235229705.png)]
JdbcTemplate操作数据库(添加)
1、对应数据库表创建实体类
2、编写service和dao
(1)在dao进行数据库添加操作
(2)调用JdbcTemplate对象里面update方法实现添加操作
update(String sql, Object... args)
- 有两个参数
- 第一个参数:sql语句
- 第二个参数:可变参数,设置sql语句值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lLQk3hPf-1642483402619)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813001737326.png)]
3、测试类
public class TestBook {
@Test
public void test(){
ApplicationContext cxt = new ClassPathXmlApplicationContext("bean.xml");
BookService bookService = cxt.getBean("bookService", BookService.class);
bookService.addBook(new Book(null,"haha","hahahah","hahhaha","hahhah"));
}
}
JdbcTemplate操作数据库(修改和删除)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JEG2Tci9-1642483402620)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813003336321.png)]
JdbcTemplate操作数据库(查询)
查询返回某个值
1、查询表里面有多少条记录,返回某个值
使用JdbcTemplate实现查询返回某个值代码
queryForObject(String sql,Class<T> requiredType)
- 有两个参数
- 第一个参数:sql语句
- 第二个参数:返回类型Class
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LnsLECYf-1642483402620)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813004915060.png)]
查询返回对象
1、场景:查询图书详情
2、JdbcTemplate实现查询返回对象
queryForObject(String sql, RowMapper<T> rowMapper, Object.. args)
- 有三个参数
- 第一个参数:sql语句
- 第二个参数:RowMapper,是接口,返回不同类型数据,使用这个接口里面实现类完成数据封装
- 第三个参数:sql语句值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qtINHouy-1642483402621)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813131900793.png)]
查询返回集合
1、场景:查询图书列表分页
2、调用JdbcTemplate方法实现查询返回集合
query(String sql, RowMapper<T> rowMapper, Object... args)
- 有三个参数
- 第一个参数:sql语句
- 第二个参数:RowMapper,是接口,返回不同类型数据,使用这个接口里面实现类完成数据封装
- 第三个参数:sql语句值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-23dhOLC2-1642483402622)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813132726558.png)]
JdbcTemplate操作数据库——批量添加功能
1、批量操作:操作表里面多条记录
2、JdbcTemplate实现批量添加操作
batchUpdate(String sql, List<Object[]> batchArgs)
- 有两个参数
- 第一个参数:sql语句
- 第二个参数:List集合,添加多条记录数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ojxHqhyg-1642483402623)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813134159919.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-klAYwanh-1642483402623)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813135036569.png)]
批量删除和修改
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fcvign1k-1642483402625)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813135328502.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rwziDw2Q-1642483402626)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813135737152.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tpbPZrdB-1642483402626)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813140427051.png)]
事务
事务时数据库操作最基本单元,逻辑上的一组操作,要么都成功,如果有一个失败所有操作都失败
典型场景:银行转账
事务四个特性(ACID)
原子性
一致性:操作之前和操作之后的总量不变
隔离性:多事务操作时不会产生影响
持久性
事务操作(搭建事务操作环境)
Service:业务操作
创建转账的方法
调用dao两个的方法
Dao:数据库操作,不写业务
创建两个方法
(1)少钱的方法
(2)多钱的方法
1、创建数据库表,添加记录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jUSPjx98-1642483402629)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813162422437.png)]
2、创建service,搭建dao,完成对象创建和注入关系
service注入dao,在dao注入JdbcTemplate,在JdbcTemplate注入DataSource
3、在dao创建两个方法:多钱和少钱的方法
在service创建转账的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cjrHc9JJ-1642483402630)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813164500709.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7HAu9sT4-1642483402631)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813164524809.png)]
使用事务进行解决转账异常
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FMJIv7RM-1642483402631)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813165428575.png)]
Spring事务管理
1、事务添加到JavaEE三层结构里面Service层(业务逻辑层)
2、在Spring进行事务管理操作
有两种方式
编程式事务管理
声明式事务管理(使用)
3、声明式事务管理
(1)基于注解方式
(2)基于xml配置文件方式
4、在Spring进行声明式事务管理,底层使用AOP
5、Spring事务管理API
(1)提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SpOrhCEd-1642483402632)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813171129651.png)]
注解声明式事务管理
1、在spring:配置文件中配置事务管理器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hq6gWGdO-1642483402633)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813172826650.png)]
2、在spring配置文件,开启事务注解
(1)在spring配置文件引入名称空间tx
(2)开启事务注解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PuMRXsEX-1642483402634)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813173247809.png)]
3、在service类上面(获取service类方法上面)添加事务注解
(1)@Transactional,这个注解添加到类上面,也可以添加到方法上面
(2)如果把这个注解添加到类上面,这个类里面所有的方法都添加事务
(3)如果把这个注解添加方法上面,为这个方法添加事务
声明式事务管理参数配置
1、在service类上面添加注解@Transactional,在这个注解里面可以配置事务相关参数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nKe9tLCQ-1642483402635)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210813180634094.png)]
propagation:事务传播行为
多事务方法之间进行调用,这个过程事务是如何进行管理的
事务方法:对数据库数据进行变化的操作
事务的传播行为可以由传播属性指定,Spring定义了7种类传播行为
传播属性 | 描述 |
---|---|
REQUIRED | 如果有事务在运行,当前的方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行 |
REQUIRED_NEW | 当前的方法必须启动新事物,并在他自己的事务内运行,如果有事务正在运行,应该将它挂起 |
SUPPORTS | 如果有事务正在运行,当前的方法就在这个事务内运行,否则它可以不运行在事务中 |
NOT_SUPPOTRED | 当前的方法不应该运行在事务中,如果有运行的事务,将它挂起 |
MANDATORY | 当前的方法必须运行在事务内部,如果没有正在运行的事务,就抛出异常 |
NEVER | 当前的方法不应该运行事务中,如果有运行的事务,就抛出异常 |
NESTED | 如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行,否则,就启动一个新事物,并在它自己的事务内运行 |
@Service
@Transaction(propagation = Propagation.REQUIRED)
public class UserService{}
isolation:事务隔离级别
(1)事务有隔离性,多事务操作之间不会产生影响,不考虑隔离性产生很多问题
(2)有三个读问题:脏读、不可重复读、幻读
(3)脏读:一个未提交事务读取到另一个未提交事务的数据
(4)不可重复读:一个未提交事务读取到另一提交事务修改数据
(5)幻读:一个未提交事务读取到另一提交事务添加数据
(6)通过设置事务隔离级别,解决读问题
脏读 | 不可重复读 | 幻读 | |
---|---|---|---|
READ UNCOMMITTED(读未提交) | 有 | 有 | 有 |
READ COMMITTED(读已提交) | 无 | 有 | 有 |
REPEATABLE READ(可重复读) | 无 | 无 | 有 |
SERIALIZABLE(串行化) | 无 | 无 | 无 |
@Service
@Transaction(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE)
public class UserService{}
timeout:超时时间
(1)事务需要在一定时间内进行提交,如果不提交进行回滚
(2)默认值是-1,设置时间以秒为单位
@Service
@Transaction(timeout = -1,propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE)
public class UserService{}
readOnly:是否只读
(1)读:查询操作,写:添加修改删除
(2)readOnly默认值false,表示可以查询,可以添加修改删除操作
(3)设置readOnly值是true,设置成true之后,只能查询
rollbackFor:回滚
设置出现哪些异常进行事务回滚
noRollbackFor:不回滚
设置出现哪些异常不进行事务回滚
事务操作(XML声明式事务管理)
1、在 spring配置文件中进行配置
第一步 配置事务管理器
第二步 配置通知
第三步 配置切入点和切面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xwXEW178-1642483402635)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210814143343902.png)]
事务操作(完全注解声明式事务管理)
1、创建配置类,使用配置类替代xml配置文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RSEfI5M0-1642483402636)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210814145606289.png)]
2、测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tbGp4cOM-1642483402637)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210814150031846.png)]
Spring5框架新功能
1、整个框架基于java8,运行时兼容JDK9,许多不建议使用的类和方法在代码库中删除
2、spring5.0框架自带了通用的日志封装
(1)spring5已经移除Log4jConfig,官方建议使用Log4j
(2)spring5框架整合Log4j2
第一步 引入jar包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lvkierkU-1642483402637)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210814152244524.png)]
第二步
创建Log4j2.xml配置文件
日志级别以及优先级排序:
OFF>FATAL>ERROR>WARN>INFO>DEBUG>TRACE>ALL
Configuration后面的status用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,可以看到log4j2内部各种详细输出
<?xml version="1.0" encoding="UTF-8" ?>
<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>
package spring5;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserLog {
private static final Logger log = LoggerFactory.getLogger(UserLog.class);
public static void main(String[] args) {
log.info("hello log4j2");
log.info("hello log4j2");
}
}
3、spring5框架核心容器支持@Nullable注解
@Nullable注解可以使用在方法上面,属性上面,参数上面,表示方法返回值可以为空,属性值可以为空,参数值可以为空
4、spring5核心容器支持函数式风格GenaericApplicationContext
context.registBean(User.class,() -> new User());
User user = (User)context.getBean("spring5.User");
5、spring5支持整合JUnit5
(1)整合JUnit4
第一步 引入依赖
spring-test
第二步 创建测试类,使用注解方式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Dp0TLLy-1642483402639)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210814214505601.png)]
(2)spring5整合JUnit5
第一步 引入JUnit5的jar包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bp3ywAim-1642483402639)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210814215042439.png)]
第二步 创建测试类,使用注解完成
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xz10lorg-1642483402640)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210814215403830.png)]
复合注解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U0W5qZtv-1642483402640)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210814215549368.png)]
Spring5框架新功能
1、SpringWebflux介绍
2、响应式编程
3、Webflux执行流程和核心API
4、SpringWebflux(基于注解编程模型)
5、SpringWebflux(基于注解编程模型)
nsole>
<loggers>
<root level="info">
<appender-ref ref="Console"/>
</root>
</loggers>
```
package spring5;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserLog {
private static final Logger log = LoggerFactory.getLogger(UserLog.class);
public static void main(String[] args) {
log.info("hello log4j2");
log.info("hello log4j2");
}
}
3、spring5框架核心容器支持@Nullable注解
@Nullable注解可以使用在方法上面,属性上面,参数上面,表示方法返回值可以为空,属性值可以为空,参数值可以为空
4、spring5核心容器支持函数式风格GenaericApplicationContext
context.registBean(User.class,() -> new User());
User user = (User)context.getBean("spring5.User");
5、spring5支持整合JUnit5
(1)整合JUnit4
第一步 引入依赖
spring-test
第二步 创建测试类,使用注解方式
[外链图片转存中…(img-8Dp0TLLy-1642483402639)]
(2)spring5整合JUnit5
第一步 引入JUnit5的jar包
[外链图片转存中…(img-Bp3ywAim-1642483402639)]
第二步 创建测试类,使用注解完成
[外链图片转存中…(img-xz10lorg-1642483402640)]
复合注解
[外链图片转存中…(img-U0W5qZtv-1642483402640)]
Spring5框架新功能
1、SpringWebflux介绍
2、响应式编程
3、Webflux执行流程和核心API
4、SpringWebflux(基于注解编程模型)
5、SpringWebflux(基于注解编程模型)