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配置的<bean>的信息封装成一个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框架常见的注解

  • 13
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码已经练习两年半

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值