Spring

作者: 小丸子的呆地 | 来源:发表于2021-11-02 14:39 被阅读0次

    什么是spring

    spring是一个轻量级的容器框架,目的是简化企业应用开发,核心有两大功能IOC和AOP,通过IOC可以帮助我们管理项目中对象依赖,通过AOP可以帮助我们动态增强应用的功能性。spring对现有主流框架都有集成的支持,让我们我们很容易的在应用中使用其他框架的功能。

    什么是IOC

    控制反转,IOC其实就是对象的生命周期交给spring管理,spring本身是一个bean容器,帮助我们创建并且缓存对象引用,当我们需要某个对象的时候,由spring进行创建;过程中需要DI依赖注入,将我们需要的对象引用赋值给变量,降低组件之间耦合性;对象与对象之间复杂的引用关系也由spring帮我们管理;第三方功能需要的对象也由spring帮我们管理,我们只需要拿来即用就好。

    什么是AOP

    面向切面,切面指不同功能不同业务中相同的一部分逻辑,比如鉴权、日志、事务等模块,aop可以帮助我们轻易的在每个业务中进行这些通用功能的拓展,让我们只专注于实现业务功能即可。
    当你需要在很多方法或接口上增加相同或相似的逻辑时,可以考虑使用AOP。
    AOP有两种实现方式Spring的实现和AspectJ的实现,AspectJ是早期的aop实现,定义了一些标准的枚举,这些枚举spring也在使用,AspectJ的实现方式是使用静态代理增强,在代码编译期间将切面逻辑织入对象;spring是通过动态代理,JDK或者CGlib,在对象创建期间。

    AOP中的概念

    连接点(Join point) 被切入的执行中的方法
    切点(pointcut) 定义的一组被切入的方法
    通知(advice) 在连接点上执行的方法包括Around、Before、After、After returning、After throwing
    切面(aspect) 被提取的公共模块 切面就是一个pointcut + 一组advice
    目标对象(target) 包含连接点的对象
    织入(Weaving) 通过代理等方法,在target的join point中执行advice

    AOP实现的方式

    spring实现的AOP,动态代理,jdk面向接口、cglib子类继承,对象创建期间、getBean

    AspectJ实现的AOP,静态代理增强,代码编译期间将切面逻辑织入对象

    什么是spingmvc

    springmvc是spring提供的web应用框架,采用mvc模式modile-view-controller,springmvc本身是spring拓展出来的一个模块,spring对他提供很好的继承支持,通过@Controller和@RequestMapping我们可以很简单的创建一个web接口,核心dispatcherservlet拦截所有请求,根据uri找到对应的handler方法并执行,返回对应视图数据。

    springmvc组件

    • Handler Handler包装了具体的业务逻辑,一个RequestMapping、servlet可以看做一个handler
    • HandlerMapping 用来查找Hanlder,每个请求都由对应的handler进行处理,reqeust找到HandlerExecutionChain,HandlerExecutionChain包含了一个Handler和一组Interceptors
    • HandlerAdapter Handler适配器,用来适配项目中老的servlet候着controller,适配器模式,
    • HandlerExceptionResolver 全局异常解析
    • ViewResolver 视图解析器,根据handler返回的ModleAndView找到对应的页面进行渲染,可以是jsp、html或者直接输出
    • MultipartResolver 处理上传文件的请求,普通的request包装成MultipartHttpServletRequest,后者可以直接调用getFile方法获取File

    springmvc运行原理

    springmvc启动的时候会创建自己的上下文applicationcontext对象,将所有controller信息载入上下文,一个reqeustmapping就是一个contoller

    1. 客户端请求提交到DispatcherServlet
    2. 由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller
    3. DispatcherServlet将请求提交到Controller
    4. Controller调用业务逻辑处理后,返回ModelAndView
    5. DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图
    6. 视图负责将结果显示到客户端

    springmvc中拦截器和过滤器的区别

    过滤器是Servlet定义的规范、由servlet容器进行实现,拦截器是由springmvc定义并且实现的
    过滤器在servlet之前调用,拦截器存储在HandlerExecutionChain中,在DispatcherServlet中调用
    过滤器拦截所有请求,拦截器只能拦截定义的handler
    过滤器是责任链模式,拦截器是代理模式(静态代理的)

    什么是springboot

    本质上springboot还是spring,在spirng的基础上做了一些更方便我们搭建项目的功能,让我们在编码、配置、部署、监控等方面变的更简单了。
    基于约定大于配置的自动装配,我们减少了很多配置项,starter帮助我们更简单的管理依赖,内置servlet容器,让我们更快的启动部署一个应用。

    什么是springcloud

    springcloud是spring提出的一套关于微服务架构的组件,包含网关、注册中心、配置中心、RPC、熔断降级、负载均衡、mq、分布式事务等组件

    spring启动过程

    spring的启动过程在AbstractApplicationContext.refresh()方法中执行

    1. prepareRefresh(); 准备上下文刷新 准备一些集合容器
    2. *创建Bean工厂ConfigurableListableBeanFactory
    3. 在使用之前准备一下BeanFactory内部的一些信息 环境参数等
    4. *postProcessBeanFactory 允许子类对BeanFactory做一些后置处理,模板方法
    5. *invokeBeanFactoryPostProcessors 执行Bean工厂后置处理器 会加载BeanDefinition
    6. *registerBeanPostProcessors 注册Bean后置处理器
    7. initMessageSource 初始化消息源
    8. initApplicationEventMulticaster 初始化应用事件广播器
    9. *onRefresh 正在refresh,模板方法,交由子类实现,ServletWebServerApplicationContext会在此处创建web服务器
    10. registerListeners 注册观察者们
    11. *finishBeanFactoryInitialization 根据BeanDefinition实例化所有Bean对象
    12. *finishRefresh 完成刷新 推送event消息,ServletWebServerApplicationContext重写此方法,增加了启动web服务器的逻辑

    beandefinition作用

    beandefinition是Bean定义信息,spring依靠beandefinition进行实例化,在spring容器启动执行invokeBeanFactoryPostProcessors方法时会扫描路径上的所有Bean对象,加载他们的BeanDefinition信息到BeanFactory中,后面会根据这些信息进行Bean的实例化

    springboot启动过程

    • 实例化部分 new SpringApplication
      从spring.factories文件中加载一些ApplicationContextInitializer、ApplicationListener;根据是否引用了某些class推测应用类型;设置一下运行主类
    • 启动部分
      从spring.factories文件中加载SpringApplicationRunListener,这个监听器是springboot启动过程的一些事件推送
      创建ConfigurableApplicationContext上下文 这里会根据推测的应用类型选择创建对应的子类实现
      准备上下文 加载一些环境信息、启动参数信息等
      执行上下文刷新启动spring
      执行结束

    spring中bean加载过程

    实例化Bean 通过反射调用class的构造方法或者通过@Bean设置的实例化方法 此时Bean对象所有属性都是默认值
    为Bean对象进行属性填充 这个阶段会遇到循环依赖问题 注入自定义对象
    为Bean对象填充awera信息 注入上下文对象
    执行BeanPostProcessor前置方法
    执行init方法
    执行BeanPostProcessor后置方法
    将Bean放入BeanFactory

    所有BeanPostProcessor都会在aware之后执行么

    有一些BeanPostProcessor会提前到populateBean阶段执行
    AOP、Autowaire、dubbo的Refrence
    InstantiationAwareBeanPostProcessor
    DestructionAwareBeanPostProcessor
    MergedBeanDefinitionPostProcessor

    spring解决循环依赖

    spring循环依赖问题:spring中交由BeanFactory创建Bean对象,而创建Bean对象过程中有可能依赖了其他对象也需要创建,如果两个对象互相依赖那么创建过程就会进入一个死循环;单缓存无法解决,是因为对象没有创建完毕就放入缓存是不安全的;双缓存可以解决,但是对于aop无法处理,spring实现aop是在BeanPostProcessor阶段,如果强行处理就需要把aop提前到Bean实例化阶段,侵入了标准Bean的创建;三级缓存解决aop动态代理问题
    解决方法:
    A对象实例化之后创建一个ObjectFactory放入三级缓存,ObjectFactory是一段lambda表达式,执行了获取A对象最终引用的代码,过程中执行一些BeanPostProcessor处理包括AOP;
    A对象属性填充阶段加载B对象,实例化B对象之后也放入三级缓存,进入B的属性填充,B的属性填充阶段需要加载A对象,从三级缓存取出对象引用放入二级缓存,并执行属性填充;
    B属性填充等一些列代码执行完毕后,将B对象的从三级缓存取出放入一级缓存;
    A对象拿到B的引用,进行属性填充完毕,从二级缓存出去放入一级缓存

    springmvc父子容器

    springmvc启动的时候,加载DispatcherServlet的时候会再创建一个ApplictionContext,并将Spring已经创建的向下文设置为父级,形成父子容器
    父子容器的存在主要是为了划分边界,service层我们使用spring框架,对象功能由spring帮我们管理,而在web层可能存在多实现,比如springmvc struts2,父子容器可以帮助我们很容易的替换web层,只需要将spring-servlet.xml替换成Struts的配置文件struts.xml,service层都不用动。
    控制扫描路径,来规避父子容器扫描的Bean对象
    SpringBoot中使用的是同一个容器,将DispatcherServlet作为一个Bean对象交由Spring启动了,以前是交由tomcat启动。

    springmvc常用注解

    @Controller 标记是一个contoller
    @RequestMapping 标记资源路径
    @RequestParam 标记参数名称,必填
    @RequestAttribute 标记属性名称,必填
    @RequestBody 标记参数是Json体
    @ResponseBody 标记返回时Json体
    @RestController 标记controller内部全是json方法
    @WebFilter 过滤器
    @CrossOrigin 标记请求与

    spring加载bean的几种方式

    @Component
    @Configuration
    <bean/>
    @Bean
    <import/>
    @Import
    ImportSelector接口
    ImportBeanDefinitionRegistrar接口

    springboot自动装配原理

    springboot自动为我们创建一些Bean对象,基于约定大于配置的原则,按照默认值去创建。
    @SpringBootApplication修饰了启动类,@SpringBootApplication包含@EnableAutoConfiguration
    @EnableAutoConfiguration包含@Import(AutoConfigurationImportSelector.class)
    所有需要自动装配的类是依靠AutoConfigurationImportSelector,从spring.factories文件中加载所有配置为EnableAutoConfiguration的类
    装配时机是在启动时,context.refresh()中,执行BeanFacotoryPostProcessor阶段,通过ConfigurationClassPostProcessor加载

    springboot内嵌tomcat原理

    1. SpringApplication在实例化阶段会根据路径上引用的一些class推测当前应用的类型,如果存在Servlet或者ConfigurableWebApplicationContext会被推测为是一个web服务器;
    2. SpringApplication.run阶段创建上下文时,会根据上面推测的应用类型创建具体的上下文,这里会创建AnnotationConfigServletWebServerApplicationContext
    3. 这个context在refresh阶段的onRefresh中会创建webServer,默认是tomcat,加载的ServletWebServerFactory默认是tomcat的,根据是否引用了内置tomcat其他的还有jetty、Undertow
      TomcatServletWebServerFactory是通过ServletWebServerFactoryAutoConfiguration自动装配的,条件是路径上有Tomcat、Servlet
    4. 在refresh阶段的finishRefresh中会启动webServer

    spring和springboot中提供了哪些扩展点

    BeanFactoryPostProcessor Bean工厂后置处理器 可以通过ApplicationContextInitializer加载,或者只要在refresh方法之前通过listener加载
    BeanPostProcessor Bean后置处理器
    ApplicationRunListener 广播springboot启动事件
    ApplicationListener 广播spring启动事件

    ApplicationContextInitializer在什么时机执行

    SpringApplication.run.prepareContext;

    springboot的starter原理

    管理依赖,省去了以前引入一大堆依赖,还要梳理版本,弄不好就会冲突,
    自动装配组件,省去了一大堆配置
    统一配置文件,将所有配置统一到spring的配置文件中,便于管理

    手写starter

    一般分为两个包 一个starter包负责引入依赖,一个autoconfiguration包负责自动装配组件
    starter包不需要任何代码,只引入依赖
    autoconfiguration包定义配置类,定义组件Bean,自动装配
    配置文件类:使用@ConfigurationProperties(prefix = "demo")修饰的Java类,属性名就是配置名
    自动配置类:@EnableConfigurationProperties(DemoProperties.class)修饰的Java类,会自动读取spring配置文件中对应配置信息
    定义组件:完成核心业务,并用@Bean等方式定义为一个Bean对象
    自动装配:在META-INF目录下添加spring.factories,并配置org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxx.DemoAutoConfiguration

    BeanFactory和ApplicationContext

    BeanFactory是bean工厂,ApplicationContext是应用上下文
    ApplicationContext实现了BeanFactory通过门面模式支持了BeanFactory中的方法,内部引用了一个DefaultListabledBeanFactory
    ApplicationContext还负责整个应用的生命周期,BeanFactory只管Bean对象

    BeanFactory和FactoryBean

    BeanFactory是bean工厂,简单工厂模式;
    FactoryBean是一个Bean,工厂方法模式,getBean方法中对其特殊处理,如果是FactoryBean实现类并且非急切加载的话,会后置处理,当获取FactoryBean时会自动调用getOBject方法,如果需要FactoryBean对象,需要getBean("&"+name),用于懒加载对象,或加载复杂对象实现,比如

    spring中的设计模式

    Listener 观察者模式
    HandlerAdapter 适配器模式
    AOP 代理模式
    ApplicationContext 门面模式
    AbstractApplicationContext.refresh() 模板方法
    BeanFactory 简单工厂
    FactoryBean和ObjectBean 工厂方法
    Waraper 装饰模式

    springcloud有哪些组件

    网关 配置中心 注册中心 服务调用RPC 负载均衡 熔断降级 限流 路由 分布式消息 分布式事务

    spring中的事务

    基于AOP + Threadlocal实现

    spring中的事务传播

    required 如果存在就加入,如果没有就创建
    supports 如果存在就加入,如果没有就非事务执行
    not_supports 如果存在就挂起,非事务执行
    required_new 如果存在就挂起,开启一个新事物执行
    mandatory 如果不存在事务,抛异常
    never 如果存在事务,抛异常
    nested 嵌套事物,子事务不影响父,父回滚,子回滚

    spring中事务失效的场景

    私有方法、final方法、多线程调用、非spring管理对象、直接调用、吞异常、数据库不支持事务、

    @Resouce和@Autowire的区别

    resouce getBeanByName J2ee注解
    autowire getBeanByType spring注解 配合@Qualifier根据name加载;可以装配多个实例到集合或者map

    相关文章

      网友评论

          本文标题:Spring

          本文链接:https://www.haomeiwen.com/subject/kyzkgltx.html