Spring5笔记
1、Spring 入门案例
1.1 、Spring5下载
进入官网https://spring.io/
GA表示稳定版
点击GitHub进入
点击链接进入
继续进入
往下滑找到spring 把导航地址替换
进入后选择相应的版本下载
1.2 入门案例
1.首先导入5个jar包
2、创建普通类,在这个类中添加普通方法
package com.spring5;
/**
* @author JLLStart
* 2022/10/10 20:00
*/
public class User {
public void add(){
System.out.println("add...");
}
}
3、创建Spring配置文件,在配置文件配置创建的对象
(1)Spring配置文件使用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对象创建 -->
<bean id="user" class="com.spring5.User"></bean>
</beans>
4、进行测试代码编写
package com.spring5.TestDemo;
import com.spring5.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author JLLStart
* 2022/10/10 20:12
*/
public class TestSpring5 {
@Test
public void testAdd(){
//1 加载Spring配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
//2.获取配置创建的对象
User user = context.getBean("user", User.class);
System.out.println(user);
user.add();
}
}
2、IOC-控制反转
2.1、IOC是什么
(1) 控制 反 转 把 对 象 创建 和 对 象 之 间 的 调用 过 程 ,交 给 Spring 进行 管理 。
(2) 使 用 IOC 目的 : 为了耦合 度 降 低 。
(3) 做 入 门 案例 就 是 IOC 实现
2.2、IOC底层原理
(1) xml 解 析
(2) 工厂模式
(3) 反 射
2.3、IOC容器实现的两种方式(两个接口)
(1) BeanFactoty
IOC容器基本实现,是Spring加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象。内部的使用接口,不提供开发人员进行使用。加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象。
(2) ApplicationContext:
BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用。
ApplicationContext有两个实现接口:
2.4、 IOC操作Bean管理(基于xml配置文件方式实现)
2.4.1、什么是Bean管理
- Spring 创建对象
- Spring注入属性
2.4.2、Bean管理操作有两种方式
1、基于xml配置文件方式实现
1.1、Spring创建对象:
<!-- 配置User对象创建 -->
<bean id="user" class="com.spring5.User"></bean>
(1)在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
(2)在bean标签有很多属性,介绍常用的属性。
* id属性:唯一标识。
* class属性:类全路径(包类路径)。
(3)创建对象时候,默认也是执行无参数构造方法完成对象创建。
-
2、Spring注入属性
1.2.1、使用set方法注入
<!-- set方法注入属性 -->
<bean id="book" class="com.spring5.Book">
<!-- 使用property完成属性注入
name: 类里面厲性名称
value:向属性注入的值
-->
<property name="name" value="易筋经"/>
</bean>
<!-- XML注入其他类型属性-->
<!-- 1.null值-->
<!-- 设置空值null -->
<property name="name">
<null/>
</property>
<!--2.属性值包含特殊符号-->
<!-- 属性值包含特殊符号
1. 把 <> 进行转义 -> <>
2. 把带特殊符号内容写入CDATA
-->
<property name="address">
<!-- <![CDATA[此处填属性值]> -->
<value><![CDATA[<南京>]]></value>
</property>
p名称空间注入(应用于set方法 了解就行)
<!-- 首先要添加名称空间 -->
xmlns:p="http://www.springframework.org/schema/p"
<bean id="book2" class="com.spring5.Book" p:name="吸星大法" p:author="任我行"/>
1.2.2、使用有参数构造注入
<!-- 3.有参数构造注入属性 -->
<bean id="order" class="com.spring5.Order">
<!-- <constructor-arg index="0" value="郭靖"/>-->
<!-- <constructor-arg index="1" value="襄阳"/>-->
<constructor-arg name="name" value="郭靖"/>
<constructor-arg name="address" value="襄阳"/>
</bean>
注意:
注入普通属性需要注意的点使用 set 方法注入属性的时候,即在bean 标签内部使用 property 标签进行属性注入要创建对应的 set 方法,然后配置 xml 文件才有效,否则会报错
**同理,使用有参构造器设置属性的时候,即在 bean 标签内部使用constructor-arg标签进行属性注入,要求类中有对应参数的构造器 **
2、基于注解方式实现。
2.4.3 、注入外部bean
ref属性:外部bean的id值
通过ref属性将外部bean注入
UserService实现类
package com.spring5.service;
import com.spring5.dao.UserDao;
import com.spring5.dao.UserDaoImpl;
/**
* @author JLLStart
* 2022/10/11 18:18
*/
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDaoImpl userDao) {
this.userDao = userDao;
}
@Override
public void service() {
userDao.add();
}
}
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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- service 和 dao 对象创建-->
<bean id="userService" class="com.spring5.service.UserServiceImpl">
<!-- 注入UserDao对象 -->
<property name="userDao" ref="userDaoImpl"/>
</bean>
<bean id="userDaoImpl" class="com.spring5.dao.UserDaoImpl">
</bean>
</beans>
2.4.4 、注入内部bean
嵌套bean
<bean id="employ" class="com.spring5.bean.Employ">
<property name="name" value="岳不群"/>
<property name="gender" value=""/>
<!-- 设置对象类型属性 -->
<property name="dep">
<bean id="department" class="com.spring5.bean.Department">
<property name="name" value="安保部"/>
</bean>
</property>
</bean>
2.4.5、注入属性-级联赋值
<!-- 级联赋值 -->
<bean id="employ" class="com.spring5.bean.Employ">
<property name="name" value="岳不群"/>
<property name="gender" value="女"/>
<!-- 级联赋值 -->
<property name="dep" ref="dept"/>
<property name="dep.name" value="技术部"/>
</bean>
<bean id="dept" class="com.spring5.bean.Department">
<property name="name" value="财务部"/>
</bean>xl
注意:这里使用dep.name 需要在Employ类写getDep()方法 否则报错
2.4.6、XML注入集合属性
1、注入数组类型属性
<!-- 数组属性注入 -->
<property name="courses">
<array>
<value>Java</value>
<value>Python</value>
<value>数据库</value>
</array>
</property>
2、注入list类型属性
<!-- list类型属性注入 -->
<property name="list">
<list>
<value>东方不败</value>
<value>令狐冲</value>
<value>田伯光</value>
</list>
</property>
3、注入map类型属性
<!-- map类型属性注入 -->
<property name="map">
<map>
<entry key="JAVA" value="java"/>
<entry key="PHP" value="php"/>
<entry key="PYTHON" value="python"/>
</map>
</property>
4、注入set类型属性
<!-- set属性注入 -->
<property name="set">
<set>
<value>MySql</value>
<value>Oracle</value>
</set>
</property>
**提取集合注入部分: **
(1)在spring配置文件引入名称空间util
(2)使用util标签完成list集合注入提取
<!-- 1.提取list集合属性注入 -->
<util:list id="bookList">
<value>易筋经</value>
<value>九阴真经</value>
<value>吸星大法</value>
</util:list>
<!-- 2.注入使用 -->
<bean id="book" class="com.spring5.collectionType.Book">
<property name="list" ref="bookList"/>
</bean>
2.4.7、FactoryBean
2.4.8、bean作用域
在spring配置文件bean标签里面有属性**scope** 用于设置单实例还是多实例。
- singleton:单例,默认也是这个,加载spring配置文件时候就会创建单实例对象
- prototype:多例,在调用getBean方法时候创建多实例对象
<!-- 2.注入使用 -->
<bean id="book" class="com.spring5.collectionType.Book" scope="prototype">
<property name="list" ref="bookList"/>
</bean>
2.4.9、bean的生命周期
基本声明周期
(1) 通过构造器创建bean实例 (无参数构造)。
(2) 为bean的属性设置值和对其他bean引用 (调用set方法)
(3) 调用bean的初始化的方法 (需要进行配置初始化的方法 )
(4) bean可以使用了 (对象获取到了)
(5) 当容器关闭时候,调用bean的销毁的方法 ( 需要进行配置销毁的方法)
加上后置处理器的生命周期
(1) 通过构造器创建bean实例 (无参数构造)。
(2) 为bean的属性设置值和对其他bean引用 (调用set方法)
(3) 把bean实例传递bean后置处理器的方法postProcessAfterInitialization.
(4) 调用bean的初始化的方法 (需要进行配置初始化的方法 )
(5) 把bean实例传递bean后置处理器的方法postProcessAfterInitialization.
(6) bean可以使用了 (对象获取到了)
(7) 当容器关闭时候,调用bean的销毁的方法 ( 需要进行配置销毁的方法)
后置处理器
package com.spring5.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @author JLLStart
* 2022/10/14 10:56
*/
public class BeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化之前");
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化之后");
return null;
}
}
**注意:**在配置文件中配置了后置处理器,对当前配置文件中所有的bean都有效
2.4.10、XML自动装配
自动装配含义:
根据指定装配规则(属性名称或者属性类型),Spring 自动将匹配的属性值进行注入
<!-- 根据名称自动注入 -->
<bean id="employ" class="com.spring5.autowire.Employ" autowire="byName">
<!-- <property name="department" ref="department"/> -->
</bean>
<!-- 根据类型自动注入 -->
<bean id="employ" class="com.spring5.autowire.Employ" autowire="byType">
<!-- <property name="department" ref="department"/> -->
</bean>
<bean id="department" class="com.spring5.autowire.Department">
</bean>
2.4.11、外部属性文件
1.演示数据库连接配置:
# 数据库驱动
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
# 数据库连接
jdbc.url=jdbc:mysql://localhost:3306/test2?serverTimezone=UTC
# 数据库用户名
jdbc.username=root
# 数据库密码
jdbc.password=root
#最大连接数
jdbc.maxActive=300
#初始化连接数
jdbc.initialSize=2
#获取连接最大等待时间
jdbc.maxWait=60000
#最小连接数
jdbc.minIdle=1
#检测连接有效性的时间间隔
jdbc.timeBetweenEvictionRunsMillis=60000
#连接保持空闲而不被驱逐的最长时间
jdbc.minEvictableIdleTimeMillis=300000
#连接有效性,检测sql
jdbc.validationQuery=SELECT 'x'
#定时检测空闲连接有效性
jdbc.testWhileIdle=true
#检测获取的连接的有效性
jdbc.testOnBorrow=false
#检测要归还的连接的有效性
jdbc.testOnReturn=false
#是否缓存preparedStatement,即PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
jdbc.poolPreparedStatements=false
jdbc.maxOpenPreparedStatements=50
2.把外部properties属性文件引入到Spring配置文件中
引入context名称空间
<!-- 引入外部属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据库信息 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${jdbc.url}"/>
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
2.5、IOC操作Bean管理(基于注解)
2.5.1、Spring针对Bean管理中创建对象提供注解
(1) @Component (普通注解创建对象)
(2) @Service (一般在业务逻辑层)
(3) @Controller (一般在Web层)
(4) @Repository (一般在DAO层)
这四个注解功能是一样的,都可以用来创建bean实例,为了区分 建议遵守规范
2.5.2、基于注解方式实现对象创建
1.引入依赖
2.开启组件扫描
这里也要引入名称空间context
<!--开启组件扫描
1如果扫描多个包,多个包使用逗号隔开
2扫描包上层目录(推荐)
-->
<context:component-scan base-package="com.spring5.dao,com.spring5.service">
</context:component-scan>
3.第三步创建类,在类上面添加创建对象注解。
4.开启组件扫描细节配置
<!-- 示例1
use - -default-filters=' false" 表示现在不使用默认filter,自己配置filter
context:include-filter,设置扫描哪些内容
-->
<context:component-scan base-package="com.spring5" use-default-filters="false">
<!-- 过滤包含Component注解的类 -->
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Component"/>
</context:component-scan>
<!-- 示例2
use - -default-filters=' false" 表示现在不使用默认filter,自己配置filter
context:exclude-filter,设置不扫描哪些内容
-->
<context:component-scan base-package="com.spring5" use-default-filters="false">
<!-- 过滤不包含Component注解的类 -->
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Component"/>
</context:component-scan>
2.5.3、属性注入
(1) @Autowired: 根据属性类型进行自动装配
(2) @Qualifier: 根据属性名称进行注入。
(3) @Resource: 可以根据类型注入,可以根据名称注入
(4) @Value: 注入普通类型属性
Dao层
@Repository
public class AnnotationDaoImpl implements AnnotationDao {
@Override
public void add() {
System.out.println("dao...add");
}
}
Service层
@Service
public class AnnotationService {
//定义dao类型属性
//不需要添加set方法
//添加注入属性注解
@Autowired // 根据类型自动注入
private AnnotationDao annotationDao;
public void add() {
System.out.println("add ...");
annotationDao.add();
}
}
注意:
- 使用@Autowired 注解进行属性注入不需要添加 set 方法
- 单独使用@Autowired 注解,只能有一个实现类,多个实现类会报错;
- @Qualifier 必须与@Autowired 一起使用,唯一的确定某类型某实现类的属性;
@Value注解
2.5.4、完全注解开发
(1) 创建配置类,替代xml配置文件。
@Configuration //作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"com.spring5"})
public class SpringConfig {
}
(2) 编写测试类
// 完全注解开发
@Test
public void testService2() {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
AnnotationService annotationService = context.getBean("annotationService", AnnotationService.class);
annotationService.add();
System.out.println(annotationService);
}
3、AOP-面向切面编程
3.1 AOP是什么
(1)面向切面编程,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用 性,同时提高了开发的效率。
(2)通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
3.2、AOP底层原理
1、AOP底层使用动态代理
有两种情况动态代理:
- 有接口情况,使用JDK动态代理。创建接口实现类代理对象,增强类的方法
- 没有接口情况,使用CGLIB动态代理。
3.3、JDK动态代理(有接口)
(1) 创建接口,定义方法。
public interface UserDao {
public int add(int a, int b);
public String update(String id);
}
(2)创建接口实现类,实现方法
public class UserDaoImpl implements UserDao {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public String update(String id) {
return id;
}
}
(3) 使用Proxy类创建接口代理对象
package com.spring5.AOP.proxy;
import com.spring5.AOP.dao.UserDao;
import com.spring5.AOP.dao.UserDaoImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author JLLStart
* 2022/10/15 14:30
*/
public class JdkProxy {
public static void main(String[] args) {
//创建接口实现类代理对象
Class[] interfaces = {UserDao.class};
// Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// return null;
// }
// });
UserDaoImpl userDao = new UserDaoImpl();
UserDao proxyInstance = (UserDao) Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
System.out.println(proxyInstance.add(1, 39));
}
}
// 创建代理对象代码
class UserDaoProxy implements InvocationHandler {
// 传递被代理类
private Object obj;
public UserDaoProxy(Object obj) {
this.obj = obj;
}
// 增强的逻辑
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object res = method.invoke(obj, args);
return res;
}
}
3.4、AOP操作术语
3.5、AOP操作
3.5.1、准备工作
1、Spring 框架-般都是基于Aspect]实现AOP操作s
(1)什么是AspectJ:
AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进
行AOP操作。
2、基于AspectJ实现AOP操作s
(1)基于xml配置文件实现
(2)基于注解方式实现(使用)
3、引入AspectJ依赖
<!-- https://mvnrepository.com/artifact/net.sourceforge.cglib/com.springsource.net.sf.cglib -->
<dependency>
<groupId>net.sourceforge.cglib</groupId>
<artifactId>com.springsource.net.sf.cglib</artifactId>
<version>2.2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.9.1</version>
<scope>runtime</scope>
</dependency>
4、切入点表达式
(1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强、
(2)语法结构:。
execution([权限修饰符][返回类型] [类全路径] [方法名称]([参数列表]) )
举例1:对com.atguigu.dao.BookDao类里面的add进行增强。
execution(* com.atguigu.dao.Book.add(…))
举例2:对com.atguigu.dao. BookDao类里面的所有的方法进行增强
execution(*com.atguigu.dao.BookDa.* (…))
举例3:对com.atguigu.dao包里面所有类,类里面所有方法进行增强.
execution(* com.atquiqu.dao.*.* (… )
3.5.2、AspectJ注解
1、创建类,在类里面定义方法
public class User {
public void add(){
System.out.println("add...");
}
}
2、创建增强类(编写增强逻辑)
(1)在增强类里面,创建方法,让不同方法代表不同通知类型.
public class UserProxy {
// 前置通知
public void before(){
System.out.println("before...");
}
}
3、进行通知的配置
(1)在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">
<context:component-scan base-package="com.spring5.AOP">
</context:component-scan>
</beans>
(2)使用注解创建User和UserProxy对象
在这两个类中添加注解@Component
(3) 在增强类上面添加注解@Aspects
(4)在spring配置文件中开启生成代理对象
<!-- 开启Aspect生成代理对象-->
<aop:aspectj-autoproxy>
</aop:aspectj-autoproxy>
4、配置不同类型的通知
package com.spring5.AOP.proxy;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* @author JLLStart
* 2022/10/15 23:07
*/
@Component
@Aspect // 生成代理对象
public class UserProxy {
// 前置通知
//@Before注解表示作为前置通知
@Before(value = "execution(* com.spring5.AOP.AspectJ.User.add(..))")
public void before() {
System.out.println("before...");
}
// 最终通知
@After(value = "execution(* com.spring5.AOP.AspectJ.User.add(..))")
public void after() {
System.out.println("after...");
}
// 后置通知
@AfterReturning(value = "execution(* com.spring5.AOP.AspectJ.User.add(..))")
public void afterReturning() {
System.out.println("afterReturning...");
}
// 异常通知
@AfterThrowing(value = "execution(* com.spring5.AOP.AspectJ.User.add(..))")
public void afterThrowing() {
System.out.println("afterThrowing...");
}
// 环绕通知
@Around(value = "execution(* com.spring5.AOP.AspectJ.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("环绕之前");
try {
proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("环绕之后");
}
}
5、相同切入点抽取
// 相同切入点抽取
@Pointcut(value = "execution(* com.spring5.AOP.AspectJ.User.add(..))")
public void point(){
}
// 前置通知
//@Before注解表示作为前置通知
@Before(value = "point()")
public void before() {
System.out.println("before...");
}
6、有多个增强类多同-一个方法进行增强,设置增强类优先级
(1)在增强类上面添加注解@Order(数字类型值),数字类型值越小优先级越高。
@Component
@Aspect
@Order(2)
public class UserProxy2 {
@Before(value = "execution(* com.spring5.AOP.AspectJ.User.add(..))")
public void before2() {
System.out.println("before2...");
}
}
7、完全注解开发
@Configuration //标注为配置类
@ComponentScan(basePackages = {"com.spring5.AOP"}) //开启注解扫描
@EnableAspectJAutoProxy(proxyTargetClass = true) //开启Aspect自动生成代理对象
public class ConfigAop {
}
3.5.3、AspectJ配置文件
1、创建两个类,增强类和被增强类,创建方法
2、在spring配置文件中创建两个类对象
<!-- 创建对象 -->
<bean id="book" class="com.spring5.AOP.aopxml.Book"/>
<bean id="bookProxy" class="com.spring5.AOP.proxy.BookProxy"/>
3、在spring配置文件中配置切入点
<!-- 配置aop增强-->
<aop:config>
<!-- 切入点-->
<aop:pointcut id="p" expression="execution(* com.spring5.AOP.aopxml.Book.buy(..))"/>
<!-- 配置切面-->
<aop:aspect ref="bookProxy">
<aop:before method="before" pointcut-ref="p"/>
</aop:aspect>
</aop:config>
4、JDBCTemplate
4.1、JdbcTemplatev概念和准备工作
概念:Spring 框架对JDBC进行封装,使用JdbcTemplate方便实现对数据库操作
准备工作:
1、引入依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.23</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.23</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
<!-- 用来整合其他框架 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.3.23</version>
</dependency>
2、配置数据库连接池
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/springUser?serverTimeZone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
</bean>
3、配置JDBCTemplate对象,注入DataSource
<bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 注入DataSource -->
<property name="dataSource" ref="dataSource"/>
</bean>
4、创建service类, 创建dao类,在dao注入jdbcTemplate对象
- 组件扫描:
<context:component-scan base-package="com.spring5.JDBCTemplate"/>
- service
package com.spring5.JDBCTemplate.service;
import com.spring5.JDBCTemplate.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author JLLStart
* 2022/10/16 16:50
*/
@Service
public class BookService {
// 注入Dao
@Autowired
private BookDao bookDao;
}
4.2、操作数据库
4.2.1、增删改查
- 增删改
@Repository
public class BookDaoImpl implements BookDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void add(Book book) {
//1.创建sql语句
String sql = "insert into t_book values(?,?,?)";
//2.调用 方法
int update = jdbcTemplate.update(sql, book.getUserId(), book.getUsername(), book.getUstatus());
System.out.println(update);
}
}
- 查询返回某个值
//查询表中记录数
@Override
public int selectCount() {
String sql = "select count(*) from t_book";
return jdbcTemplate.queryForObject(sql, Integer.class);
}
- 查询返回对象
**这里的Book类需要有无参构造器 **
@Override
public Book findBookInfo(String id) {
String sql = "select * from t_book where user_id = ?";
return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Book.class), id);
}
- 查询返回集合
// 查询返回集合对象
@Override
public List<Book> findAllBook() {
String sql = "select * from t_book";
return jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(Book.class));
}
4.2.2、批量操作数据
DAO实现类
@Override
public void addBooks(List<Object[]> bookList) {
String sql = "insert into t_book values(?,?,?)";
int[] ints = jdbcTemplate.batchUpdate(sql, bookList);
System.out.println(Arrays.toString(ints));
}
测试
@Test
public void testBookService5() {
ApplicationContext context = new ClassPathXmlApplicationContext("JDBCTemplate/bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
List<Object[]> books = new ArrayList<>();
Object[] o1 = {"3", "c++","a"};
Object[] o2 = {"4", "Rust","r"};
Object[] o3 = {"5", "Ruby","R"};
Collections.addAll(books,o1,o2,o3);
bookService.batchAdd(books);
}
4.3、事务管理
spring提供-一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类
4.3.1、声明式事务管理(注解操作)
1、在spring配置文件配置事务管理器
<!-- 创建事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
2、在spring配置文件,开启事务注解
(1)引入tx名称空间
(2)开启事务注解
<tx:annotation-driven transaction-manager="transactionManager"/>
3、在service类上面(获取service类里面方法上面)添加事务注解
(1) @Transactional, 这个注解添加到类上面,也可以添加方法上面。
(2)如果把这个注解添加类上面,这个类里面所有的方法都添加事务
(3)如果把这个注解添加方法上面,为这个方法添加事务,
声明式事务管理参数配置
1、propagation:事务传播行为
2、ioslation: 事务隔离级别。
(1)事务有特性成为隔离性,多事务操作之间不会产生影响, 不考虑隔离性产生很多问题。
(2)有三个读问题:脏读、不可重复读、虚(幻)读
(3)脏读:一个未提交事务读取到另-一个未提交事务的数据
(4)一个未提交事务读取到另-提交事务修改数据
(5)一个未提交事务读取到另一提交事务添加数据
解决读问题:
3、timeout: 超时时间。
(1) 事务需要在一定时间内进行提交,如果不提交进行回滚。
(2)默认值是-1,设置时间以秒单位进行计算
4、readOnly: 是否只读
(1)读:查询操作,写:添加修改删除操作。
(2) readOnly 默认值false,表示可以查询,可以添加修改删除操作。
(3)设置readOnly,值是true, 设置成true之后,只能查询。
5、rollbackFor: 回滚。
设置出现哪些异常进行事务回滚
6、noRollbackFor: 不回滚
设置出现哪些异常不进行事务回滚
4.3.2、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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/springuser?serverTimeZone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
</bean>
<bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 注入DataSource -->
<property name="dataSource" ref="dataSource"/>
</bean>
<context:component-scan base-package="com.spring5.JDBCTemplate"/>
<!-- 创建事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--2配置通知-->
<tx:advice id="txadvice" >
<!--配置事务参数-->
<tx:attributes>
<!--指定哪种规则的方法_上面添加事务-->
<tx:method name="accountMoney" propagation="REQUIRED"/>
<!--<tx:method name= "account*'” />-->
</tx:attributes>
</tx:advice>
<aop:config>
<!--配置切入点-->
<aop:pointcut id="pt" expression=" execution(* com.spring5.JDBCTemplate.service.*(..))"/>
<!--配置切面-->
<aop:advisor advice-ref="txadvice" pointcut-ref="pt" />
</aop:config>
</beans>
4.3.3、完全注解生命式事务管理
package com.spring5.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;
/**
* @author JLLStart
* 2022/10/18 21:30
*/
@Configuration
@ComponentScan(basePackages = {"com.spring5.JDBCTemplate"})
@EnableTransactionManagement() // 开启事务注解
public class TxConfig {
// 创建数据库连接池
@Bean
public DruidDataSource getDruidDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/springuser?serverTimeZone=UTC");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
// 创建JdbcTemplate对象
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource); // IOC容器根据类型自动注入
return jdbcTemplate;
}
// 创建事务管理器
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}
5、spring5新功能
5.1、整合日志框架
1、整个Spring5框架的代码基于Java8, 运行时兼容JDK9, 许多不建议使用的类和方法
在代码库中删除。
2、Spring5.0框架自带了通用的日志封装
(1) Spring5 已经移除Log4jConfigListener, 官方建议使用Log4j2
(2) Spring5 框架整合Log4j2
导入依赖
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.19.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.19.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.19.0</version>
</dependency>
5.2、支持@Nullable注解
@Nullable 注解可以使用在方法上面,属性上面,参数上面,表示方法返回可以为空,属性值可以
为空叁数值可以 为空,
5.3、Spring5核心容器支持函数式风格GenericApplicationContext
5.4、Spring5 支持整合JUnit5
(1)整合JUnit4
第一步 引入Spring相关针对测试依赖。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.23</version>
<scope>test</scope>
</dependency>
第二步 创建测试类,使用注解方式完成
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:JDBCTemplate/bean2.xml")
public class JTest4 {
@Autowired
private UserService userService;
@Test
public void testJunit4(){
userService.accountMoney();
}
}
(2)整合JUnit5
使用复合注解
package com.spring5.newAbility.service;
import com.spring5.JDBCTemplate.service.UserService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
/**
* @author JLLStart
* 2022/10/19 13:27
*/
@SpringJUnitConfig(locations = "classpath:JDBCTemplate/bean2.xml")
public class JTest5 {
@Autowired
private UserService userService;
@Test
public void testJunit4(){
userService.accountMoney();
}
}