• Spring总结


    Spring框架中的单例bean是线程安全的吗?

    Spring的单例bean不是线程安全的。

    成员变量和成员方法需要考虑线程安全的问题。

    局部变量一般是没有线程问题的。

    Spring的bean中例如Service类和DAO类是无状态的类。

    不能被修改的类就是无状态的类,所以说无状态的类是线程安全的。

    总结:

    不一定线程安全。

    Spring框架中有一个@Scope注解,默认值就是singleton,单例的。

    一般在spring的bean中都是注入无状态的类,这样是没有线程安全问题的,如果在bean中定义了可修改的成员变量,就要考虑线程安全了,可以使用多例或者加锁来解决。

    什么是AOP?

    面向切面编程,将那些对多个对象产生影响的公共行为和逻辑,抽取出来封装成一个可重用的模块,这个模块就叫做“切面”。

    底层是由动态代理实现的。

    优点:减少重复代码,降低模块间的耦合度,提高了可维护性。

    常用场景:记录操作日志,缓存处理,spring内置的事务管理。

    spring中事务是如何实现的?

    spring支持编程式事务和声明式事务。

    编程式事务对业务代码有侵入性,所以项目很少使用。

    大多都使用声明式事务,本质就是使用aop对方法进行拦截,在方法前后以及异常进行事务管理的功能增强。

    总结:

    什么是AOP?

    面向切面编程,将一些跟业务无关,但是却对多个对象产生影响的公共行为和逻辑,抽取出来生成公共模块进行复用,降低耦合度。

    项目中的场景应用?

    记录操作日志,缓存处理,spring的事务管理。

    一般都是用环绕通知Around和切点表达式pointCut(用来寻找方法)实现。

    spring的事务如何实现的?

    就是通过aop,对方法进行功能增强,在方法执行前开启事务,在方法结束后或异常时回滚提交事务。

    spring中事务失效的场景有哪些?

    异常捕获处理

    在方法中已经将异常捕获处理掉并没有抛出。

    事务只有捕捉到了抛出的异常才可以进行处理,如果有异常业务中直接捕获处理掉没有抛出,事务是无法感知到的。

    解决:在catch块throw抛出异常。

    抛出检查异常

    spring默认只会回滚非检查异常。

    解决:

    非public方法导致事务失效

    spring为方法创建代理,添加事务通知,前提条件都需要方法是public的。

    解决:把方法改为public。

    总结:

    异常捕获处理,自己处理了异常,没有抛出,解决:手动抛出。

    抛出检查异常,配置rollbackFor属性为Exception.class。

    非public方法导致的事务失效,改为public。

    spring的bean的生命周期

    Spring容器会在进行实例化时,将xml配置的的信息封装成一个BeanDefinition对象,Spring根据BeanDefinition来创建Bean对象,里面有很多属性来描述Bean。

    beanClassName:bean的类名

    initMethodName:初始化方法名称

    properryValues:bean的属性值

    scope:作用域

    lazyInit:延迟初始化

    最后销毁bean

    bean的创建和赋值是分开的

    总结

    通过BeanDefinition获取bean的定义信息

    调用构造函数实例化bean

    bean的依赖注入

    实现Aware接口(BeanNameAware,BeanFactoryAware,ApplicationContextAware)

    Bean的后置处理器BeanPostProcessor-前置

    初始化方法(InitializingBean,init-method)

    Bean的后置处理器BeanPostProcessor-后置

    销毁bean

    spring中的循环引用

    Spring的三级缓存

    一级缓存 singletonObjects 单例池,缓存已经经历了完整的生命周期,已经初始化完成的bean对象。

    二级缓存 earlySingletonObjects 缓存早期的bean对象(生命周期还没走完)

    三级缓存 singletonFactories 缓存ObjectFactory,表示对象工厂,用来创建某个对象。

    总结

    循环依赖就是两个或者两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于A。

    循环依赖在spring中是允许存在的,spring框架依据三级缓存已经解决了大部分的循环依赖。

    一级缓存 singletonObjects 单例池,缓存已经经历了完整的生命周期,已经初始化完成的bean对象。

    二级缓存 earlySingletonObjects 缓存早期的bean对象(生命周期还没走完)

    三级缓存 singletonFactories 缓存ObjectFactory,表示对象工厂,用来创建某个对象。

    首先实例化A—》原始对象A生成一个ObjectFactory对象,存入三级缓存—》需要注入B但是B不存在,就去实例化B—》原始对象B生成一个ObjectFactory对象,存入三级缓存—》需要注入A,就去三级缓存中获取—》通过A的ObjectFactory对象创建代理对象,存入二级缓存—》将A的代理对象注入给B—》B创建成功,存入一级缓存—》将B注入给A—》A创建成功,存入一级缓存。

    构造方法出现循环依赖怎么办?

    由于bean的生命周期中构造函数是第一个执行的,spring框架并不能解决构造函数的依赖注入。

    解决:使用@Lazy进行懒加载,什么时候需要对象什么时候再创建bean对象。

    SpringMVC的执行流程

    JSP版

    用户发送出请求到前端控制器DispatcherServlet。

    前端控制器收到请求后调用处理器映射器HandlerMapping。

    处理器映射器根据路径找到具体的处理器的类名和方法名,生成处理器对象(如果有拦截器就会一起封装到其中),返回给DispatcherServlet。

    前端控制器调用处理器适配器HandlerAdapter。

    处理器适配器结果适配调用具体的处理器。

    执行完后将ModelAndView对象返回给处理器适配器,处理器适配器将它返回给前端控制器。

    前端控制器将模型和视图对象传给视图解析器ViewReslover。

    视图解析器解析后将具体的View返回给前端控制器。

    前端控制器根据View进行渲染。

    最后将数据和视图响应给用户。

    前后端分离版

    用户发送请求到前端控制器。

    前端控制器收到请求后将调用处理器映射器

    处理器映射器根据路径找到具体的处理器类名和方法名,然后生成处理器对象,如果有拦截器也会将拦截器一起封装,最后返回给前端控制器。

    前端控制器调用处理器适配器。

    处理器适配器经过适配调用具体的处理器。

    会将方法上添加了@ResponseBody的返回值通过HttpMessageConverter来将返回值传换成JSON返回给前端控制器,然后前端控制器进行响应用户。

    Springboot自动装配原理

    在springboot项目中的引导类上有一个注解@SpringBootApplication,这个注解对三个注解进行了封装,分别是:

    @SpringBootConfiguration

    @EnableAutoConfiguration

    @ComponentScan

    其中@EnableAutoConfiguration是实现自动化配置的核心注解。这个注解通过@Import注解将对应的配置导入。

    内部就是读取了该项目和该项目引用的jar包的classpath路径下META-INF/spring.factories文件中的所配置的类的全类名。在这些配置类中所定义的Bean会根据条件注解所指定的条件来决0是否将其导入到Spring容器中。

    条件判断会有像@ConditionalOnClass这样的注解,判断是否有对应的class文件,如果有则加载该类,把这个配置类的所有的Bean放入spring容器中使用。

    Spring框架常见的注解

  • 相关阅读:
    Spring Boot 3.2发布:大量Java 21的支持上线,改进可观测性
    UObject 创建、销毁、内存管理、垃圾回收
    开源机密计算平台:蓬莱-OpenHarmony
    目标检测网络之Fast-RCNN
    修改时间服务器-域控环境
    【react小项目】bmi-calculator
    MySQL梳理
    【Java基础篇 | 类和对象】--- 聊聊什么是内部类
    你的Edge浏览器难道不需要一个好看的浏览器起始页嘛
    通过数据可观测性进行价值工程和数据成本优化
  • 原文地址:https://blog.csdn.net/weixin_62773644/article/details/136609712