Spring系列面试

Spring
Spring 有application和bootstrap,其中application是自动化配置的文件,而bootstrap具有不能被覆盖
一.Spring
    1.原理:它是一个全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层。但是 Spring 仍然可以和其他的框架无缝整合。
    2.特点:轻量级 ,控制反转,面向切面,容器,框架集合
    3.常用模块:核心容器,Spring上下文,Spring AOP,Spring DAO,Spring ORM,Spring web,Spring MVC;
二.IOC
    1.原理:Spring 通过一个配置文件描述 Bean 及 Bean 之间的依赖关系,利用 Java 语言的反射功能实例化 Bean 并建立 Bean 之间的依赖关系。 Spring 的 IoC 容器在完成这些底层工作的基础上,还提供了 Bean 实例缓存、生命周期管理、 Bean 实例代理、事件发布、资源装载等高级服务。其中 Bean 缓存池为 HashMap 实现
    控制反转就是把创建和管理 bean 的过程转移给了第三方;容器负责创建、配置和管理 bean,也就是它管理着 bean 的生命,控制着 bean 的依赖注入
    BeanFactory 简单粗暴,可以理解为 HashMap:
    Key - bean name
    Value - bean object
    IoC 是设计思想,DI 是具体的实现方式;
    IoC 是理论,DI 是实践;
 
    2.IOC 容器实现
        (1)BeanFactory-框架基础设施 :BeanFactory 是Spring框架的基础设施,面向Spring本身;ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合我们都直接使用 ApplicationContext 而非底层的 BeanFactory。
        (2)BeanDefinitionRegistry注册表 接口提供了向容器手工注册 BeanDefinition 对象的方法。
        (3)    BeanFactory 顶层接口:位于类结构树的顶端 ,它最主要的方法就是 getBean(String beanName),该方法从容器中返回特定名称的 Bean,BeanFactory 的功能通过其他的接口得到不断扩展;
        (4)ListableBeanFactory 该接口定义了访问容器中 Bean 基本信息的若干方法,如查看 Bean 的个数、获取某一类型 Bean 的配置名、查看容器中是否包括某一 Bean 等方法;
        (5)HierarchicalBeanFactory父子级联 :父子级联 IoC 容器的接口,子容器可以通过接口方法访问父容器; 通过HierarchicalBeanFactory 接口,Spring的IoC容器可以建立父子  
        的容器体系,子容器可以访问父容器中的 Bean,但父容器不能访问子容器的 Bean。Spring 使用父子容器实现了很多功能,比如在 Spring MVC 中,展现层 Bean 位于一个子容器中,而业务层和持久层的 Bean 位于父容器中。这样,展现层 Bean 就可以引用业务层和持久层的 Bean,而业务层和持久层的 Bean 则看不到展现层的 Bean。
        (6)ConfigurableBeanFactory 是一个重要的接口,增强了 IoC 容器的可定制性,它定义了设置类装载器、属性编辑器、容器初始化后置处理器等方法;
        (7)AutowireCapableBeanFactory 自动装配:定义了将容器中的 Bean 按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法;
        (8)SingletonBeanRegistry运行期间注册单例Bean:定义了允许在运行期间向容器注册单实例 Bean 的方法;对于单实例( singleton)的 Bean 来说,BeanFactory 会缓存 Bean 实例,所以第二次使用 getBean() 获取 Bean 时将直接从 IoC 容器的缓存中获取 Bean 实例。Spring 在 DefaultSingletonBeanRegistry 类中提供了一个用于缓存单实例 Bean 的缓存器,它是一个用 HashMap 实现的缓存器,单实例的 Bean 以 beanName 为键保存在这个 HashMap 中。
        (9)依赖日志框框:在初始化 BeanFactory 时,必须为其提供一种日志框架,比如使用 Log4J, 即在类路径下提供 Log4J 配置文件,这样启动 Spring 容器才不会报错。
    3.ApplicationContext 面向开发应用
        ApplicationContext 由BeanFactory派生而来,提供了更多面向实际应用的功能 。ApplicationContext 继承了 HierarchicalBeanFactory 和 ListableBeanFactory 接口,在此基础上,还通过多个其他的接口扩展了 BeanFactory 的功能;
            (1)ClassPathXmlApplicationContext:默认从类路径加载配置文件
            (2)FileSystemXmlApplicationContext:默认从文件系统中装载配置文件
            (3)ApplicationEventPublisher:让容器拥有发布应用上下文事件的功能,包括容器启动事件、关闭事件等
            (4)MessageSource:为应用提供 i18n 国际化消息访问的功能;
            (5)ResourcePatternResolver : 可以通过带前缀的 Ant 风格的资源文件路径装载 Spring 的配置文件。
            (6)LifeCycle:提供了 start()和 stop()两个方法,用于控制异步处理过程,传递给容器中所有实现了该接口的 Bean,以达到管理和控制 JMX、任务调度等目的
            (7)ConfigurableApplicationContext:扩展于 ApplicationContext,它新增加了两个主要的方法: refresh()和 close(),让 ApplicationContext 具有启动、刷新和关闭应用上下文的能力,在应用上下文关闭的情况下调用 refresh()即可启动应用上下文,在已经启动的状态下,调用 refresh()则清除缓存并重新装载配置信息,而调用 close()则可关闭应用上下文。
    4.WebApplication 体系架构
        WebApplicationContext 是专门为 Web 应用准备的,它允许从相对于 Web 根目录的路径中装载配置文件完成初始化工作。从 WebApplicationContext 中可以获得 ServletContext 的引用,整个 Web 应用上下文对象将作为属性放置到 ServletContext 中,以便 Web 应用环境可以访问 Spring 应用上下文。
    5.Spring Bean 作用域
        Spring 3 中为 Bean 定义了 5 中作用域,分别为 singleton(单例)、prototype(原型)、 request、session 和 global sessio
        1.singleton:Spring 容器内只存在一个 Bean 实例 单例模式 是系统默认值,该模式在多线程下是不安全的
        2.prototype:每次调用都会创建一个 Bean 也就是每次 getBean()就相当于是 new Bean()的操作,prototype 的作用域需要慎重考虑 因为每次创建和销毁都会造成很大的性能开销 WEB 环境下的作用域:
        3.request:每次 HTTP 请求都会创建一个 Bean
        4.session:HTTP Session 共享一个 Bean 实例
        5.global-session:用于 portlet 容器,因为每个 portlet 有单独的 session,globalsession 提供一个全局性的 http session。
    6.Spring Bean 生命周期
    实例化
        1.    实例化一个 Bean,也就是我们常说的 new。
        IOC 依赖注入
        2.    按照 Spring 上下文对实例化的 Bean 进行配置,也就是 IOC 注入。
        setBeanName 实现
        3.    如果这个 Bean 已经实现了 BeanNameAware 接口,会调用它实现的 setBeanName(String) 方法,此处传递的就是 Spring 配置文件中 Bean 的 id 值
        BeanFactoryAware 实现
        4.    如果这个 Bean 已经实现了 BeanFactoryAware 接口,会调用它实现的 setBeanFactory, setBeanFactory(BeanFactory)传递的是 Spring 工厂自身(可以用这个方式来获取其它 Bean,只需在 Spring 配置文件中配置一个普通的 Bean 就可以)。
        ApplicationContextAware 实现
        5.    如果这个 Bean 已经实现了 ApplicationContextAware 接口,会调用 setApplicationContext(ApplicationContext)方法,传入 Spring 上下文(同样这个方式也可以实现步骤 4 的内容,但比 4 更好,因为 ApplicationContext 是 BeanFactory 的子接口,有更多的实现方法)
        6.    如果这个 Bean 关联了 BeanPostProcessor 接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor 经常被用
        作是 Bean 内容的更改,并且由于这个是在 Bean 初始化结束时调用那个的方法,也可以被应用于内存或缓存技术。
        7.init-method:如果 Bean 在 Spring 配置文件中配置了 init-method 属性会自动调用其配置的初始化方法。
        postProcessAfterInitialization
        8.    如果这个 Bean 关联了 BeanPostProcessor 接口,将会调用 postProcessAfterInitialization(Object obj, String s)方法。
        注:以上工作完成以后就可以应用这个 Bean 了,那这个 Bean 是一个 Singleton 的,所以一般情况下我们调用同一个 id 的 Bean 会是在内容地址相同的实例,当然在 Spring 配置文件中也可以配置非 Singleton。
        Destroy 过期自动清理阶段
        9.    当 Bean 不再需要时,会经过清理阶段,如果 Bean 实现了 DisposableBean 这个接口,会调用那个其实现的 destroy()方法; destroy-method 自配置清理
        10.    最后,如果这个 Bean 的 Spring 配置中配置了 destroy-method 属性,会自动调用其配置的销毁方法。
        11.    bean 标签有两个重要的属性(init-method 和 destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct 和@PreDestroy)。
    Spring 依赖注入四种方式
        构造器注入 XML:<constructor-arg> </constructor-arg>
        setter方法注入 XML:<property></property>
        静态工厂注入 :通过调用静态工厂的方法来获取自己需要的对象,依然通过 spring 注入的形式获取XML:
        实例工厂:实例工厂的意思是获取对象实例的方法不是静态的,所以你需要首先 new 工厂类,再调用普通的实例方法;
    5 种不同方式的自动装配
        Spring 装配包括手动装配和自动装配,手动装配是有基于 xml 装配、构造方法、setter 方法等自动装配有五种自动装配的方式,
        1.    no:默认的方式是不进行自动装配,通过显式设置 ref 属性来进行装配。
        2.    byName:通过参数名 自动装配,Spring容器在配置文件中发现bean的autowire 属性被设置成 byname,之后容器试图匹配、装配和该 bean 的属性具有相同名字的 bean。
        3.    byType:通过参数类型自动装配,Spring 容器在配置文件中发现 bean 的 autowire 属性被设置成byType,之后容器试图匹配、装配和该bean的属性具有相同类型的bean。如果有多个 bean 符合条件,则抛出错误。
        4.    constructor:这个方式类似于 byType, 但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
        5.    autodetect:首先尝试使用constructor 来自动装配,如果无法工作,则使用byType方式。
三:Spring AOP
    原理:
    1."横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,
并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
    2.使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常
    发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
    使用场景
    1.    Authentication 权限
    2.    Caching 缓存
    3.    Context passing 内容传递
    4.    Error handling 错误处理
    5.    Lazy loading 懒加载
    6.    Debugging  调试
    7.    logging, tracing, profiling and monitoring 记录跟踪 优化 校准
    8.    Performance optimization 性能优化
    9.    Persistence  持久化
    10.    Resource pooling 资源池
    11.    Synchronization 同步
    12.    Transactions 事务
    核心概念:
    1、    切面(aspect):类是对物体特征的抽象,切面就是对横切关注点的抽象
    2、    横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点。
    3、    连接点(joinpoint):被拦截到的点,因为 Spring 只支持方法类型的连接点,所以在 Spring 中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。
    4、    切入点(pointcut):对连接点进行拦截的定义
    5、    通知(advice):所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类。
    6、    目标对象:代理的目标对象
    7、    织入(weave):将切面应用到目标对象并导致代理对象创建的过程
    8、引入(introduction):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段。
    代理方式
        Spring 提供了两种方式来生成代理对象: JDKProxy 和 Cglib,具体使用哪种方式生成由 AopProxyFactory 根据 AdvisedSupport 对象的配置来决定。默认的策略是如果目标类是接口,则使用 JDK 动态代理技术,否则使用 Cglib 来生成代理。
        JDK动态接口代理
            1.    JDK 动态代理主要涉及到 java.lang.reflect 包中的两个类:Proxy 和 InvocationHandler。
            InvocationHandler是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编制在一起。Proxy 利用 InvocationHandler 动态创建一个符合某一接口的实例,生成目标类的代理对象。
        CGLib 动态代理
            2.    :CGLib 全称为 Code Generation Library,是一个强大的高性能,高质量的代码生成类库,可以在运行期扩展 Java 类与实现 Java 接口,CGLib 封装了asm,可以再运行期动态生成新的 class。和 JDK 动态代理相比较:JDK 创建代理有一个限制,就是只能为接口创建代理实例,而对于没有通过接口定义业务方法的类,则可以通过 CGLib 创建动态代理。
四:Spring MVC
    (1)原理:Spring的模型-视图-控制器(MVC)框架是围绕一个 DispatcherServlet 来设计的,这个 Servlet 会把请求分发给各个处理器,并支持可配置的处理器映射、视图渲染、本地化、
        springMVC就是spring的一个子模块
    (2)MVC: M-Model 模型(完成业务逻辑:有javaBean构成,service+dao+entity)
            V-View 视图(做界面的展示  jsp,html……)
            C-Controller 控制器(接收请求—>调用模型—>根据结果派发页面)
    时区与主题渲染等,甚至还能支持文件上传
    (2)流程
        1、  用户发送请求至前端控制器DispatcherServlet。
        2、  DispatcherServlet收到请求调用HandlerMapping处理器映射器。
        3、  处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
        4、  DispatcherServlet调用HandlerAdapter处理器适配器。
        5、  HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
        6、  Controller执行完成返回ModelAndView。
        7、  HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
        8、  DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
        9、  ViewReslover解析后返回具体View。
        10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
        11、 DispatcherServlet响应用户。
    (3)组件说明:
        以下组件通常使用框架提供实现:
        DispatcherServlet:作为前端控制器,整个流程控制的中心,控制其它组件执行,统一调度,降低组件之间的耦合性,提高每个组件的扩展性。
        HandlerMapping:通过扩展处理器映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
        HandlAdapter:通过扩展处理器适配器,支持更多类型的处理器。
        ViewResolver:通过扩展视图解析器,支持更多类型的视图解析,例如:jsp、freemarker、pdf、excel等
 
    组件:
            1、前端控制器DispatcherServlet(不需要工程师开发),由框架提供
            作用:接收请求,响应结果,相当于转发器,中央处理器。有了dispatcherServlet减少了其它组件之间的耦合度。
            用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
            2、处理器映射器HandlerMapping(不需要工程师开发),由框架提供
            作用:根据请求的url查找Handler
            HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
            3、处理器适配器HandlerAdapter
            作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler
            通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
            4、处理器Handler(需要工程师开发)
            注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
            Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
            由于Handler涉及到具体的用户业务请求,所以一般情况需要工程师根据业务需求开发Handler。
            5、视图解析器View resolver(不需要工程师开发),由框架提供
            作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)
            View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。
            一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由工程师根据业务需求开发具体的页面。
            6、视图View(需要工程师开发jsp...)
            View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf...)
            核心架构的具体流程步骤如下:
            1、首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
            2、DispatcherServlet——>HandlerMapping, HandlerMapping 将会把请求映射为HandlerExecutionChain 对象(包含一个Handler 处理器(页面控制器)对象、多个HandlerInterceptor 拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
            3、DispatcherServlet——>HandlerAdapter,HandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
            4、HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter 将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView 对象(包含模型数据、逻辑视图名);
            5、ModelAndView的逻辑视图名——> ViewResolver, ViewResolver 将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
            6、View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
            7、返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
    整体流程:
    第一步:用户发起请求到前端控制器(DispatcherServlet)
    第二步:前端控制器请求处理器映射器(HandlerMappering)去查找处理器(Handle):通过xml配置或者注解进行查找
    第三步:找到以后处理器映射器(HandlerMappering)像前端控制器返回执行链(HandlerExecutionChain)
    第四步:前端控制器(DispatcherServlet)调用处理器适配器(HandlerAdapter)去执行处理器(Handler)
    第五步:处理器适配器去执行Handler
    第六步:Handler执行完给处理器适配器返回ModelAndView
    第七步:处理器适配器向前端控制器返回ModelAndView
    第八步:前端控制器请求视图解析器(ViewResolver)去进行视图解析
    第九步:视图解析器像前端控制器返回View
    第十步:前端控制器对视图进行渲染
    第十一步:前端控制器向用户响应结果
四:Spring Boot (核心在于注解)
    @SpringBootApplication
    这是 Spring Boot 最最最核心的注解,用在 Spring Boot 主类上,标识这是一个 Spring Boot 应用,用来开启 Spring Boot 的各项能力。
    其实这个注解就是 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan 这三个注解的组合,也可以用这三个注解来代替 @SpringBootApplication 注解。
    2、@EnableAutoConfiguration
    允许 Spring Boot 自动配置注解,开启这个注解之后,Spring Boot 就能根据当前类路径下的包或者类来配置 Spring Bean。
    如:当前类路径下有 Mybatis 这个 JAR 包,MybatisAutoConfiguration 注解就能根据相关参数来配置 Mybatis 的各个 Spring Bean。
    3、@Configuration
    这是 Spring 3.0 添加的一个注解,用来代替 applicationContext.xml 配置文件,所有这个配置文件里面能做到的事情都可以通过这个注解所在类来进行注册。
    4、@SpringBootConfiguration
    这个注解就是 @Configuration 注解的变体,只是用来修饰是 Spring Boot 配置而已,或者可利于 Spring Boot 后续的扩展。
    5、@ComponentScan
    这是 Spring 3.1 添加的一个注解,用来代替配置文件中的 component-scan 配置,开启组件扫描,即自动扫描包路径下的 @Component 注解进行注册 bean 实例到 context 中。
    6、@Conditional
    这是 Spring 4.0 添加的新注解,用来标识一个 Spring Bean 或者 Configuration 配置文件,当满足指定的条件才开启配置。
    7、@ConditionalOnBean
    组合 @Conditional 注解,当容器中有指定的 Bean 才开启配置。
    8、@ConditionalOnMissingBean
    组合 @Conditional 注解,和 @ConditionalOnBean 注解相反,当容器中没有指定的 Bean 才开启配置。
    9、@ConditionalOnClass
    组合 @Conditional 注解,当容器中有指定的 Class 才开启配置。
    10、@ConditionalOnMissingClass
    组合 @Conditional 注解,和 @ConditionalOnMissingClass 注解相反,当容器中没有指定的 Class 才开启配置。
    11、@ConditionalOnWebApplication
    组合 @Conditional 注解,当前项目类型是 WEB 项目才开启配置。
    12、@ConditionalOnNotWebApplication
    组合 @Conditional 注解,和 @ConditionalOnWebApplication 注解相反,当前项目类型不是 WEB 项目才开启配置。
    13、@ConditionalOnProperty
    组合 @Conditional 注解,当指定的属性有指定的值时才开启配置。
    14、@ConditionalOnExpression
    组合 @Conditional 注解,当 SpEL 表达式为 true 时才开启配置。
    15、@ConditionalOnJava
    组合 @Conditional 注解,当运行的 Java JVM 在指定的版本范围时才开启配置。
    16、@ConditionalOnResource
    组合 @Conditional 注解,当类路径下有指定的资源才开启配置。
    17、@ConditionalOnJndi
    组合 @Conditional 注解,当指定的 JNDI 存在时才开启配置。
    18、@ConditionalOnCloudPlatform
    组合 @Conditional 注解,当指定的云平台激活时才开启配置。
    19、@ConditionalOnSingleCandidate
    组合 @Conditional 注解,当指定的 class 在容器中只有一个 Bean,或者同时有多个但为首选时才开启配置。
    20、@ConfigurationProperties
    用来加载额外的配置(如 .properties 文件),可用在 @Configuration 注解类,或者 @Bean 注解方法上面。
    关于这个注解的用法可以参考Java技术栈《 Spring Boot读取配置的几种方式》这篇文章。
    21、@EnableConfigurationProperties
    一般要配合 @ConfigurationProperties 注解使用,用来开启对 @ConfigurationProperties 注解配置 Bean 的支持。
    22、@AutoConfigureAfter
    用在自动配置类上面,表示该自动配置类需要在另外指定的自动配置类配置完之后。\
    23、@AutoConfigureBefore
    这个和 @AutoConfigureAfter 注解使用相反,表示该自动配置类需要在另外指定的自动配置类配置之前。
    24、@Import
    这是 Spring 3.0 添加的新注解,用来导入一个或者多个 @Configuration 注解修饰的类,这在 Spring Boot 里面应用很多。
    25、@ImportResource
    这是 Spring 3.0 添加的新注解,用来导入一个或者多个 Spring 配置文件,这对 Spring Boot 兼容老项目非常有用,因为有些配置无法通过 Java Config 的形式来配置就只能用这个注解来导入。
五.Spring事务
        1.事务管理:
            事务就是对一系列的数据库操作(比如插入多条数据)进行统一的提交或回滚操作,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作。
            这样可以防止出现脏数据,防止数据库数据出现问题。
        2.事务的4个特性
            1.原子性(Atomic):事务是由一个或多个活动所组成的一个工作单元。原子确保事务中的所有操作全部发生或全部不发生。如果所有的活动都成功了,事务也就成功了。如果任意一个
            活动失败了,整个事务也失败并回滚。
            2.一致性(Consistent):一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态。现实的数据不应该被损坏。
            3.隔离性(Isolated):事务允许多个用户对相同的数据进行操作,每个用户的操作不会与其他用户纠缠在一起。因此,事务应该被彼此隔离,避免发生同步读写相同数据的事情(注意的是,
            隔离性往往涉及到锁定数据库中的行或表)。
            4.持久性(Durable):一旦事务完成,事务的结果应该持久化,这样就能从任何的系统崩溃中恢复过来。这一般会涉及将结果存储到数据库或其他形式的持久化存储中。\
        3.Spring的核心配置文件applicationContext.xml中配置事务
            主要配置三大方面:事务管理器、事务通知和定义事务性切面
                事务管理器:DataSourceTransactionManager
                事务通知:transactionManager
                定义事务性切面:txAdvice
                操作事务的方法一般就三种:开启事务、提交事务、回滚事务。针对这三个方法,JDBC、Hibernate、Mybatis等都有不同的实现方式。因为在不同平台、操作事务的代码各不相同。
                为此,Spring提供了一个接口PlatformTransactionManager,针对不同的操作平台提供不同的实现类。比方说,如果是JDBC和iBatis,实现类是DataSourceTransactionManager,
                如果是Hibernate,实现类是HibernateTransactionManager。不同的实现类就是不同的事务管理器,为了使用事务管理器,你需要将其声明在应用程序上下文中。
                当配置好事务管理器之后,在spring中具体配置事务时,又有两种选择:一种是编码事务(了解),一种是声明式事务。声明式事务是通过事务属性来定义的,具体的说,
                是通过传播行为、隔离级别、只读提示、事务超时及回滚规则来进行定义的。
        4.事务的传播行为指在业务(service)方法之间平行调用时,如何来处理事务的问题
        5.Spring中定义事务七种传播行为的属性:
        分别是REQUIRED、REQUIRES_NEW、SUPPORTS、NOT_SUPPORTED、MANDATORY、NESTED、NEVER。
        6.务中可能会出现的并发:
            脏读、不可重复读、幻读,解决并发问题的方法就是设置隔离级别。在理想情况下,事务之间是完全隔离的,从而可以防止这些问题发生,但是完全隔离会导致性能问题,
            因为它通常会涉及锁定数据库中的记录,侵占性的锁定会阻碍并发性,要求事务互相等待以完成各自的工作。 考虑到完全的隔离会导致性能问题,而且并不是所有的应用程序都需要完全的隔离,所以有时应用程序需要在事务隔离上有一定的灵活性。因此就会有各种隔离级别。
        7.事务中有几种隔离级别呢?
             读未提交(uncommitted)、读已提交(committed)、可重复读(repeatable_read)、串行化(serializable)。
             读未提交(uncommitted):允许读取尚未提交的数据变更。可能会导致脏读、幻读或不可重复读。
             读已提交(committed):允许读取并发事务已经提交的数据。可以阻止脏读、但是幻读或不可重复读仍有可能发生。
             可重复读(repeatable_read):可以阻止脏读和不可重复读,但可能会导致幻读。
             串行化(serializable):完全服从ACID的隔离级别,确保阻止脏读、不可重复读以及幻读。这是最慢的事务隔离级别,因为它通常是通过完全锁定事务相关的数据库表来实现的。
        8.Spring声明式事务配置参考
                事物配置中有哪些属性可以配置?以下只是简单的使用参考
                事务的传播性:
                @Transactional(propagation=Propagation.REQUIRED)
                事务的隔离级别:
                @Transactional(isolation = Isolation.READ_UNCOMMITTED)
                读取未提交数据(会出现脏读, 不可重复读) 基本不使用
                只读:
                @Transactional(readOnly=true)
                该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。
                事务的超时性:
                @Transactional(timeout=30)
                回滚:
                指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)
                指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
 
Spring cloud
    概述:Spring Cloud就是微服务系统架构的一站式解决方案,服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控,使我们能在 Spring Boot 的基础上轻松地实现微服务项目的构建。
    Spring Cloud 的服务发现框架——Eureka
        1.主要在AWS云中用于定位服务,以实现负载均衡和中间层服务器的故障转移。我们称此服务为Eureka服务器。Eureka还带有一个基于Java的客户端组件Eureka Client,它使与服务的交互变得更加容易。客户端还具有一个内置的负载平衡器,可以执行基本的循环负载平衡。在Netflix,更复杂的负载均衡器将Eureka包装起来,以基于流量,资源使用,错误条件等多种因素提供加权负载均衡,以提供出色的弹性。
        2.服务发现:服务提供者:服务消费者:服务中介:服务注册 Register:服务续约(心跳来续约) Renew:获取注册列表信息 Fetch Registries
    负载均衡之 Ribbon
        1.Ribbon 是Netflix公司的一个开源的负载均衡 项目,是一个客户端/进程内负载均衡器,运行在消费者端.指的是,Ribbon是运行在消费者端的负载均衡器,在其内部使用负载均衡算法,
        进行对多个系统的调用
        2.Nginx 和 Ribbon 的对比
            Nignx和Ribbon不同的是,它是一种集中式的负载均衡器。集中式将所有请求都集中起来,然后再进行负载均衡。
        3.负载均衡,不管Nginx还是Ribbon都需要其算法的支持,Nginx使用的是 轮询和加权轮询算法。而在Ribbon中有更多的负载均衡调度算法,其默认是使用的RoundRobinRule轮询策略。
            RoundRobinRule:轮询策略。Ribbon默认采用的策略。若经过一轮轮询没有找到可用的provider,其最多轮询 10 轮。若最终还没有找到,则返回 null。
            RandomRule: 随机策略,从所有可用的 provider 中随机选择一个。
            RetryRule: 重试策略。先按照 RoundRobinRule 策略获取 provider,若获取失败,则在指定的时限内重试。默认的时限为 500 毫秒。
        4.在Ribbon中你还可以自定义负载均衡算法,你只需要实现IRule接口,然后修改配置文件或者自定义Java Config类。
    Open Feign:
        1.Eureka,RestTemplate,Ribbon就可以地进行服务间的调用了,但是使用RestTemplate还是不方便
        2.@FeignClient映射:就像域名和IP地址的映射。
        3.OpenFeign 也是运行在消费者端的,使用 Ribbon 进行负载均衡,所以 OpenFeign 直接内置了 Ribbon。
    Hystrix之熔断和降级:
        1.Hystrix是一个库,可通过添加等待时间容限和容错逻辑来帮助您控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点,停止服务之间的级联故障并提供后备选项来
        实现此目的,所有这些都可以提高系统的整体弹性。
        2.所谓熔断就是服务雪崩的一种有效解决方案。当指定时间窗内的请求失败率达到设定阈值时,系统将通过断路器直接将此请求链路断开。熔断就是指的[Hystrix]中的断路器模式,
        你可以使用简单的@[Hystrix]Command注解来标注某个方法,这样[Hystrix]就会使用断路器来“包装”这个方法,每当调用时间超过指定时间时(默认为1000ms),断路器将会中断对这个方法的调用。
        3.降级是为了更好的用户体验,当一个方法调用异常时,通过执行另一种代码逻辑来给用户友好的回复。对应着[Hystrix]的后备处理模式。你可以通过设置fallbackMethod来给一个方法设置
        备用的代码逻辑。
    微服务网关——Zuul:
        1.ZUUL 是从设备和 web 站点到 Netflix 流应用后端的所有请求的前门。作为边界服务应用,ZUUL 是为了实现动态路由、监视、弹性和安全性而构建的。它还具有根据情况将请求路由到多个 Amazon Auto Scaling Groups(亚马逊自动缩放组,亚马逊的一种云计算方式) 的能力
        2.简单来讲网关是系统唯一对外的入口,介于客户端与服务器端之间,用于对请求进行鉴权、限流、路由、监控等功能。Zuul中最关键的就是路由和过滤器了
        3.Zuul 的路由功能,路由映射
        4.路由策略配置,统一前缀,路由策略配置,服务名屏蔽,路径屏蔽,敏感请求头屏蔽
        5.Zuul 的过滤功能:实现限流,灰度发布,权限控制,令牌桶限流
    Spring Cloud配置管理——Config
        1.Spring Cloud Config为分布式系统中的外部化配置提供服务器和客户端支持。使用Config服务器,可以在中心位置管理所有环境中应用程序的外部属性。
        2.Spring Cloud Config就是能将各个 应用/系统/模块 的配置文件存放到统一的地方然后进行管理(Git 或者 SVN)。
    Spring Cloud Bus
        1.用于将服务和服务实例与分布式消息系统链接在一起的事件总线。在集群中传播状态更改很有用(例如配置更改事件)。
        2.Spring Cloud Bus的作用就是管理和广播分布式系统中的消息,也就是消息引擎系统中的广播模式。当然作为消息总线的Spring Cloud Bus可以做很多事而不仅仅是客户端的配置刷新功能。
posted @ 2021-06-10 16:36  秃头猿  阅读(73)  评论(0编辑  收藏  举报
百度一下吧