Spring5(尚硅谷笔记)

    技术2025-12-08  11

    补充笔记

    1.IOC底层原理

    1.IOC概念以及原理:

    什么是ioc? 1.IOC(DI)概述: Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。DI概述: DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。2.ICO前生: 1.分离接口与实现: 例子:生成HTML或PDF格式的不同类型的报表 2.采用工厂设计模式: 3.采用反转控制 IOC底层原理: 1.xml解析 2.工厂模式 3.反射

    1.工厂模式:

    原始方式: 工厂模式:

    实际意义:service和dao的耦合度减少,dao层变了,修改工厂类,且是Static的,提高了代码重用率

    2.xml解析:

    IOC过程: 1.xml配置文件,配置创建的对象: 2.有service和dao类,创建工厂类

    2.IOC接口

    IOC思想基于IOC容器完成,IOC容器底层就是对象工厂

    Spring提供IOC容器实现的两种方式

    BeanFactory:IOC基本设施:提供了贡多的高级特性大多数我们使用ApplicationContext ,在你记载配置文件的时候,不会创建对象,只有你加载,才会创建ApplicationContext是BeanFactory的子接口,加载xml配置文件的时候就创建类了,主要实现类: ClassPathXmlApplicationContext:从类路径下加载配置文件 refresh():刷新上下文 close():关闭上下文 FilesSystemXmlApplicationContext:从文件系统加载配置文件调用ApplicationContext的getBean()方法 1.参数尽量写id,不写class型,除非配置的bena唯一

    3.IOC

    什么是bean管理?Spring创建对象,Spring注入属性 基于xml

    基于xml方式创建对象(IOC):

    配置XML文件,在IOC容器加入bean,并配置属性 bean常用属性讲解: id:唯一标识 name:和id差不多,但不可以加入特殊符号 class:类全路径(通过路径再反射获得地址码)创建对象的时候,默认也是执行无参数构造方法

    基于xml方式注入属性:

    DI:依赖注入,就是注入属性,在创建对象的基础之上,基于IOC的具体实现 第一种注入方式:使用set方法进行注入 1. 创建对象,并创建set 方法 2.在Spring配置文件文件中,通过property来配置 第一种注入方式:使用构造器进行注入 1. 在你的类配置构造器,必须要有无参构造器!!!! 2. 在Spring配置文件通过constructor来配置 通过p命名空间来给属性赋值: 需要先导入p命名空间 2.在Spring配置文件 ,通过p命名空间,来配置属性(只是用与你的bean有setter) 注入空值和特殊符号 空值:在当前标签的子节点使 特殊符号:如果value属性或者字标签的值包含特殊字符如<>,那么必须要写成<![CDATA[值 ]]>(或者转义) 注入属性bean: 外部bean: 1. 创建两个类service和dao,并建立set方法 2. 在service调用dao里面的方法 内部bean和级联赋值: 内部bean 在你的bean中添加好级联属性: 直接在你的Spring配置文,嵌套bean 级联赋值 通过ref,以及外部bean的联用: 注入集合属性 1.

    集合赋值对象和公共集合 集合赋值对象: 1. 先建立对应的集合 2.在spirng配置文件直接配置就可以了

    独立集合

    FactoryBean

    普通bean:在配置文件中定义bean类型就是返回类型工厂bean:在配置文件中定义bean类型不一定就是返回类型 1. 第一步 创建类 ,让这个类作为工厂bean,实现接口FactoryBean 2. 第二步 实现接口FactoryBean里面的方法,在实现的方法中定义返回的bean类型

    Bean的作用域 使用bean的scope来配置bean的作用域 singleton:默认值,容器初始创建bean实例,在这个容器的生命周期只创建这个一个bean,单例的 prototype:原形的,容器初始化是不创建bean,在每次请求的时候,调用getbean()方法的时候创一个bean实例,并返回一个 1.默认情况下,Spring中的bean的实现都是单实例的 当你在spring上下文,设置属性scope 那么,运行结果

    bean生命周期

    生命周期 1.从对象创建到销毁的过程

    bean生命周期

    通过构造器创建bean实例(无参构造器)为bean的属性设置值和对其他bean的引用(调用set方法)调用bean的初始化方法(需要进行配置)bean创建完成,可以使用了当容器关闭,调用bean销毁的方法(需要进行配置)

    bean的后置处理器

    通过构造器创建bean实例(无参构造器)为bean的属性设置值和对其他bean的引用(调用set方法)把bean实例传递给bean后置处理器的方法调用bean的初始化方法(需要进行配置)把bean实例传递给bean后置处理器的方法bean创建完成,可以使用了当容器关闭,调用bean销毁的方法(需要进行配置) 后置处理器的演示: 1.创建类,实现接口BeanPostProcessor,创建后置处理器 2. 在Spring上下文配置文件

    bean的自动装配

    byName 根据当前Bean的id的setter风格的属性名自动装配,如果也有匹配的,则成功;若没有,则不装配 byType 根据bean的class和当前bean的类型进行装配,但是当出现两个或多个同类型的bean,会异常 15. 调用外部文件:

    基于注解

    简绍

    什么是注解:代码里面的特殊标记目的:简化代码

    Spring针对Bean管理中创建对象提供注解

    @Component:基本注解,标志了一个手Spring管理的组件@Respository:标识持久层@Service:表示服务层(业务层)组件@Controller:标识表现层组件 注意:功能是一样的,但是为了让你更加清晰,所以分开使用

    基于注解实现对象的创建

    配置扫描器(componet-scan)在你的Spring配置文件 在对应的包里的bean 加上注解

    组件扫描的细节配置: 1. base-package:指定一个扫描的包,可以选多个包,用逗号隔开 2. resource-pattem: 表示当前报下指定的一个类 3. context:include-filter(指定类): 字节点表示只包含的目标类,注意!!!:使用这个属性的时候要设定use-default-filters=“false”,意思就是不再是用官方的默认指定 4. context:exclude-filter(指定类): 字节点表示排除的目标类 5. 注意: context:include-filter和context:exclude-filter可以是context:component-canf的子节点 注意这两个方法有一个属性type:annotation:根据注解名称,只扫描注解。assinable :根据类名称,只扫描选定类 6. expression: 表示只扫描某一种注解

    基于注解方式实现属性注入

    @AutoWired: 根据属性类型进行自动装配 第一步:把service和dao添加创建对象注解 第二步:把service注入dao对象,在service添加

    @Qualifier: 当你需要一个指定名称的对象/属性时,你可以在@AutoWired的下面添加这个注解设置value值,必须要和目标注解的value对应

    @Resource:既可以根据类型,名称注入

    @Value:注入普通类型的属性

    完全注解开发:

    创建配置类,替代xml配置文件

    编写测试类

    3.AOP(面向切面编程)

    1.概念

    AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

    AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

    使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

    好处: 1.每个事物逻辑位于一个位置,代码不分散,便于维护和升级 2.业务模块更加简洁。只包括核心业务代码

    2.AOP底层使用动态代理

    有两种情况动态代理

    有接口 使用JDK动态代理 创建接口实现类代理对象,等价于new 但不是new

    无接口 使用CKLIB动态代理 创建子类实现类代理对象,等价于new 但不是new

    JDK动态代理实现(使用Proxy) 1.创建对应的接口,和实现类 2.使用Proxy,代理对象

    AOP术语: 连接点:类里面那些方法可以被增强,这些方法成为连接点切入点:实际被真正增强的方法,成为切入点通知(增强):就是你想要的功能,也就是 安全,事物,日志等 它有多种类型:前置,后置,环绕,异常,最终通知切面 :是一个动作,把通知应用到切入点过程个人理解:让切入点(犯法)通过连接点判断通知的位置(连接点)这叫做切面,而通知则会告诉你,什么时候干,干什么.切面这个过程会告诉你在哪里干 Aop操作(准备)

    Spring框架一般都是基于AspectJ实现AOP操作

    什么是AspectJ? AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用。进行Aop操作

    加入jar包

    基于AspectJ实现Aop操作

    基于xml配置文件实现(了解就好)

    创建两个类,增强类和被增强类,创建方法在Spring配置文件中创建两个类对象在Spring配置文件中配置切入点

    基于注解方式实现(使用) 1.创建被增强类,在类里面定义方法 2. 创建增强类,让不同的方法代表不同的通知 3. 在你的Spring配置文件开启注解扫描 4. 在你的类加上注解

    配置不同类型的通知 package AOP.AOP_annotation; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; //增强类 @Component //表示生成了代理对象 @Aspect public class UserProxy { @Pointcut("execution(public int AOP.AOP_annotation.User.add())") //为了让切点表达式重用,这里建立表示切点表达式的方法 public void pointcut(){ } // JoinPoint:可以联动被增强这个方法 //前置通知 @Before("execution(public int AOP.AOP_annotation.User.add())") public void before(JoinPoint j){ System.out.println("before:"+j.getSignature().getName()); } //后置通知 @After("execution(public int AOP.AOP_annotation.User.add()))") public void after(){ System.out.println("after"); } //返回通知: //在方法正常结束后执行的代码 //返回通知是可以访问到方法的返回值! @AfterReturning(value = "execution(public int AOP.AOP_annotation.User.add()))",returning = "res") public void AfterReturning(int res){ System.out.println("AfterReturning:"+res); } //异常通知:只有异常的时候才会执行,可以返回异常 @AfterThrowing(value = "execution(public int AOP.AOP_annotation.User.add()))",throwing = "s") public void AfterThrowing(Exception s){ System.out.println("AfterThrowing:"+s.toString()); } /*环绕通知,功能很强,但是并不常用 *环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法 *且环绕通知必须有返回值,返回值为目标方法的返回值 */ @Around("execution(public int AOP.AOP_annotation.User.add()))") public void Around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("环绕之前"); //被增强的方法执行 Object proceed = joinPoint.proceed(); System.out.println("环绕之后·"); } } 切入点表达式 切入点表达式作用:知道对那个类里面的那个方法进行增强语法结构:execution([权限修饰符][返回类型][类全路径][方法名称][参数列表]) 例子:在com.atguigu.dao.BookDao类的add()方法进行增强 execution(* void com.atguigu.dao.BookDao.add(int,int )) 切入点表达式的重用

    切面的增强顺序 默认是看类文件的名字在增强类上面添加注解@Order(数值),数字值越小优先级越高 完全注解开发

    4.事务管理

    1.概念:什么是事务

    事务是数据库操作的最基本单元,逻辑上一组操作,要么成功,要么又一个失败所有的操作全都失败.典型场景:银行转账

    2. 事务的四个特性(ACID)

    原子性:事务是一个原子操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要不全部不起作用一致性: 一旦所有事务动作完成,事务就被提交,数据和资源就处于一种满足业务规则的一致性状态中隔离性: 可能有许多事务会同时处理相同的数据。因此每个事务东应该与其他事物隔离开来,防止数据损坏持久性: 一旦事务完成,无论发生什么系统错误,它的结果都不应该收到影响。通常情况下,事物的结果被写到持久化储存中

    3.实例:

    创建银行转账表

    建立对应的 dao service 层并写入转账方法 如果在addMoney方法后发生未知异常,但是addMoney已经执行完了,就会出现作错误

    解决办法:事务

    事务操作:

    事务添加到JavaEE三层架构的Service层(业务逻辑层)

    两种方式:编程式事务管理和声明式事务管理(使用)

    声明式事务管理:

    基于注解方式

    配置事务管理器:

    在Spring配合文件开启事注解 1. 加入名称空间tx,开启事务注解

    在你的service类上面获取service类里面方法上面添加事务注解 注意:@Transactional既可以加在类上面,也可以加在方法上面 区别就是将事务套在类上或方法上

    当你方法出现异常的时候,你的数据也没发生改变

    基于xml配置文件方式(了解) 1. 在Spring配置文件,设置事务管理器,配置通知 2. 配入切入点和切面 3.

    在Spring进行声明式事务管理,底层使用Aop原理

    Spring事务管理的API

    提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类

    声明式事务的参数配置

    propagation():事务传播行为 1. 多事务方法,直接进行调用,这个过程中事务是如何进行管理的 2. 事务传播行为:事务方法的互相调用 3. 事务七种传播行为:

    ioslation:事务隔离级别

    事务有特性:隔离性,多事务操作之间不会产生影响,若不考虑隔离性产生很多问题有三个读的问题: 1.脏读:一个未提交事务读到另一个未提交事物的数据 2. 不可重复读:一个未提交事务读取到另一提交事务修改数据

    虚读:一个未提交事务读取到另一提交事务修改数据 解决办法:设置隔离级别属性ioslation,默认是REPEATABLE READ

    timeout:超过时间 事务需要在一定时间内进行提交,如果不不提交进行回滚 默认值为-1,设置时间一秒单位进行计算

    readonly:是否只读 读:查询,写:增删改 默认值:false

    rollbackfor:回滚 设置哪些异常回滚

    norollbackfor:不回滚 设置哪些异常不回滚

    package Transaction.CompletelyAnnotation; 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.transaction.annotation.EnableTransactionManagement; @Configuration//配合类 @ComponentScan(basePackages = "Transaction")//组件扫描 @EnableTransactionManagement//开启事务 public class TxConfig { //创建数据库连接池 @Bean public DruidDataSource getDruidDataSource(){ DruidDataSource dataSource=new DruidDataSource(); return null; } @Bean public JdbcTemplate getJdbct(){ return null; } }

    Spring5.x新功能

    整合日志

    整个Spring5代码基于java8,运行时兼容JDK9,许多不建议使用的类和方法在代码库中删除Spring5.x框架自带了通用的日志封装 Spring5已经移除了Log4jConfigListennerSpring5整合Log4j2 加入jar包: <!--Log4J2--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.12.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.12.1</version> </dependency> <dependency> <!-- 桥接:告诉Slf4j使用Log4j2 --> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.6.2</version> </dependency> <dependency> <groupId>com.walterjwhite.infrastructure.dependencies</groupId> <artifactId>slf4j-api</artifactId> <version>0.0.15</version> </dependency>

    创建log4j2的配置文件

    在这里我们还可以自己添加日志内容

    nullable注解和函数式注册对象

    @Nullable注解可以使用在方法上面,属性上面,参数上面,表示方法返回可以为空,属性会可以为空,参数值可以为空 例如: 1. 方法上:表示方法返回值可以是空值 2. 属性上: 表示属性值可以是空值 3. 参数上:表示参数值可以为空 函数式

    Spring5支持JUnit5

    整合JUnit4

    引入Spring相关针对测试依赖

    创建测试类,使用注解方式完成,不用每次都建立ioc容器,更加整洁

    整合junit5 引入JUnit5jar包创建测试类

    还有简化版:

    WebFlux:(没基础还没学)

    响应式编程WebFlux执行流程和核心APISpringWebflux基于注解编程模型SpringWebflux基于函数式编程模型
    Processed: 0.013, SQL: 9