spring-八股文
- 对IOC的理解
- 单例bean与单例模式
- spring事务传播机制
- spring事务什么时候会失效-√
- spring中创建的bean,生命周期有哪些-※
- spring中的bean是线程安全的吗?
- applicationContext和beanFactory有什么区别?
- spring中的事务是如何实现的?
- spring容器的启动流程是怎样的?(IOC的工作流程)
- spring用到了哪些设计模式?
- spring boot常用注解及其底层实现-※
- springboot是如何启动Tomcat?
- spring cloud 有哪些组件?
- springboot如何解决跨域问题?
- @component和@bean之间的区别
- 过滤器和拦截器之间的区别
- @Async一定会异步执行
- 为什么有些公司会禁用Transaction注解
- @Conditional的作用
- springMVC的理解
- spring MVC执行流程
- 什么是循环依赖?
- 什么是三级缓存?
- @Lazy的作用
- 自动装配的基本原理
- @Resource与@autowired的区别
- SpringBoot中约定优于配置的理解
- ResponseBody的作用
- Controller与RestController的区别? ``` RestController=Controller+responseBody ```
inverse of control,控制翻转,将bean的生成交给spring管理,例如,@autowired自动装配的mapper层对象。
好处:单例bean可以有效复用,减少对象生成的时间成本。各种bean还有自身的应用场景。
spring自动装配出来的对象全都会指向同一个单例bean,不强制约束用户不可创建第二个对象。
单例模式针对的是类而言的,如果某个类应用了单例模式,那么这个类就不可能创建出第二个对象,所有该类的引用都会指向同一个对象,不管是spring自动装配还是用户自己new。
事务注解对应的方法A,调用了方法B,那么B是共用一个事务的逻辑,还是单独开一个新事务,,,,这些策略取决于两个方法定义的事务传播类型
1. REQUIRED(Spring默认的事务传播类型):如果当前没有事务,则⾃⼰新建⼀个事务,如果当前存
在事务,则加⼊这个事务
2. SUPPORTS:当前存在事务,则加⼊当前事务,如果当前没有事务,就以⾮事务⽅法执⾏
3. MANDATORY:当前存在事务,则加⼊当前事务,如果当前事务不存在,则抛出异常。
4. REQUIRES_NEW:创建⼀个新事务,如果存在当前事务,则挂起该事务。
5. NOT_SUPPORTED:以⾮事务⽅式执⾏,如果当前存在事务,则挂起当前事务
6. NEVER:不使⽤事务,如果当前事务存在,则抛出异常
7. NESTED:如果当前事务存在,则在嵌套事务中执⾏,否则REQUIRED的操作⼀样(开启⼀个事
务)
数据库:数据库如果不支持事务,那么spring事务就会失效
Java:
类:事务所在类没有对应的注解,spring没有在容器里面生成该类的bean[类上面没有component之类的注解]
方法:方法上没有加上事务注解或者方法的权限修饰符不是public
调用:调用方法没有使用代理对象,而是通过原对象调用的方法。[自己new]
1.推断构造方法
2.实例化
3.依赖注入[构造方法可能需要部分外部注入属性;成员变量中依赖于其他类,等等多种需要将其他实例注入的情况]
4.处理@postConstruct注解,构造之后还可以执行的自定义处理
5.处理initializingBean接口复写内容,如果实现了该接口的话[前面就是bean的实例化,这一步就是bean的初始化,这就是两者的区别]
6.生成代理对象,最后生成bean
如果bean上有状态,就不是线程安全的
如果bean上没有状态,就是线程安全的
beanFatory的功能,applicationContext都有,但applicationContext还有其他功能[获取系统环境变量、事件发布]
事务这个概念是数据库层面的,spring只是基于数据库的事务功能,对其进行了扩展,提供了方便开发人员操作事务的方式
1.针对使用了Transaction注解的bean,生成代理对象
2.当调用了事务方法,创建新的数据库连接,并关掉自动提交功能
3.然后执行当前方法,会执行若干SQL
4.执行以后,没有发生异常,直接提交该事务
5.执行以后,发生异常,进行回滚[需要回滚的异常级别,在@Transactional注解中的rollbackFor属性配置]
定义:IOC,inverse of control,即控制反转,将bean的创建管理交给spring,有利于单例bean的复用,单例bean还能减少对象创建的时间成本,还能降低对象与对象之间的耦合性。
1.扫描所有beanDefinition对象,将其保存到beanDefinitionMap集合中
2.通过对beanDefinitionMap遍历,可以逐个实例化bean对象,推断构造方法-实例化-依赖注入-postConstruct注解-beanInition接口复写方法-生成代理对象-生成bean
3.applicationContext发布spring容器启动事件
4.多例bean与lazy修饰的单例bean只有使用到的时候,才真正初始化完成,在使用之前,仅有一个代理对象作为依赖注入
工作流程:
1.beanFactory-工厂模式
2.单例bean-单例模式
3.代理对象-代理模式
常用注解有
1.@bean 方法级注解,可用于对应的单例bean对象
2.@autowired 用于生成单例bean的引用;要求原类增加类注解例如component\service\controller\mapper等来交给spring托管
3.@controller\@service\@mapper,这三都是类注解,用于指定controller、service、mapper类,从而可以自动将请求匹配到controller对应方法上,以及自动调用对应的SQL
4.@GetMapping,@PostMapping,用于指定请求的匹配类型,方法接收get请求、post请求等等
具体实现 不太清楚
1.检索是否有tomcat依赖
2.将tomcat实例化,并加入到spring容器中
3.启动tomcat实例
1.实现webMvcConfigurer接口,实现addCoresMapping方法
2.利用注解@CrossOrigin,加到spring boot容器对象上即可
1.用途不同:component声明的是一个普通类,而bean则是在配置类中声明和配置一个bean对象
2.声明不同:component应用的是类 ,而bean应用的是方法上
3.控制不同:component的创建配置过程是由spring管理的,而bean的创建配置过程允许开发人员手动控制
过滤器:filter
拦截器:interceptor[例如操作日志记录的AOP]
1.filter在请求达到servlet之前,interceptor在servlet容器收到请求之后,进入controller之前运行
2.filter依赖于servlet容器[实现的是javax.servlet.Filter接口],interceptor是spring的一个组件[实现的是handlerinterceptor接口]
3.filter基于函数回调,interceptor基于java反射机制
filter-->interceptor.prehandle-->handler-->interceptor.posthandler-->interceptor.afterCompletion-->filter
A:被@Async标记的方法
B:调用A的方法
@Async:
这是一个标记方法为异步执行的注解
spring框架会默认使用一个线程池来管理异步方法的执行,spring框架将A封装成代理对象[这也就是为什么A必须是托管的bean对象的原因],B调用A的时候,实际上都是使用线程池来执行A的方法体
这个注解只是标记A是异步执行的,真正是否异步执行,取决于:
一、要打开功能-@EnableAsync-@Async
二、必须能创建代理对象
2.1 类:spring托管
2.2 方法:必须是public[新版spring貌似protected也可以]
2.3 方法:不能是静态-否则无法创建子类来代理[Spring用的应该是CGLIB]
三、必须要使用代理对象
3.1 调用方与被调用方不能在同一个对象内-否则会绕过代理对象
四、合理配置线程池
4.1.使用@Async必须配置一个合适的线程池来执行异步方法。
[一般spring默认就配置了线程池,但是默认的线程池不是真正的线程池,并没有真正复用线程]
[也可以自定义重新指定线程池,通过对ThreadPoolTaskExecutor进行封装即可,指定
1.setMaxPoolSize
2.setCorePoolSize
3.setThreadNamePrefix
4.initialize
即可将对象返回给注解--->@Async("asyncTaskExecutor")
]
事务注解主要存在以下隐患
正常情况:如果事务耗时较长,那么占用锁时间也会较长,甚至有可能耗尽数据库连接池,影响程序的正常执行
非正常情况:如果事务中还存在嵌套情况,有可能造成未知的异常情况
项目:随着项目的复杂程度提升,事务的控制逻辑越来越复杂,降低了代码的可读性与可维护性
作用是给 bean是否装载到容器 增加一个条件判断
入:注解接受一个或多个实现了condition接口的类;condition接口里面有一个matches方法需要重写
出:可以修饰在类上面,也可以修饰在方法上面。
springMVC是spring生态下,基于MVC架构设计的webFramwork模块,是一种web框架
M:model,模型
V:view,视图
C:controller,控制器
其组件主要有:前端控制器(dispatcherServlet),控制器映射器(handlerMapping),控制器适配器(handlerAdapter),视图解析器(viewResolver)
其主要执行流程见《spring MVC执行流程》
循环依赖就是在spring在构建单例bean对象的时候,依赖注入阶段,A与B互相之间有依赖关系
往A注入B的时候,单例池里面既没有A也没有B,触发B的构建,往B注入A的时候,由于单例池里面没有A,又会触发A的构建,
从而导致无法正常实例化、初始化这些单例bean
三级缓存是解决循环依赖的一种解决方案
第一级缓存 singletonObjects<beanName,单例 bean>:用于保证所有bean是单例的
保存的是 经过完整生命周期,创建完成的单例bean对象
第二级缓存 earlySingletonObjects<beanName,单例bean>:用于防止出现多代理问题
保存的是,在出现循环依赖的情况下,自己都没有创建完,需要提前暴露给其他单例bean用的单例bean对象
第三级缓存 singletonFactories<beanName,()->getEarlyBeanReference(beanName,mbd,bean)>:用于打破循环
保存的是bean对应的普通对象,用于循环依赖的时候,能提供一个普通对象,用于生成代理对象
基本流程:
背景:A->B[A依赖于B] A->C[A依赖于C]
1.构建A的普通对象-->保存到第三级缓存,用于之后调用打破循环
1.x 记录creatingset 判断循环依赖
2.B依赖注入:
2.1 构建B的普通对象-->保存到第三级缓存,用于之后调用打破循环
2.2 找依赖对象A:单例池->earlySingletonObjects->singleFactories->返回代理对象->earlySingletonObjects
2.3 依赖注入,@postConstruct,initializeBean接口实现,生成代理对象,放入单例池[AOP等一系列操作]
2.4 生成的B代理对象返回给A
3.C依赖注入:
2.1 构建C的普通对象-->保存到第三级缓存,用于之后调用打破循环
2.2 找依赖对象A:单例池->earlySingletonObjects
2.3 依赖注入,@postConstruct,initializeBean接口实现,生成代理对象,放入单例池[AOP等一系列操作]
2.4 生成的C代理对象返回给A
4.通过earlyProxyReference判断是否需要继续AOP等操作
5.取出earlySingletonObjects提前放入的代理对象,放入单例池[由于二级缓存里面存放的是三级缓存造出来的代理对象,三级缓存是通过当前的普通对象造的,因此,本质上应当是同一个对象引用]
1.当构造函数带参的时候,spring是无法通过三级缓存解决循环依赖的问题
2.lazy可以通过将bean代理对象直接依赖注入,从而打破循环,直接实例初始化成功
3.直到用的时候,才会去找容器对应的bean对象的方法
定义:自动装配简而言之就是将第三方依赖的bean自动装载到IOC容器里面,不需要开发人员去写bean的配置信息
使用:
1.引入spring-boot-starter依赖
2.@SpringBootApplication注解开启功能,这是一个复合注解,实际是@EnableAutoConfiguration注解开启的功能
该功能的实现主要依赖于以下三步:
1.引入依赖的时候,第三方依赖里面应当包含@Configuration配置类,以@Bean注解的方式声明
2.这个配置类的的全路径应当写入,classpath:/META-INF/spring.factories,这个文件里面[默认情况下,一般官方组件已经完成这步骤了,有需要的话,就要自己修改],SpringFactoriesLoader加载这个文件以后,spring就知道了对应的bean在哪里了。
3.知道bean在哪里以后,ImportSelector 接口就能动态加载这些bean。
两个注解都可以用于声明bean对象
@autowired
类型:可以
名称:必须搭配@qualified注解同时使用
@Resource
类型:可以
名称:可以
解释:约定大于配置,是一种开发理念,核心思想是让开发人员减少对配置项的维护,从而聚焦于业务逻辑
spring boot如何体现:
spring boot本身就是这个理念的产物,它类似于一个脚手架,方便开发人员快速spring生态下的应用程序
1.jar包依赖管理
2.自动装配机制中的第三方组件集成
3.应用部署到容器
4.默认加载application配置文件
声明 将接口方法的返回值转成JSON字符串 并输出
原先没有该注解 仅返回给前端数据 数据由前端界面接收
有了该注解 会将返回值转成JSON字符串 并放入一个模板HTML的body里面 从而输出到浏览器
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下