Spring框架学习笔记
2026/7/16 5:23:14 网站建设 项目流程

场景引入

OCP开闭原则:对扩展开,对修改闭。只要你在扩展系统功能的时候,没有修改以前写好的代码,那么你就是符合OCP原则的。

DIP依赖倒置原则:面向接口编程,面向抽象编程,不面向具体编程。

上不依赖下,就是符合DIP。

程序违背了OCP原则 也违背了DIP原则,这时候 采用控制反转IoC(Inversion of Control)思想来解决。反转的是两件事:我不在程序中采用硬编码的方式来维护对象的关系了,也不用硬编码的方式来new对象了。

Spring框架

Spring框架实现了控制反转IoC这种思想,Spring框架来new对象和维护对象的关系。

实现方式:依赖注入(DI,Dependency Injection)

依赖:A对象和B对象的关系,注入:通过这种手段,让A和B产生关系。

分两种,set注入和构造方法注入

特点:1、轻量 非侵入式的框架(侵入式:不好做单元测试)2、控制反转 3、面向切面编程 4、容器Bean 5、框架

Spring底层Ioc如何实现的:XML解析+工厂模式+反射机制

Bean的生命周期

分五步:

1.实例化Bean(调用无参构造方法)

2.给Bean属性赋值(调用set方法)

3.初始化Bean(调用Bean的init方法,init方法要自己写自己配)

4.使用Bean

5.销毁Bean(调用Bean的destroy方法,destroy方法需要自己写自己配)

分七步:

1.实例化

2.Bean属性赋值

3.执行Bean后处理器的before方法

4.初始化Bean

5.执行Bean后处理器的after方法

6.使用Bean

7.销毁Bean

分十步:

1.实例化

2.Bean属性赋值

3.检查Bean是否实现了Aware的相关接口,并设置相关依赖

4.执行Bean后处理器的before方法

5.检查Bean是否实现了initializingBean接口,并调用接口方法

6.初始化Bean

7.执行Bean后处理器的after方法

8.使用Bean

9.检查Bean是否实现了DisposableBean接口,并调用接口方法

10.销毁Bean

Spring容器只对单例模式的Bean进行完整的生命周期管理,如果是prototype作用域的Bean,Spring容器只负责将Bean初始化完毕,等客户端程序一旦获取到Bean后,Spring容器就不再管理该对象的生命周期了。

singleton+setter模式下的循环依赖(A的属性需要B赋值,B的属性需要A赋值)是没有问题的。因为spring容器在加载的时候,实例化Bean对象,所有bean对象都会曝光。

在prototype+setter模型下循环依赖是存在问题的,因为是多例模式。如果其中一个是单例,那就没有问题。

三级缓存

三个缓存都是Map集合,Map集合的key存储的都是bean的name(bean id)

一级缓存(豆子):完整的单例Bean对象,这个缓存中的Bean对象的属性都已经赋值了,是一个完整的Bean对象。

二级缓存(青涩的豆子):早期的单例Bean对象,这个缓存中的Bean对象的属性没有赋值,只是一个早期的实例对象。

三级缓存(植株-长豆子的):单例工厂对象,这个里面存储了大量的工厂对象,每一个单例Bean对象都会对应一个单例工厂对象。这个集合中存储的是,创建该单例对象时对应的那个单例工厂对象。

SpringIoc注解式开发

简化XML的配置

声明Bean注解

常见的注解:

@Component 以下三种本质都是component 只是为了方便可读 所以分了三种

@Controller

@Service

@Repository

怎么使用:加入aop的依赖,在配置文件中添加context命名空间,在配置文件中指定扫描的包,在Bean类上使用注解。

负责注入的注解

@Value 注入简单类型

使用@Value注解注入 可以用在属性上 并且可以不写setter方法

也可以使用在set方法、构造方法上。

@Autowired 注入非简单类型 默认根据类型来装配

@Qualifier 和@Autowired联合使用 用名字来装配

用在属性、setter方法、构造方法、构造方法参数上

@Resource 也可以完成非简单类型注入 默认根据名称装配 如果找不到名称 就用类型装配

用在属性上和setter方法上

属于JDK扩展包,需要加依赖。jakarta.annotatiopn-api

JdbcTemplate(不用过多了解)

是对Jdbc的封装,简化JDBC代码。

GoF代理模式

在Java程序中的代理模式的作用

1.当一个对象需要受到保护的时候,可以考虑使用代理对象去完成某个行为。

2.需要给某个对象的功能进行功能增强的时候,可以考虑找一个代理进行增强。

3.A和B无法直接交互,可以用代理模式解决。

三大角色

目标对象,代理对象,公共接口(让客户端在使用代理的时候以为是在用目标对象)

静态代理

代理对象:将目标对象作为代理对象的一个属性,形成关联关系,比继承关系耦合度低。

代理对象含有目标对象的引用,关联关系,has a

创建代理对象的时候要传一个目标对象给代理对象。 (构造方法)

优点:解决OCP问题,采用代理模式的has a 可以减低耦合度

缺点: 类爆炸,假设系统有1000个接口,那每个接口都得有对应的代理类,这样类会急剧膨胀不好维护。

动态代理

字节码生成技术,可以在内存中为我们动态地生成Class字节码,这个字节码就是代理类。

常见技术:

JDK动态代理技术:只能代理接口。

CGLIB动态代理技术:开源代码生成库,可以代理接口也可以代理类。底层是用继承方式实现的,性能比JDK动态代理要好。

Javassist动态代理技术:通过使用javassist对字节码操作为JBoss实现动态aop框架。

面向切面编程AOP

AOP是对OOP的补充延伸。Spring的AOP使用的动态代理是JDK+CGLIB。

一般系统重都会有一些系统服务,比如日志、事务管理和安全等等,这被称为交叉业务。

交叉业务基本是通用的,将和核心业务无关的代码独立地抽取出来,形成一个独立的组件,然后以横向交叉的方式应用到业务流程当中的过程被称为AOP。

优点:代码复用性强,代码易维护,使开发者更关注业务逻辑。

AOP七大术语

连接点JoinPoint:在程序的整个执行流程中,可以织入切面的位置。方法的执行前后,异常抛出之后等位置。

切点Pointcut:在程序执行流程中,真正织入切面的方法。(一个切点对应多个连接点)

通知Advice:又叫增强,具体你要织入的代码。 通知包括 前置通知@Before,后置通知@AfterReturning,环绕通知@Around 最大的范围 在前置通知之前,后置通知、最终通知之后,异常通知@AfterThrowing 发生异常之后执行的通知,最终通知@After 放在finalliy语句块中的通知。

切面Aspect:切点+通知就是切面

织入Weaving:把通知应用到目标对象上的过程

代理对象Proxy:一个目标对象被织入通知后产生的新对象

目标对象Target:被织入通知的对象

两个切面之间谁先执行 用@Order(数字)数字越小 优先级越高

Spring对事务的支持

ACID 原子性 一致性 隔离性 持久性

基于面向切面编程aop的二次封装

声明式事务:基于注解方式(最多) 或者 基于XML配置方式

@Transactional

事务的7种传播行为

REQUIRED:支持当前事务,如果不存在就新建一个(没有就新建,有就加入)

SUPPORTS:支持当前事务,如果当前没有事务,就以非事务的方式执行(有就加入,没有就算了)

MANDATORY:必须运行在一个事务中,如果当前没有事务正在发生,将抛出一个异常(有就加入,没有就抛异常)

REQUIRES_NEW:开启一个新事务,如果一个事务已经存在,则将这个存在的事务挂起(不管有没有,直接开新的,开启的新的和之前的不存在嵌套关系,之前的事务被挂起)

NOT_SUPPORTED:以非事务的方式运行,如果有事务存在,挂起当前事务(不支持事务,存在就挂起)

NEVER:以非事务的方式运行,如果有,就抛出异常(不支持事务,存在就抛异常)

NESTED:如果当前有一个事务正在进行中,则该方法应当运行在一个嵌套式事务中。被嵌套的事务可以独立于外层事务进行提交或回滚。如果外层事务不存在,行为就像REQUIRED一样。(有事务的话,就在这个事务里再嵌套一个完全独立的事务,嵌套的事务可以独立的提交和回滚,没有事务就和REQUIRED一样。)

事务的隔离级别

数据库中读取数据存在的三大问题:

脏读:读取到数据库里没有的数据

不可重复读:在同一个事务中,第一次和第二次读到的数据不一样

幻读:读到的数据是假的。

DEFAULT

READ_UNCOMMITTED 读未提交 存在脏读 可以读到其他事务未提交的数据

READ_COMMITTED 读已提交 解决脏读问题 其他事务提交后才能读到,但是存在不可重复读

REPEATABLE_READ 可重复读 mysql默认级别 解决了不可重复读 只要当前事务不结束,读到的数据一直是一样的,但存在幻读问题

SERIALIZABLE 序列化 解决了幻读问题,事务排队执行,不支持并发。

事务超时

@Transactional(timeout = 10)

表示超过10s如果事务中的所有DML语句还没有执行完毕的话,最终结果会选择回滚

如果想让整个方法的所有代码都计入超时时间的话,可以在方法最后一行添加一行无关紧要的DML语句。

只读事务

@Transactional(readOnly=true)

将当前事务设置为只读事务,在该事务执行过程中只允许select语句执行。不能用增删改。

作用是:启动spring的优化策略,提高select语句的执行效率。

特定回滚

还可以设置哪些异常回滚事务,或者是设置哪些异常不回滚事务。

@Transactional(rollbackFor = RuntimeException.class)

@Transactional(noRollbackFor = NullPointerException.class)

八大设计模式

·简单工厂模式:BeanFactory的getBean方法,通过唯一标识来获取Bean对象。静态工厂模式

工厂方法模式:FactoryBean,在配置文件中通过factory-method属性来制定工厂方法,该方法是一个实例方法。

单例模式:Spring用的是双重判断加锁的单例模式 getSingleton

代理模式:AOP 用的动态代理实现的

装饰器模式:IO流

Spring根据每次请求的不同,将dataSource属性设置成不同的数据源,以达到切换数据源的目的。

Spring中类名里带Decorator和Wrapper的类 都是装饰器模式

观察者模式:Servlet中的ServletContextListener就是观察者模式,观察者ServletContextListener,被观察者:ServletContext 事件:ServletContext对象被创建,或者是被销毁。

Spring中的事件编程模型 ApplicationListener接口,用来监听Application的事件。 Application就是 ApplicationContext。

策略模式:行为性模式,调用不同的方法,适应行为的变化,强调父类的调用子类的特性。

getHandler是HandlerMapping接口中的唯一方法,用于根据请求找到匹配的处理器。

模板方法模式:JdbcTemplate类就是末班类。在模板类的模板方法execute中编写核心算法,具体实现步骤在子类中完成。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询