# Spring
# Spring中的单例Bean是线程安全的吗?
- singleton Bean 是线程安全的,因为 Spring 容器会保证在同一个容器中,一个 Bean 只有一个实例。
- prototype Bean 是非线程安全的,因为每次获取 Prototype Bean 时,Spring 都会创建一个新的实例。
@Scope("singleton") // 默认是单例
解答:
只是某种程度上线程安全
不是线程安全的,因为单例 Bean 的属性是共享的,如果多个线程同时访问一个单例 Bean 的属性,可能会出现线程安全问题。可以通过加锁/多实例解决。
# 什么是AOP?
AOP(Aspect Oriented Programming)面向切面编程,用于将与业务无关,但却对多个对象产生影响的公共行为封装到一个独立的模块中,这些公共行为成为切面(Aspect),减少重复代码,提高代码的复用性。
- 对方法的增强,不需要修改原有的代码,只需要在需要增强的方法上添加一个切面,即可实现增强。
可以通过 AOP 实现的功能:
- 日志记录
- 事务处理
# Spring中的事务是如何实现的?
Spring 事务的实现是基于 AOP 的,通过 AOP 实现事务管理,Spring 提供了两种事务管理方式:
- 编程式事务管理
通过 TransactionTemplate实现编程式事务管理,对业务代码进行事务管理。
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
// 业务代码
}
});
- 声明式事务管理 本质是 AOP 通过代理对象实现的
通过 @Transactional 注解实现声明式事务管理,对业务方法进行事务管理。
@Transactional
public void insertUser(User user) {
// 业务代码
}
# Spring中的事务失效场景有哪些?
- 异常被捕获 事务默认只在抛出运行时异常时回滚,如果异常被捕获,事务将不会回滚。
- 抛出检查异常 事务默认只在抛出运行时异常时回滚,如果抛出检查异常,事务将不会回滚。(加上 rollbackFor = Exception.class 可以回滚)
- 非public方法导致事务失效 Spring 事务是通过 AOP 实现的,只能对 public 方法进行事务管理,非 public 方法事务失效。
# BeanDefinition是什么?
Spring容器在进行实例化时,会将xml配置的
的信息封装成BeanDefinition对象,BeanDefinition对象是对bean配置信息的封装,包括bean的类名、属性、构造方法、初始化方法、销毁方法等。
- beanClassName:bean的类名
- scope:bean的作用域
- lazyInit:是否懒加载
- initMethodName:初始化方法
- propertyValues:属性值
# Spring的Bean的初始化过程是怎样的?
- 构造函数 BeanDefinition
- 依赖注入
- Aware接口回调
- BeanPostProcessor的前置处理
- 初始化方法 InitializingBean 自定义初始化方法
- BeanPostProcessor的后置处理 AOP
总结:Bean的初始化过程是在Bean的实例化之后,初始化之前,通过BeanPostProcessor的前置处理和后置处理来实现的。
# 什么是Spring的循环依赖?
Spring容器在实例化Bean时,如果A依赖B,B依赖A,就会产生循环依赖。
Spring解决循环依赖的方式:三级缓存
- 一级缓存 singletonObjects:存放完全初始化的Bean
- 二级缓存 earlySingletonObjects:存放原始的Bean
- 三级缓存 singletonFactories:存放Bean的工厂
# 构造方法出现循环依赖
public class A {
private B b;
public A(B b) {
this.b = b;
}
}
public class B {
private A a;
public B(A a) {
this.a = a;
}
}
解决方式:通过**@Lazy**注解实现懒加载,什么时候需要Bean时再去创建Bean。
# SpringMVC的执行流程是怎样的?
- 用户发送请求到前端控制器 DispatcherServlet
- DispatcherServlet 根据请求信息调用 HandlerMapping(处理映射器)
- HandlerMapping找到具体的处理器,生成处理器对象及处理器拦截器一并返回给 DispatcherServlet
- DispatcherServlet 调用 HandlerAdapter (处理器适配器)
- HandlerAdapter 经过适配调用具体的处理器(Controller,也叫后端控制器)
- Controller 执行完成返回 ModelAndView
- 处理器适配器将 Controller 执行结果 ModelAndView 返回给 DispatcherServlet
- DispatcherServlet 将 ModelAndView 传给 ViewReslover 视图解析器
- 视图解析器解析后返回具体 View
- DispatcherServlet 对 View 进行渲染视图(即将模型数据填充至视图中)
- DispatcherServlet 响应用户
# SpringBoot自动装配原理是什么?
SpringBoot的自动装配是通过 @EnableAutoConfiguration 注解实现的,@EnableAutoConfiguration 注解是 SpringBoot 的核心注解之一,用于开启自动配置功能。
- @EnableAutoConfiguration 该注解通过@Import注解导入对应的配置选择器。
- 内部就是读取META-INF/spring.factories文件。
- 根据条件注解例如@ConditionalOnClass来判断是否是否有对应的class文件,如果有则自动配置。
# Spring的常见注解
@Component
、@Service
、@Controller
、@Repository
:用于标注Bean@Autowired
:自动装配@Qualiifer
:根据名称进行依赖注入@Scope
:设置Bean的作用域@Configration
:配置类@Bean
:定义Bean@ComponentScan
:扫描包@Import
:使用@Import导入的类会被Spring容器托管@Aspect
、@Pointcut
、@Before
、@After
、@Around
:用于切面编程
# SpringMVC的常见注解
@RequestMapping
:用于映射请求路径,可以定义在类上或方法上@RequestBody
:注解实现接收http请求的json数据,将json数据转换为对象@ResponseBody
:注解实现将controller方法返回的对象转为json格式@PathVariable
:用于接收路径参数@RequestParam
:用于接收请求参数@RequestHeader
:用于接收请求头信息@RestController
:相当于@Controller和@ResponseBody的结合
# SpringBoot的常见注解
@SpringBootApplication
:SpringBoot的核心注解,用于开启自动配置@EnableAutoConfiguration
:开启自动配置@ComponentScan
:扫描包