❤进大厂必刷送分题❤ | Spring精通吗?

2021-08-16 16:47:47 浏览数 (1)

文章目录

    • Spring的IOC和AOP机制
      • IOC(DI)
      • AOP
    • Spring AOP 和 AspectJ AOP 有什么区别?
    • Spring中Bean的作用域有哪些
    • Spring中单例Bean的线程安全问题了解吗
    • @Component 和 @Bean 的区别是什么?
    • Spring中Bean的生命周期
    • SpringMVC的执行流程
    • Spring框架中用到了哪些设计模式
    • @Transactional(rollbackFor = Exception.class)注解了解吗?
    • BeanFactory和ApplicationContext有什么区别?
    • 什么是Bean装配
    • Spring自动装配Bean有哪些方式
    • Spring实现事务的原理
    • Spring 管理事务的方式有几种?
    • Spring 事务中的隔离级别有哪几种?
    • Spring的循环依赖
    • Spring事务什么时候会失效
    • SpringMVC的工作流程
    • SpringBoot自动装配原理
    • 如何理解 Spring Boot 中的 Starter

Spring的IOC和AOP机制

    我们在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入和AOP,面向切面编程,这两个是Spring的灵魂

主要用到的设计模式有工厂设计模式和代理设计模式

    (1)IOC就是典型的工厂模式,通过sessionfactory注入实例

    (2)AOP就是典型的代理模式的体现

    代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息,过滤消息,把消息转发给委托类以及事后处理消息等,代理类与委托类之间通常会存在关联关系,一个代理类对象与一个委托类的对象关联,代理类的对象本身并不是真正实现服务,而是通过调用委托类的相关方法,来提供特定的服务

spring的IOC容器是spring的核心,spring AOP是spring框架的重要组成部分

IOC(DI)

    在传统的程序设计中,当调用者需要被调用者的协助时,通常由调用者来1创建被调用者的实例,但在spring里创建被调用者到的工作不再由调用者来完成,因此被称为控制反转(IOC)

    IOC(Inverse of Control:控制反转)是一种设计思想,就是 将原本在程序中手动创建对象的控制权,交由Spring框架来管理。 IOC在其他语言中也有应用,并非 Spring 特有。 IOC容器是 Spring 用来实现 IOC的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。

IOC容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。

    IOC利用了工厂模式,将对象交给容器管理,你只需要再spring配置文件中配置相应的bean,以及设置相关的属性,让spring容器来生成类的实例对象以及管理对象,在spring容器启动的时候,spring会把你在配置文件中配置的bean都初始化好,然后在你需要调用的时候,就把它以及初始化好的那些bean分配给你需要调用的那些bean的类(假设这个类名为A),分配的方式是调用A的setter方法来注入,而不需要你再A里面new这些bean了

AOP

    AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码降低模块间的耦合度,并有利于未来的可拓展性和可维护性

​ 实现AOP的技术,主要分为两大类:

​ (1)采用动态代理技术,利用截取消息的方法,对该对象进行装饰,以取代原有对象行为的执行。

​ (2)采用静态织入的方式,引入特定的语法创建"方面",从而使得编译器在编译期间织入有关"方面"的代码。

​ AOP实现的关键在于代理模式,AOP的代理主要分为静态代理和动态代理。静态代理的代表为AspectJ,动态代理的代表则以SpringAOP为代表

​ (1)AspectJ是静态代理的增加,所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,她会在编译阶段将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。

​ (2)Spring AOP使用的是动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法

AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB的动态代理

Spring AOP 和 AspectJ AOP 有什么区别?

  1. Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
  2. AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单。
  3. 如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比Spring AOP 快很多。

Spring中Bean的作用域有哪些

  1. singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
  2. prototype : 每次请求都会创建一个新的 bean 实例。
  3. request : 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
  4. session : 每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效。
  5. application:bean被定义为在ServletContext的生命周期中复用的一个单例对象。
  6. websocket:bean被定义为在websocket的生命周期中复用的一个单例对象。
  7. blobal-session:全局作用域。

Spring中单例Bean的线程安全问题了解吗

    的确是存在安全问题的。因为,当多个线程操作同一个对象的时候,对这个对象的成员变量的写操作会存在线程安全问题,即如果Bean时有状态的(有状态的意思就是说有数据存储功能),那么需要开发人员来保证线程安全。     一般情况下,我们常用的 Controller、Service、Dao 这些 Bean 是无状态的。无状态的 Bean 不能保存数据,因此是线程安全的。     常用的解决办法有两种:

  1. 在类中定义一个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。
  2. 改变 Bean 的作用域为 prototype:每次请求都会创建一个新的 bean 实例,自然不会存在线程安全问题。

@Component 和 @Bean 的区别是什么?

  1. 作用对象不同:@Component注解作用于类,而@Bean注解作用于方法。
  2. @Component通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中(我们可以使用@Component注解定义扫描的路径从中找出标识了需要装配的类自动装配到Spring的Bean容器中),@Bean注解通常是我们在标有该注解的方法中定义产生这个Bean,@Bean告诉了Spring这是某个类的示例,当我需要用的时候把他给我。
  3. @Bean注解比@Component注解的自定义性更强,而且很多地方我们只能通过@Bean注解来注册Bean。比如当我们引用第三方库中的类需要装配到 Spring 容器时,则只能通过@Bean来实现。

Spring中Bean的生命周期

  • Bean 容器找到配置文件中 Spring Bean 的定义。
  • 如果有多个构造方法,则要推断需要执行哪一个构造方法。
  • 确定好构造方法后,进行实例化得到一个对象。
  • 对加入了@Autowired注解的对象的属性进行填充。
  • 回调Aware方法对Bean容器进行一系列的初始化操作,比如BeanNameAware、BeanFactoryAware。
  • 调用BeanPostProcessor的初始化的前方法。
  • 调用初始化方法。
  • 调用BeanPostProcessor的初始化的后方法,在这里会进行AOP。
  • 如果当前创建的Bean是单例的,那么会把Bean放入单例池。
  • 程序员使用Bean。
  • Spring容器关闭时调用DisposableBean中的destory()方法。

SpringMVC的执行流程

  1. 用户发送请求至前端控制器DispatcherServlet
  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器。
  3. 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet
  4. DispatcherServlet调用HandlerAdapter处理器适配器。
  5. HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
  6. Controller执行完成返回ModelAndView
  7. HandlerAdapterController执行结果ModelAndView返回给DispatcherServlet
  8. DispatcherServletModelAndView传给ViewReslover视图解析器。
  9. ViewReslover解析后返回具体View
  10. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
  11. DispatcherServlet响应用户。

Spring框架中用到了哪些设计模式

  • 工厂设计模式 : Spring使用工厂模式通过 BeanFactoryApplicationContext 创建 bean 对象。
  • 代理设计模式 :Spring AOP 功能的实现。
  • 单例设计模式 :Spring 中的 Bean 默认都是单例的。
  • 模板方法模式 : Spring 中 jdbcTemplatehibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。
  • 包装器设计模式 :我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
  • 观察者模式:Spring 事件驱动模型就是观察者模式很经典的一个应用,Spring中Observer(观察者模式)最常用的地方就是Listener监听器。
  • 适配器模式 :Spring定义了一个适配器接口,使得每一种Controller都有一种对应的适配器实现类,让适配器代替Controller执行相应的方法,这样在拓展Controller时,只需增加一个适配器类就完成了SpringMVC的拓展了。
  • 装饰器模式:动态地给一个对象添加一些额外的职责,Spring中用到的包装器模式在类名上有两种表现:一种时类名中含有Wrapper,另一种时类名中含有Decorator。
  • 策略模式:Spring框架的资源访问Resource接口,该接口提供了更强的资源访问能力。Spring框架本身大量使用了Resource接口来访问底层资源。

@Transactional(rollbackFor = Exception.class)注解了解吗?

    Exception分为运行时异常RuntimeException和非运行时异常。事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性。

    当@Transactional注解作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。如果类或者方法加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。

    在@Transactional注解中如果不配置rollbackFor属性,那么事务只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事务在遇到非运行时异常时也回滚。

BeanFactory和ApplicationContext有什么区别?

BeanFactoryApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。

  1. BeanFactory是Spring中最底层的接口,包含了各种Bean的定义、读取配置文件、管理Bean的加载、Bean的实例化、控制Bean的生命周期,维护Bean之间的依赖。ApplicationContext接口作为BeanFactory的派生,除了具有BeanFactory所具有的功能外,他还具有其他功能:支持国际化、统一资源文件的访问方式、同时加载多个配置文件。
  2. BeanFactory时采用延迟加载的形式来注入Bean的,即只有在某个Bean时(调用getBean()),才对该Bean进行加载实例化, 这样我们就不能发现一些spring存在的配置问题,如果Bean的某一个属性没有注入,BeanFactory加载后直到第一次调用getBean方法才会抛出异常。
  3. ApplicationContext它是在容器启动的时候,一次性创建了所有的Bean,这样在容器启动的时候,我们就可以发现Spring中存在的配置错误,这样有利于检查依赖属性是否注入。ApplicationContext启动后会预载入所有的单实例Bean,通过预载入单实例的Bean,确保你在需要的时候,可以不需要等待,直接取用。
  4. 相对于BeanFactory,ApplicationContext唯一的不足时占用内存,当应用程序配置的Bean较多的时候,程序启动会比较慢。
  5. BeanFacotry通常是以编程的方式被创建的,而ApplicationContext还可以以声明的方式来创建,比如说ContextLoader。
  6. BeanFactory和ApplicationContex都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但是两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。

什么是Bean装配

    装配是指在Spring容器中把bean组装在一起。     在Spring框架中,在配置文件设定bean依赖关系是一个很好的机制,Spring容器可以自动装配互相合作的bean,这样意味着容器不需要配置就能够通过Bean工厂发自动处理Bean之间的协作。

Spring自动装配Bean有哪些方式

    在Spring的配置文件中共有五种自动装配:

  1. no:默认的方式是不通过自动装配,通过手动ref属性来进行装配Bean。
  2. byName:通过Bean的名称进行自动装配,如果一个Bean的property与另一个Bean的name相同,就会进行自动装配。
  3. byType:通过参数的数据类型进行自动装配。
  4. constructor:通过构造函数进行自动装配,并且构造函数的参数也是通过byType进行装配的。
  5. autodetect:自动探测,如果有构造方法就是使用construct的方式自动装配,否则使用byType的方式自动装配。

Spring实现事务的原理

在使用Spring框架时,可以有两种使用事务的方式,一种是编程式事务,另一种是声明式事务,@Transaction注解就是声明式事务。

首先事务的概念是在数据库层面的,Spring只是基于数据库中的事务进行了拓展,以及提供了一些能让程序员更既方便操作事务的方式。比如我们可以在某个方法上增加@Transaction注解,开启事务,这个方法中的所有sql都会在一个事务中执行,统一成功或者统一失败。

在一个方法上加了@Transaction注解后,Spring会基于这个类生成一个代理对象,会将这个这个代理对象作为bean,在当使用这个代理对象的方法时,如果中国方法上存在@Transaction注解,那么代理逻辑会把事务的自动提交设置为false,然后再去执行原本的业务逻辑方法,如果执行的业务逻辑没有出现异常,那么代理逻辑中就会将事务进行提交,如果执行的业务逻辑方法出现了异常,那么会将事务进行回滚。

针对哪些异常回滚事务是可以配置的,可以利用@Transaction注解中的rollbackFor属性进行配置,默认会对RuntimeException和Error进行回滚。

Spring 管理事务的方式有几种?

  1. 编程式事务:在代码中硬编码。(不推荐使用)
  2. 声明式事务:在配置文件中配置。(推荐)
    • 基于XML的声明式事务
    • 基于注解的声明式事务

Spring 事务中的隔离级别有哪几种?

TransactionDefinition 接口中定义了五个表示隔离级别的常量:

  1. TransactionDefinition.ISOLATION_DEFAULT:使用后端数据库默认的隔离级别,MySQL采用REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别。
  2. TransactionDefinition.ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取未提交的数据,可能会导致脏读、幻读、不可重复读。
  3. TransactionDefinition.ISOLATION_READ_COMMITTED:允许去读并发事务已提交的数据,可以阻止脏读,但是幻读或者不可重复读可能发生。
  4. TransactionDefinition.ISOLATION_REPEATABLE_READ:对同一个字段多次读取结果都是一致的,除非数据时被本身事务自己所修改,可以阻止脏读和不可重复读,但是幻读仍然可能发生。
  5. TransactionDefinition.ISOLATION_SERIALIZABLE:最高的隔离级别1,完全服从ACID的隔离级别,所有事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。

Spring的循环依赖

  1. A创建过程中需要B,于是A将自己放到三级缓存中,去实例化B。
  2. B实例化的时候发现需要A,于是B先去查一级缓存,发现找不到,然后去查二级缓存,还是没有,接着再去找三级缓存,找到了A,于是把三级缓存里面的这个A放到二级缓存中,并删除三级缓存里面的A。
  3. B顺利初始化完毕,将自己放到一级缓存里面(此时B里面的A依然是创建中的状态),然后接着回来创建A,此时B已经创建结束,直接从一级缓存中拿到B,然后完成创建,并将A自己放到一级缓存里面。

Spring事务什么时候会失效

  1. 发生自调用。
  2. 方法不是public的,@Transaction只能用于public方法,否则事务会失效,如果要用到非public方法上,可以开启AspectJ代理模式。
  3. 数据库不支持事务的。
  4. 没有被Spring管理的。
  5. 异常被catch了,事务不会回滚。

SpringMVC的工作流程

  1. 客户端(浏览器)发送请求,直接请求到 DispatcherServlet。
  2. DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。
  3. 解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由 HandlerAdapter 适配器处理。
  4. HandlerAdapter 会根据 Handler来调用真正的处理器开始处理请求,并处理相应的业务逻辑。
  5. Handler处理器处理完业务后,会返回一个 ModelAndView 对象,Model 是返回的数据对象,View 是个逻辑上的 View。
  6. HandlerAdapter将Handler执行结果ModelAndView返回到DispatcherServlet。
  7. DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
  8. ViewReslover解析后返回具体View。
  9. DispatcherServlet对View进行渲染视图(即将模型数据model填充至视图中)。
  10. DispatcherServlet响应用户。

SpringBoot自动装配原理

如何理解 Spring Boot 中的 Starter

比如传统使用spring springmvc,如果需要引入mybatis等框架,需要到xml中定义mybatis需要的bean。

stater就是定义一个start的jar包,写一个@Configuration配置类,将这些bean定义在里卖弄,然后在start包的META-INF/spring.factories中写入该配置类,springboot会按照约定来加载该配置类。

开发人员只需要将相应的start包依赖引入到应用,然后进行相应的属性配置,也有默认的配置,就可以直接进行代码的开发了。

0 人点赞