Spring框架知识点
Spring框架中的单例Bean是线程安全的吗?
答:Spring框架中有一个@Scope注解,默认值是singleton,单例的,当bean中定义了可变参数,就不是线程安全的。我们建议不要注入有状态的变量,如果必须使用,建议使用ThreadLocal进行变量副本保存,保证线程安全。
什么是AOP?项目中有没有使用到AOP?
答:AOP是面向切面编程,是指哪些与业务实现无关,但又对多个对象产生影响的公共行为和逻辑,将他们横向抽取并封装为一个可重用的模块,这个模块就叫“切面”。作用就是降低代码耦合度,提高了系统的可维护性
常见的AOP使用场景:
- 日志
- Spring中内部的事务处理
- 异常处理
Spring中的事务是如何实现的?
Spring中事务失效的场景有哪些?
情况一:异常捕获处理
情况二:抛出非运行时(检查)异常
情况三:非public方法导致的事务失效
Spring的bean的生命周期?
首先了解BeanDefinition
BeanDefinition定义了Bean的基本信息,构造函数进行创建,依赖注入,Aware接口,初始化方法之前的后置处理器,初始化方法,初始化方法包括InitialzingBean和自定义init方法,初始化后的后置处理器,AOP就是在这里进行的:
其中,BeanDefinition -> 构造函数 属于是Bean的创建
下面都属于初始化赋值
对一个bean进行增强的时候,就可以在after后置处理器进行操作。
@Override
public Object postProcessAfterInitialization(Object bean,String beanName) {
if(beanName.equals("user")) {
// cglib代理对象
Enhancer enhancer = new Enhancer();
//设置需要增强的类
enhancer.setSuperClass(bean.getClass());
//执行回调方法,增强方法
enhancer.setCallback(new InvocationHandler() {
@Override
public Object invoke(Object o,Method method,Object[] objects) throws Throwable {
return method.invoke(method,objects);
}
});
return enhancer.create();
}
}
Spring中的循环引用问题
所谓的循环依赖就是类A中注入了类B,类B也注入了类A:
死循环产生:
那么Spring是如何解决的呢?
三级缓存解决循环依赖:
Spring解决循环依赖是通过三级缓存,对应的三级缓存如下所示:
一级缓存中存放的是单例Bean,如果一个Bean是多例的,那么就不会存放,需要的时候会再创建一个。
二级缓存中存放的Bean是没有走完生命周期的,比如刚经历过构造函数的Bean。
三级缓存
一级缓存的作用:限制Bean只存在一份,即实现singleton scope,解决不了循环依赖。
如果想要打破循环依赖了,就需要一个中间人的参与,这个中间人就是二级缓存:
想要创建A,先创建了半成品A,放入到二级缓存中,接着创建半成品B,继续创建B的时候,先拿着半成品A创建完整的B,接着把B放入一级缓存,这个时候半成品A就可以创建完整A,接着A放入一级缓存,创建完成。
但是如果A是代理对象的话,就是A需要增强的话,二级缓存解决循环依赖就不够了。
三级缓存:
还有个经典问题:
由于bean的生命周期中构造函数是第一个执行的,spring框架并不能解决构造函数的依赖注入。
SpringMVC的执行流程
客户端(浏览器)发送请求, DispatcherServlet
拦截请求。
DispatcherServlet
根据请求信息调用 HandlerMapping
。HandlerMapping
根据 URL 去匹配查找能处理的 Handler
(也就是我们平常说的 Controller
控制器) ,并会将请求涉及到的拦截器和 Handler
一起封装。
DispatcherServlet
调用 HandlerAdapter
适配器执行 Handler
。
Handler
完成对用户请求的处理后,会返回一个 ModelAndView
对象给DispatcherServlet
,ModelAndView
顾名思义,包含了数据模型以及相应的视图的信息。Model
是返回的数据对象,View
是个逻辑上的 View
。
ViewResolver
会根据逻辑 View
查找实际的 View
。
DispaterServlet
把返回的 Model
传给 View
(视图渲染)。
把 View
返回给请求者(浏览器)
著作权归JavaGuide(javaguide.cn)所有 基于MIT协议 原文链接:https://javaguide.cn/system-design/framework/spring/spring-knowledge-and-questions-summary.html
SpringBoot中的自动配置原理
在SpringBoot项目中的引导类上有一个注解@SpringBootApplication,这个注解是对三个注解进行了封装,分别是:
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @ComponentScan
其中,@EnableAutoConfiguration是实现自动化配置的核心注解。该注解通过**@Import注解导入对应的配置选择器。内部就是读取了该项目和项目所用的jar包的classpath路径下META-INF/spring.factories文件中的所配置的类的全类名。在这些配置类中定义的Bean会根据条件注解所制定的条件来决定**是否需要将其导入到Spring容器中。
条件判断会有想**@ConditionalOnClass**这样的注解,判断是否有对应的class字节码文件,如果有则加载该类,把这个配置类的所有的Bean放入容器。
Spring框架常见注解