前段时间不是离职在家复习嘛,很多小伙伴也想要我的复习路线,以及我自己笔记里面的一些知识点,好了,整整花了我一个月的时间,整整一个月啊,给大家整理出来了。
由于图片太大,所以只是截取了一小部分
这期看下去你会发现很硬核,啥也不说了,看在我熬夜一个月满脸痘痘的份上,你可以点赞了哈哈。
Spring
Spring Core:框架的最基础部分,提供 IoC 容器,对 bean 进行管理。
Spring Context:继承BeanFactory,提供上下文信息,扩展出JNDI、EJB、电子邮件、国际化等功能。
Spring DAO:提供了JDBC的抽象层,还提供了声明性事务管理方法。
Spring ORM:提供了JPA、JDO、Hibernate、MyBatis 等ORM映射层.
Spring AOP:集成了所有AOP功能
Spring Web:提供了基础的 Web 开发的上下文信息,现有的Web框架,如JSF、Tapestry、Structs等,提供了集成
Spring Web MVC:提供了 Web 应用的 Model-View-Controller 全功能实现。
Bean定义5种作用域
singleton(单例)、 prototype(原型、) request session global session
spring ioc初始化流程?
resource定位即寻找用户定义的bean资源,由 ResourceLoader通过统一的接口Resource接口来完成beanDefinition载入BeanDefinitionReader读取、解析Resource定位的资源 成BeanDefinition 载入到ioc中(通过HashMap进行维护BD)BeanDefinition注册即向IOC容器注册这些BeanDefinition, 通过BeanDefinitionRegistery实现
BeanDefinition加载流程?
定义BeanDefinitionReader解析xml的document BeanDefinitionDocumentReader解析document成beanDefinition
DI依赖注入流程? (实例化,处理Bean之间的依赖关系)
过程在Ioc初始化后,依赖注入的过程是用户第一次向IoC容器索要Bean时触发
- 如果设置lazy-init=true,会在第一次getBean的时候才初始化bean, lazy-init=false,会容器启动的时候直接初始化(singleton bean);
- 调用BeanFactory.getBean()生成bean的;
- 生成bean过程运用装饰器模式产生的bean都是beanWrapper(bean的增强);
依赖注入怎么处理bean之间的依赖关系?
其实就是通过在beanDefinition载入时,如果bean有依赖关系,通过占位符来代替,在调用getbean时候,如果遇到占位符,从ioc里获取bean注入到本实例来
Bean的生命周期?
- 实例化Bean: Ioc容器通过获取BeanDefinition对象中的信息进行实例化,实例化对象被包装在BeanWrapper对象中
- 设置对象属性(DI):通过BeanWrapper提供的设置属性的接口完成属性依赖注入;
- 注入Aware接口(BeanFactoryAware, 可以用这个方式来获取其它 Bean,ApplicationContextAware):Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给bean
- BeanPostProcessor:自定义的处理(分前置处理和后置处理)
- InitializingBean和init-method:执行我们自己定义的初始化方法
- 使用
- destroy:bean的销毁
IOC:控制反转:将对象的创建权,由Spring管理. DI(依赖注入):在Spring创建对象的过程中,把对象依赖的属性注入到类中。
Spring的IOC注入方式
构造器注入、 setter方法注入、 注解注入、 接口注入
怎么检测是否存在循环依赖?
Bean在创建的时候可以给该Bean打标,如果递归调用回来发现正在创建中的话,即说明了循环依赖了。
Spring如解决Bean循环依赖问题?
Spring中循环依赖场景有:
- 构造器的循环依赖
- 属性的循环依赖
- singletonObjects:第一级缓存,里面放置的是实例化好的单例对象;
earlySingletonObjects:第二级缓存,里面存放的是提前曝光的单例对象;singletonFactories:第三级缓存,里面存放的是要被实例化的对象的对象工厂
- 创建bean的时候Spring首先从一级缓存singletonObjects中获取。如果获取不到,并且对象正在创建中,就再从二级缓存earlySingletonObjects中获取,如果还是获取不到就从三级缓存singletonFactories中取(Bean调用构造函数进行实例化后,即使属性还未填充,就可以通过三级缓存向外提前暴露依赖的引用值(提前曝光),根据对象引用能定位到堆中的对象,其原理是基于Java的引用传递),取到后从三级缓存移动到了二级缓存完全初始化之后将自己放入到一级缓存中供其他使用,
- 因为加入singletonFactories三级缓存的前提是执行了构造器,所以构造器的循环依赖没法解决。
- 构造器循环依赖解决办法:在构造函数中使用@Lazy注解延迟加载。在注入依赖时,先注入代理对象,当首次使用时再创建对象说明:一种互斥的关系而非层次递进的关系,故称为三个Map而非三级缓存的缘由 完成注入;
Spring 中使用了哪些设计模式?
- 工厂模式: spring中的BeanFactory就是简单工厂模式的体现,根据传入唯一的标识来获得bean对象;
- 单例模式: 提供了全局的访问点BeanFactory;
- 代理模式: AOP功能的原理就使用代理模式(1、JDK动态代理。2、CGLib字节码生成技术代理。)
- 装饰器模式: 依赖注入就需要使用BeanWrapper;
- 观察者模式: spring中Observer模式常用的地方是listener的实现。如ApplicationListener。
- 策略模式: Bean的实例化的时候决定采用何种方式初始化bean实例(反射或者CGLIB动态字节码生成)
AOP 核心概念
1、切面(aspect):类是对物体特征的抽象,切面就是对横切关注点的抽象
2、横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点。
3、连接点(joinpoint):被拦截到的点,因为 Spring 只支持方法类型的连接点,所以在Spring 中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。
4、切入点(pointcut):对连接点进行拦截的定义
5、通知(advice):所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类。
6、目标对象:代理的目标对象
7、织入(weave):将切面应用到目标对象并导致代理对象创建的过程
8、引入(introduction):在不修改代码的前提下,引入可以在运行期为类动态地添加方法或字段。
解释一下AOP
传统oop开发代码逻辑自上而下的,这个过程中会产生一些横切性问题,这些问题与我们主业务逻辑关系不大,会散落在代码的各个地方,造成难以维护,aop思想就是把业务逻辑与横切的问题进行分离,达到解耦的目的,提高代码重用性和开发效率;
AOP 主要应用场景有:
- 记录日志
- 监控性能
- 权限控制
- 事务管理
AOP源码分析
- @EnableAspectJAutoProxy给容器(beanFactory)中注册一个AnnotationAwareAspectJAutoProxyCreator对象;
- AnnotationAwareAspectJAutoProxyCreator对目标对象进行代理对象的创建,对象内部,是封装JDK和CGlib两个技术,实现动态代理对象创建的(创建代理对象过程中,会先创建一个代理工厂,获取到所有的增强器(通知方法),将这些增强器和目标类注入代理工厂,再用代理工厂创建对象);
- 代理对象执行目标方法,得到目标方法的拦截器链,利用拦截器的链式机制,依次进入每一个拦截器进行执行
AOP应用场景
- 日志记录
- 事务管理
- 线程池关闭等
AOP使用哪种动态代理?
- 当bean的是实现中存在接口或者是Proxy的子类,---jdk动态代理;不存在接口,spring会采用CGLIB来生成代理对象;
- JDK 动态代理主要涉及到 java.lang.reflect 包中的两个类:Proxy 和 InvocationHandler。
- Proxy 利用 InvocationHandler(定义横切逻辑) 接口动态创建 目标类的代理对象。
jdk动态代理
- 通过bind方法建立代理与真实对象关系,通过Proxy.newProxyInstance(target)生成代理对象
- 代理对象通过反射invoke方法实现调用真实对象的方法
动态代理与静态代理区别
- 静态代理,程序运行前代理类的.class文件就存在了;
- 动态代理:在程序运行时利用反射动态创建代理对象<复用性,易用性,更加集中都调用invoke>
CGLIB与JDK动态代理区别
- Jdk必须提供接口才能使用;
- C不需要,只要一个非抽象类就能实现动态代理
SpringMVC
springMVC流程:
(1):用户请求发送给DispatcherServlet,DispatcherServlet调用HandlerMapping处理器映射器;
(2):HandlerMapping根据xml或注解找到对应的处理器,生成处理器对象返回给DispatcherServlet;
(3):DispatcherServlet会调用相应的HandlerAdapter;
(4):HandlerAdapter经过适配调用具体的处理器去处理请求,生成ModelAndView返回给DispatcherServlet
(5):DispatcherServlet将ModelAndView传给ViewReslover解析生成View返回给DispatcherServlet;
(6):DispatcherServlet根据View进行渲染视图;
->DispatcherServlet->HandlerMapping->Handler
->DispatcherServlet->HandlerAdapter处理handler->ModelAndView
->DispatcherServlet->ModelAndView->ViewReslover->View
->DispatcherServlet->返回给客户
Mybatis
Mybatis原理
- sqlsessionFactoryBuilder生成sqlsessionFactory(单例)
- 工厂模式生成sqlsession执行sql以及控制事务
- Mybatis通过动态代理使Mapper(sql映射器)接口能运行起来即为接口生成代理对象将sql查询到结果映射成pojo
sqlSessionFactory构建过程
- 解析并读取配置中的xml创建Configuration对象 (单例)
- 使用Configruation类去创建sqlSessionFactory(builder模式)
Mybatis一级缓存与二级缓存
默认情况下一级缓存是开启的,而且是不能关闭的。
- 一级缓存是指 SqlSession 级别的缓存
原理:使用的数据结构是一个 map,如果两次中间出现 commit 操作 (修改、添加、删除),本 sqlsession 中的一级缓存区域全部清空 - 二级缓存是指可以跨 SqlSession 的缓存。是 mapper 级别的缓存;
原理: 是通过 CacheExecutor 实现的。CacheExecutor其实是 Executor 的代理对象
Zookeeper+eureka+springcloud
SpringBoot启动流程
- new springApplication对象,利用spi机制加载applicationContextInitializer,
applicationLister接口实例(META-INF/spring.factories); - 调run方法准备Environment,加载应用上下文(applicationContext),发布事件 很多通过lister实现
- 创建spring容器, refreshContext() ,实现starter自动化配置,spring.factories文件加载, bean实例化
SpringBoot自动配置的原理
- @EnableAutoConfiguration找到META-INF/spring.factories(需要创建的bean在里面)配置文件
- 读取每个starter中的spring.factories文件
Spring Boot 的核心注解
核心注解是@SpringBootApplication 由以下三种组成
- @SpringBootConfiguration:组合了 @Configuration 注解,实现配置- 文件的功能。
- @EnableAutoConfiguration:打开自动配置的功能。
- @ComponentScan:Spring组件扫描。
SpringBoot常用starter都有哪些
spring-boot-starter-web - Web 和 RESTful 应用程序;
spring-boot-starter-test - 单元测试和集成测试;
spring-boot-starter-jdbc - 传统的 JDBC;
spring-boot-starter-security - 使用 SpringSecurity 进行身份验证和授权;
spring-boot-starter-data-jpa - 带有 Hibernate 的 Spring Data JPA;
spring-boot-starter-data-rest - 使用 Spring Data REST 公布简单的 REST 服务
Spring Boot 的核心配置文件
(1):Application.yml 一般用来定义单个应用级别的,如果搭配 spring-cloud-config 使用
(2).Bootstrap.yml(先加载) 系统级别的一些参数配置,这些参数一般是不变的
Zuul与Gateway区别
(1):zuul则是netflix公司的项目集成在spring-cloud中使用而已, Gateway是spring-cloud的
一个子项目;
(2):zuul不提供异步支持流控等均由hystrix支持, gateway提供了异步支持,提供了抽象负载均衡,提供了抽象流控; 理论上gateway则更适合于提高系统吞吐量(但不一定能有更好的性能),最终性能还需要通过严密的压测来决定
(3):两者底层实现都是servlet,但是gateway多嵌套了一层webflux框架
(4): zuul可用至其他微服务框架中,内部没有实现限流、负载均衡;gateway只能用在springcloud中;
Zuul原理分析
(1):请求给zuulservlet处理(HttpServlet子类) zuulservlet中有一个zuulRunner对象,该对象中初始化了RequestContext(存储请求的数据),RequestContext被所有的zuulfilter共享;
(2): zuulRunner中有 FilterProcessor(zuulfilter的管理器),其从filterloader 中获取zuulfilter;
(3):有了这些filter之后, zuulservelet执行的Pre-> route-> post 类型的过滤器,如果在执行这些过滤器有错误的时候则会执行error类型的过滤器,执行完后把结果返回给客户端.
Gateway原理分析
(1):请求到达DispatcherHandler, DispatchHandler在IOC容器初始化时会在容器中实例化HandlerMapping接口
(2):用handlerMapping根据请求URL匹配到对应的Route,然后有对应的filter做对应的请求转发最终response返回去
Zookeeper 工作原理(待查)
Zookeeper 的核心是原子广播,这个机制保证了各个 server 之间的同步。实现这个机制的协议叫做 Zab 协议。Zab 协议有两种模式,它们分别是恢复模式和广播模式。
zoo与eur区别
- zookeeper保证cp(一致性)
- eureka保证ap(可用性)
- zoo在选举期间注册服务瘫痪,期间不可用
- eur各个节点平等关系,只要有一台就可保证服务可用,而查询到的数据可能不是最新的,可以很好应对网络故障导致部分节点失联情况
- zoo有leader和follower角色,eur各个节点平等
- zoo采用半数存活原则(避免脑裂),eur采用自我保护机制来解决分区问题
- eur本质是个工程,zoo只是一个进程ZooKeeper基于CP,不保证高可用,如果zookeeper正在选主,或者Zookeeper集群中半数以上机器不可用,那么将无法获得数据。Eureka基于AP,能保证高可用,即使所有机器都挂了,也能拿到本地缓存的数据。作为注册中心,其实配置是不经常变动的,只有发版(发布新的版本)和机器出故障时会变。对于不经常变动的配置来说,CP是不合适的,而AP在遇到问题时可以用牺牲一致性来保证可用性,既返回旧数据,缓存数据。所以理论上Eureka是更适合做注册中心。而现实环境中大部分项目可能会使用ZooKeeper,那是因为集群不够大,并且基本不会遇到用做注册中心的机器一半以上都挂了的情况。所以实际上也没什么大问题。
Hystrix原理(待查)
通过维护一个自己的线程池,当线程池达到阈值的时候,就启动服务降级,返回fallback默认值
为什么需要hystrix熔断
防止雪崩,及时释放资源,防止系统发生更多的额级联故障,需要对故障和延迟进行隔离,防止单个依赖关系的失败影响整个应用程序;
微服务优缺点
- 每个服务高内聚,松耦合,面向接口编程;
- 服务间通信成本,数据一致性,多服务运维难度增加,http传输效率不如rpc
eureka自我保护机制
- eur不移除长时间没收到心跳而应该过期的服务
- 仍然接受新服务注册和查询请求,但是不会同步到其它节点(高可用)
- 当网络稳定后,当前实例新注册信息会同步到其它节点(最终一致性)
MQ对比
ActiveMQ:Apache出品,最早使用的消息队列产品,时间比较长了,最近版本更新比较缓慢。
RabbitMQ:erlang语言开发,支持很多的协议,非常重量级,更适合于企业级的开发。性能较好,但是不利于做二次开发和维护。
RocketMQ:阿里开源的消息中间件,纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点,分布式事务。
ZeroMQ:号称最快的消息队列系统,尤其针对大吞吐量的需求场景,采用 C 语言实现。消息队列的选型需要根据具体应用需求而定,ZeroMQ 小而美,RabbitMQ 大而稳,Kakfa 和 RocketMQ 快而强劲
由于文章过长
下面是我整理的一些学习笔记资料,已整理成文档,需要获取的小伙伴可以直接转发+关注后私信(学习)即可获取哦!