框架篇
Spring单例bean是线程安全的吗
-
不是线性安全的,Spring框架中有一个@Scope注解,默认值是singleton,单例的.
-
因为一般spring的bean中注入无状态的对象,没有线程安全问题,如果bean中定义了可修改的成员变量,是有线程安全问题的,可以通过加锁或者多例来解决
AOP的理解
面向切面编程,用于将那些与业务无关的,但却对多个对象产生影响的公共行为和逻辑,抽取成公共模块复用,降低耦合.
使用场景: 记录操作日志,springbean生命周期里,核心是使用aop的环绕通知+切入点表达式(找到要记录的日志的方法),通过环绕通知的参数获取请求方法的参数,保存到数据库.
spring事务实现: 本质是通过aop,对方法前后进行拦截,执行方法前开启事务,执行完目标方法之后根据执行情况提交或者回滚事务.
事务失效的场景
- 异常捕获处理,处理掉异常,不能进行回滚,解决就是手动抛出异常
- 抛出受查异常,解决办法配置rollbackFor属性为Exception.class
- 非public方法导致事务失效
springbean的生命周期
springbean生命周期分为四个阶段:实例化,属性赋值,初始化,销毁
- 实例化bean
- 设置对象属性
- 处理Aware接口:根据对象实现不同的aware接口,注入相关的aware实例
- 如果想对bean进行自定义处理,让bean实现BeanPostProcessor接口,调用其方法
- 如果实现了InitializingBean接口,执行afterProperitesSet()方法
- 如果配置了init-method属性,会自动调用初始化方法
- 实现BeanPostProcessor接口,调用postProcessAfterInitialization()方法实现增强
- 如果bean实现了DisposableBean接口,如果不再需要bean,执行清理,调用destroy()方法
- 如果spring配置了destroy-method方法,会自动调用其销毁方法
spring循环引用(循环依赖)
- 循环依赖是指两个或者以上的bean互相持有对方,最终形成闭环
- spring框架依据三级缓存解决了大部分的循环依赖,具体就是当出现循环依赖时,比如A依赖B,B依赖A。Spring会先创建A,并将A放入三级缓存中,然后在为A注入属性时发现需要B,于是去创建B,并将B也放入三级缓存中。接着,在为B注入属性时发现需要A,于是就从三级缓存中通过工厂对象获取到A,并注入到B中。然后完成B的初始化,并将B放入一级缓存中。最后回到A,完成A的属性注入和初始化,并将A也放入一级缓存中。
- 构造方法出现循环依赖: 使用@Lazy解决
- 一级缓存: 单例池,缓存已经经历完整的生命周期,已经初始化完成的bean对象
- 二级缓存: 缓存早期的bean对象
- 三级缓存: 缓存对象工厂,用来创建某个对象
spring mvc处理请求流程
Spring MVC 处理请求的流程大致如下:
- 用户发送请求至前端控制器
DispatcherServlet
。 DispatcherServlet
收到请求后调用HandlerMapping
处理器映射器。- 处理器映射器根据请求 URL 找到具体的处理器(后端控制器),生成处理器对象及处理器拦截器(如果有则生成)一并返回给
DispatcherServlet
。 DispatcherServlet
调用HandlerAdapter
处理器适配器去调用处理器。- 处理器适配器执行处理器。
- 处理器执行完成后给处理器适配器返回
ModelAndView
。 - 处理器适配器向前端控制器返回
ModelAndView
。ModelAndView
是 Spring MVC 框架的一个底层对象,包括Model
和View
。 - 前端控制器请求视图解析器去进行视图解析,根据逻辑视图名来解析真正的视图。
- 视图解析器向前端控制器返回
View
。 - 前端控制器进行视图渲染,就是将模型数据(在
ModelAndView
对象中)填充到 request 域。 - 前端控制器向用户响应结果。
springboot自动配置原理
- 当我们启动一个Spring Boot应用时,会执行一个带有@SpringBootApplication或@EnableAutoConfiguration注解的主类的main方法。
- 这些注解会触发Spring Boot的自动配置功能,首先会扫描classpath中的所有jar包,寻找META-INF/spring.factories文件,这些文件中会列出所有可用的自动配置类。
- 然后,Spring Boot会根据jar依赖和其他条件,筛选出符合条件的自动配置类,并将其加载到Spring容器中。
- 接着,Spring Boot会根据属性文件中的配置,绑定相应的属性到自动配置类或bean上。
- 最后,Spring Boot会根据自动配置类中定义的bean或条件,创建相应的bean实例,并注入到其他组件中。
spring常见注解
boot:
- @SpirngBootConfiguration: 实现配置文件的功能
- @EnableAutoConfiguration: 打开自动配置功能
- @ComponentScan: spring组件扫描
mvc:
- @RequestMapping: 用于映射请求路径
- @RequestBody: 注解实现接收http请求的json数据,并将其转为Java对象
- @RequestParam: 指定请求参数的名称
- @PathVirable: 从请求路径获取参数,传递给方法的形参
- @ResponseBody: 将对象转化为json对象发送给客户端
- @RequestHeader: 获取请求头数据
- @RestController: @Controller+@ResponseBody
spring:
- @Compoent,@Controller,@Service,@Repository: 用在类上实例化Bean
- @Autowired: 用在字段上,根据类型注入
- @Qualifier: 结合@Autowired,用于根据名称注入
- @Scope: 标注Bean的作用范围
- @Configuration: 指定当前类为spring配置类,当容器创建会从该类上加载注解
- @ComponentScan: 初始化容器要扫描的包
- @Bean: 使用在方法上,标注将该方法的返回值储存到Spring容器中
- @Import: 加载到IOC容器中
- @Aspect,@Before,@After,@Around,@Pointcut: aop常用注解
Mybatis的执行流程
- 读取MyBatis配置文件: mybatis-config.xml加载运行环境和映射文件
- 构造会话工厂SqISessionFactory
- 会话工厂创建SqlSession对象(包含了执行SQL语句的所有方法)
- 操作数据库的接口,Executor执行器, 同时负责查询缓存的维护
- Executor接口的执行方法中有一个MappedStatement类型的参数, 封装了映射信息
- 输入参数映射
- 输出结果映射
Mybatis延迟加载
- 延迟加载: 需要用到数据时在进行加载
- Mybatis支持一对一的关联对象和一对多的关联对象的延迟加载
- 在Mybatis配置文件中通过lazyLoadingEnabled = true|false
底层原理:
- 使用CGLIB创建目标对象的代理对象
- 当调用目标方法时,进入拦截器invoke方法, 发现目标方法是null值,执行sq|查询
- 获取数据以后,调用set方法设置属性值,再继续查询目标方法,就有值了
Mybatis缓存
- 一级缓存:基于PerpetualCache的HashMap本地缓存,其存储作用域为Session,当Session进行flush或
close之后,该Session中的所有Cache就将清空,默认打开一-级缓存 - 二级缓存是基于namespace和mapper的作用域起作用的,不是依赖于SQL session,默认也是采用
PerpetualCache, HashMap 存储。需要单独开启,-个是核心配置-一个是mapper映射文件
二级缓存什么时候会清理数据: 当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了新增、修改、删除操作后,默认该作用域下所有select中的缓存将被clear.