【面试准备四】sping

目录

spring springmvc springboot springcloud区别

springMVC 工作流

spring设计模式

Bean

作用域

生命周期

AOP代理 2种

spring循坏依赖

spring如何解决循环依赖

三级缓存是什么

为什么必须要三级缓存

构造方法注入为什么无法解决循环依赖

Spring事务

事务四个特性

spring事务配置方式(两种)

spring事务传播机制 7种

常引发安全性问题

事务隔离级别 5种

事务实现原理


spring springmvc springboot springcloud区别

spring:控制反转(IOC)和面向切面(AOP)的容器框架。ioc是容器管理bean;aop公共提出来,比如鉴权、操作日志等等;

springMVC是spring的一部分,spring还包括springJDBC、springTest等;

springBoot秉承约定大于配置的原则,省去spring复杂的配置,基于spring的一套快速开发整合包,可以快速搭建一个spring服务;

springCloud是基于springBoot开发的微服务包,专注于服务管理。Eureka:服务注册、zuul:网关;security:安全控制(权限)、ribbon:负载均衡、hystrix:熔断器;feign:http客户端

springMVC 工作流

https://blog.csdn.net/floating_dreaming/article/details/89089214

1. 用户请求到DispatcherServlet(中央处理器)到HanderMapping(映射处理器)获取对应的Handler;

2. DispatcherServlet请求到对应适配器处理器HandlerAdapter,HandlerAdapter调用对应的后端处理器(Controller)处理相应业务逻辑,返回view给HandlerAdapter返回DispatcherServlet,

3. DispatcherServlet再到视图解析器ViewResolver中获取对应的view,DispatcherServlet根据Model渲染数据到view,再返回客户。

0

spring设计模式

1. 简单工厂:BeanFactory,配置bean的xml,加载xml到XmlBeanFactory factory中,factory.getBean(beanName)得到对应的bean。三级缓存中存放的就是它的map。意义:用它来注入依赖对象

2. 工厂模式:FactoryBean,getObject的时候,返回的不是FactoryBean对象,而是T.getObject的对象。比如jdbc,SqlSessionFactoryBean,返回的就是一个sqlSession的对象

3. 单例模式:spring默认注入的bean基本上都是单例。提供一个全局可以访问此类的唯一对象

4. 适配器模式: HandlerAdapter,类似于外界统一提供usb接口,用户如果需要typc-c,则需要一个usb转type-c的接口(适配器)。将类的接口转化为用户所期待的,使得不能在一起工作的类可以在一起工作。实现解藕,单一指责。

spring中HandlerAdapter就是一个很清晰的例子。如果新增一个Controller,则需要在DispatcherServlet中判断新增的Controller然后处理,则会增加很多if else,代码很难维护,并且需要修改spring源码(根本不可能),spring也不会穷举所有Controller,因为不同项目组使用是不一样的。所以提出了适配器,就是XXXController随意创建,如果现有HandlerAdapter适配器处理不了,则可以定义新的XXXHandlerAdapter(support方法:是否是XXXController对象,handle调用XXXController的处理方法),该适配器只要实现了implements HandlerAdapter,则在项目启动的时候,DispatcherServlet会把其放到List中,来一个请求会根据请求获取对应的HandlerAdapter(List依次support方法判断是不是)进行处理(调用handle)。

举例:https://blog.51cto.com/haolloyin/346128

简化spring代码:https://www.cnblogs.com/tongkey/p/7919401.html

5. 责任链模式:请求被传递,直到被处理,如果没处理传递给下一条处理器处理。

List, for循环依次每个filter进行处理。过滤器拦截器可以依次传递下去执行

6. 动态代理模式:aop,如果类实现了接口用jdk;如果没有实现接口,用gclib

Bean

作用域

1. 单例:容器启动时,唯一注入一个,在整个容器中只有一个;

2. 多例(原型):多个实例,在getBean或者注入其他class实例时,都会生成一个新的bean。每次访问的时候bean都不是一样的;

3. request:一个请求生命周期,对于每次HTTP请求,使用request定义的Bean都将产生一个新实例

4. session:一个会话周期,对于每次HTTP Session,使用session定义的Bean都会产生一个新实例

5. globalSession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例

生命周期

https://www.jianshu.com/p/1dec08d290c1

https://www.cnblogs.com/javazhiyin/p/10905294.html

实例化(调用构造方法)

属性注入(setter)

aware相关(BeanNameAware.setBeanName -> BeanFactoryAware.setBeanFactory -> AppplicationContextAware.setAppplicationContext -> BeanPostProcessor.postProcessorBeforeInitionlization预处理 -> InitionlizationBean.afterPropertiesSet)

初始化

BeanPostProcessor.postProcessorAfterInitionlization -> bean可以销毁了? -> DisposableBean.destory()

销毁

结束

AOP代理 2种

https://www.jb51.net/article/191673.htm

静态代理:手动写的,运行前已存在;被代理类变、代理类也需要变,基本一一对应,难以维护

动态代理:自动生成该对象的代理对象,把该对象放在target中,然后该对象调用方法的时候会先调用invoke函数(jdk)或者intercept(gclib)函数。jdk、gclib两种方式

jdk、gclib区别:

1. jdk需要类实现接口,gclib不需要;

2. jdk是自带的,gclib需要引入第三方库,spring-core中就有gclib;

3. cglib是生成一个代理类的子类,所以代理类的static、final、private方法都不会被代理

spring中:

如果类实现了接口用jdk;如果没有实现接口,用gclib

spring循坏依赖

spring如何解决循环依赖

构造方法注入无法解决

setter注入可以解决(A依赖B,B依赖A),通过三级缓存。初始化一个对象时包括:实例化对象,然后填充属性,initBean。实例化也就是调用构造器(必须用构造器,所以构造器注入的无法解决)

实例化bean,这里A构造器,为半成品

然后属性B字段的时候,发现B没初始化,所以又去初始化B,

实例化B的时候,把A的半成品塞进去A字段属性,

递归B塞给A对象的B字段。

三级缓存是什么

三级缓存 map:singletonObjects(完全初始化的bean集合),earlySingletonObjects(半成品,叫做代理),singletonFactories(单例对象工厂)

半成品的bean,第一次放在singletonFactories中,第二次访问放到earlySingletonObjects,完成初始化好了放到singletonObjects。

为什么必须要三级缓存

如下图,如果类有aop,则最后得到的是该类的代理(因为该类被aop,所以每次访问该对象的时候都会先经过aop,所以最后得到的是这个对象+aop,也就是该对象的代理),所以和放在B中的A对象不是一个东西,所以需要三级缓存,singletonFactories会返回A的代理(如果A没有aop,则返回的是A)

0

那么earlySingletonObjects直接放代理不就得了,原因如下:

因为通过singletonFactories工厂获得对象代理比较耗时间,但是后续不一定能会用到,1%的概率用到,所以这里没必要生成代理,但是第二次访问了,则已经很耗时间的创建出代理了,所以直接放到earlySingletonObjects备用。比如A依赖B,B依赖C,C依赖B,A、C会放到singletonFactories中,但是不会被用到。

构造方法注入为什么无法解决循环依赖

spring实例化bean成办成品的时候依赖构造方法,所以...

Spring事务

https://www.cnblogs.com/mseddl/p/11577846.html

事务四个特性

原子性:不可分割

一致性:事务执行前后数据完整性保持一致,不能出现部分成功、部分失败

隔离性:一个事务执行,不应该受其他事务影响

持久性:一个事务执行结束后,都要持久化存储

spring事务配置方式(两种)

编程式:直接statement 执行sql,commit这样;代码级别,不推荐

声明式:xml配置或者注解,方法级别,推荐。

spring事务传播机制 7种

@Transactional(propagation=Propagation.REQUIRED)

解决事务嵌套的时候怎么处理,是合并还是挂起?

1. propagation_requested: 如果当前事务在一个事务中,则合并;如果上面没有事务,则新建一个事务执行;

2. propagation_reques_new:如果当前事务在一个事务中,则外事务挂起,等当前事务执行结束之后再接着执行外事务;如果上面没有事务,则新建一个事务执行;

3. propagetion_support:如果当前事务有外事务,合并;如果没有,非事务方式执行;

4. propagation_not_support:如果当前事务有外事务,挂起,非事务执行,结束后执行外事务,并且如果当前执行失败也不会影响外事务;

5. propagation_never: 如果当前事务有外事务,抛出异常;

6. propagation_mandatory: 如果当前事务无外事务,抛出异常;

7. propagation_nested: 可以保存状态保存点,如果失败各自回滚各自的,但是如果子事务处理不了异常,也会引起全部回滚

常引发安全性问题

1. 脏读:一个事务读了另一个事务未提交的数据;

2. 不可重复读:一个事务读了另一个事务update的数据,导致前后读的数据不一致;

3. 幻读:一个事务读了另一个事务insert的数据,导致前后读区数据不一致。

事务隔离级别 5种

@Transactional(isolation = Isolation.READ_UNCOMMITTED)

isolation_default: 采用数据库设置的默认级别

isolation_read_uncommit: 未提交读,当前事务可以读其他未提交事务的数据,脏读、不可重复读、幻读都会发生;

isolation_read_commit: 提交读,当前事务只能提交其他事务已提交的数据,脏读可避免;oracle默认

isolation_repeatable_read: 可重复读,当前事务多次读相同字段值是一样,但幻读不可避免;mysql默认

isolation_serialization: 序列化,最慢,但是都可以避免,因为当前事务涉及到的数据都会锁住;

事务实现原理

aop动态代理,spring在加载类、方法时,针对@Transactional注解进行处理,前后增加配置信息,生成相应的代理,达到如果成功则commit,失败rollback。数据库底层的回滚通过binlog、redo log实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值