关于spring:面试题Spring

4次阅读

共计 9045 个字符,预计需要花费 23 分钟才能阅读完成。

Spring 概述

什么是 spring?

spring 是一个轻量级的 java 开发框架,它的呈现简化了企业级利用开发的难度,是 Java 开发人员更专一于业务代码逻辑的编写。它有两个特点:IOC 管制翻转和 AOP 面向切面编程。

谈谈 IOC 和 AOP

IOC(管制翻转)

平时咱们须要应用对象,都是本人 new 一个进去。这样在咱们我的项目中,就会呈现大量的冗余对象。而 IOC 管制翻转所在的事件,就是咱们之前本人 new 对象的操作取代了,对象由 spring 的 IOC 容器创立并治理。咱们须要用到一个对象的时候,只须要向 IOC 容器的 beanFactory 索取即可。总体来说,就是将对象创立的权力从程序员手上,交到了 IOC 容器手中。

AOP(面向切面编程)

AOP 是对 OOP(面向对象编程)的一种补充,面向对象编程是将事务的特色和行为形象成一个个对象,而面向切面编程则是在一个个对象的根底上的进一步形象。找寻这些对象都须要做的事件,而后就成一把刀一样在这些对象上切出一个面,来退出对象都须要做的事件。AOP 是通过动态代理或者动静代理来实现的,其余动静代理更为灵便,分为 Java 自带的代理接口和 Cglib 动静代理。咱们通常应用 AOP 来实现日志、事务、安全检查相干的操作。

Spring 由哪些模块组成?

  1. spring core:提供了框架的根本组成部分,如 IOC、DI 等性能。
  2. spring beans:提供了 BeanFactory,是工厂模式的一个经典实现,spring 将治理对象称为 bean。
  3. spring context:构建与 core 封装包根底上的 context 封装包,提供了一种框架式的对象拜访办法。
  4. Spring jdbc:拱了一个 JDBC 的形象层,打消了繁琐的 JDBC 编码和数据库厂商特有的错误代码解析,用于简化 JDBC 的操作。
  5. Spring AOP:提供了面对想切面的编程实现,让你能够自定义拦截器、切点等。
  6. Spring web:提供了针对 web 开发的继承个性,例如文件上传,利用 servlet listeners 进行 IOC 容器初始化和针对 web 的 applicationContext。
  7. Spring test:次要为测试提供反对的,反对应用 Junit 或 TestNG 对 Spring 组件进行单元测试和集成测试。

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

  1. 工厂模式:BeanFactory 就是简略工厂模式的体现的,用来创建对象的实例。
  2. 单例模式:Bean 默认为单例模式。
  3. 代理模式:Spring 的 AOP 面向切面编程就用来到了 JDK 的动静代理和 CGLIB 动静代理。
  4. 模板办法:比方,RestTemplate、JpaTemplate 都用了模板办法,用来解决代码反复的问题。
  5. 观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态产生扭转时,所有依赖于它的对象都会失去告诉被制动更新,如 Spring 中 listener 的实现ApplicationListener

Spring 如何治理事务的?

Spring 的事务申明有两种形式:编程式和申明式。
spring 次要是通过“申明式事务”的形式对事务进行治理,即在配置文件、注解进行事务申明,通过 AOP 将事务切面切入程序,最大的益处是大大减少了代码量。

Spring IOC 容器配置 Bean 的形式?

  1. XML 文件 bean 标签的形式
  2. 注解的形式
  3. java Config 代码类的形式

Bean 是如何被治理的?【重点】

在 spring 框架中,一旦把一个 bean 纳入到 Spring IOC 容器之中,这个 bean 的生命周期就会交由容器进行治理,个别担当管理者角色的是 BeanFactory 或 ApplicationContext。认识一下 Bean 的生命周期流动,对更好的利用它有很大的帮忙。
详情来说次要有四个阶段:实例化、初始化、应用、销毁。

  1. 首先容器启动后,会对 scope 为 singleton 且非懒加载的 bean 进行实例化。
  2. 依照 bean 定义信息配置信息,注入所有的属性。
  3. 如果 bean 实现了 BeanNameAware 接口,会回调该接口的 setBeanName()办法,传入该 Bean 的 id,此时该 bean 就取得了本人在配置文件中的 id。
  4. 如果 Bean 实现 BeanFactoryAware 接口,会回调该接口的 setBeanFactory()办法,传入该 bean 的 BeanFactory,这样该 bean 就取得了本人所在的 BeanFactory。
  5. 如果 Bean 实现了 ApplicationContextAware 接口,会回调该接口的 setApplicationContext()办法,传入该 Bean 的 ApplicationContext,这样该 bean 就取得了本人所在的 ApplicationContext。
  6. 如果有 Bean 实现了 BeanPostProcessor 接口,则会回调该接口的 postProcessBeforeInitialzation()办法。
  7. 如果 Bean 实现了 InitializingBean 接口,则会回调该接口的 afterPropertiesSet()办法。
  8. 如果 Bean 配置了 init-method 办法,则会执行 init-method 配置的办法。
  9. 如果有 Bean 实现了 BeanPostProcessor 接口,则会回调该接口的 postProcessAfterInitialization()办法。
  10. 通过流程 9 之后,就能够正式应用该 bean 了,对于 scope 为 singleton 的 bean,spring 的 ioc 容器中会缓存一份该 bean 的实例,而对于 scope 为 prototype 的 bean,每次被调用都会 new 一个新的对象,申明周期就交给调用方治理了,不再是 Spring 容器进行治理了。
  11. 容器敞开后,如果 Bean 实现了 DisposableBean 接口,则会回调该接口的 destroy()办法。
  12. 如果 Bean 配置了 destroy-method 办法,则会执行 destroy-method 配置的办法,至此,整个 Bean 的生命周期完结了。

Spring 中的主动拆卸有哪些限度?

  • 如果应用了结构器注入或者 settter 注入,那么将笼罩主动拆卸的依赖关系。
  • 根本数据类型的值、字符串字面量、类字面量无奈应用主动拆卸来注入。
  • 优先应用显式的拆卸来进行更准确的依赖注入而不是应用主动拆卸。

Spring 中 Bean 的作用域有哪些?

  1. singleton 作用域: 在 spring IOC 容器中仅仅存在一个 Bean 实例,Bean 是以单例形式存在的,为默认值。
  2. prototype 作用域:每次从容器中调用 Bean 时,都返回一个新的实例,即每次调用 getBean()时,相当于执行 newXXXBean().
  3. request 作用域:每一个 http 申请中的 bean 是单例的,该作用域仅实用于 WebApplicationContext 环境
  4. session 作用域:每一个 session 中的 bean 是单例的,不同 Session 应用不同的 Bean,仅实用于 WebApplicationContext 环境
  5. globalSession 作用域:个别用于 Portlet 应用环境,该作用域仅实用于 WebApplicationContext 环境。

什么是 IOC 和 DI?DI 是如何实现的?

IOC 是管制反转的意思,之前没有引入 IOC 容器时,退出对象 A 依赖于对象 B,那么对象 A 在创立初始化或者运行到某一点的时候,须要用到 B 对象时,就须要咱们手动本人去创立一个 B 对象。这个时候无论是创立 B 对象,还是应用 B 对象的控制权都在咱们本人的手上。然而在引入 IOC 容器之后,情景就实现变动了,当对象 A 运行过程中须要用到对象 B 的时候,不是须要咱们本人再手动创立一个 B 对象了,而是 IOC 容器会主动创立一个 B 对象,帮忙咱们注入到 A 对象中。通过前后的比照,咱们不难发现。对象 A 获取依赖对象 B 的过程,由被动行为编程了被动行为。对象的创立、管理权,从咱们手上转移到了 IOC 容器中了。这就是 IOC 管制翻转。
对于 DI 依赖注入:其实 DI 与 IOC 管制反转是从不同方面形容的同一件事件,都是指将对象的创立、管理权从使用者的手上,通过依赖注入到 IOC 容器中。

IOC 的优缺点

长处

升高了类之间的耦合,可维护性失去了进步。

毛病

  • 因为 IOC 容器中对象的生成是通过反射造成的,所以在运行效率上会有一些损失。
  • 要做一些额定的配置工作

你如何了解 AOP 中失去连接点(Joinpoint)、切点(Pointcut)、加强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念?

  • 连接点:程序执行的某个特定地位(如:某个办法调用前、调用后,办法抛出异样后)。一个类或一段程序代码领有一些具备边界性质的特定点,这些代码中的特定点就是连接点。Spring 仅反对办法的连接点。
  • 切点(Pointcut):如果连接点相当于数据中的记录,那么切点相当于查问条件,一个切点能够匹配多个连接点。Spring AOP 的规定解析引擎负责解析切点所设定的查问条件,找到对应的连接点。
  • 加强(Advice):加强是植入到指标类连接点上的一段程序代码。Spring 提供的加强连贯口都是带方位名的。如:BeforeAdvice、AfterReturningAdvice、ThrowsAdvice 等。
  • 引介(Introduction):引介是一种非凡的加强,它为类增加一些属性和办法。这样,即便一个业务类本来没有实现某个接口,通过引介性能能够动静的为该业务类增加接口的实现逻辑。让业务类成为这个接口的实现类。
  • 织入(Weaving):织入是将加强增加到指标类具体连接点上的过程,AOP 有三种织入形式:

    1. 编译期织入:须要非凡的 Java 编译期(例如 AspectJ 的 ajc)
    2. 装载期织入:要求应用非凡的类加载器,在装载类的时候对类进行加强
    3. 运行时织入:在容许时为指标生成代理实现加强。spring 采纳动静代词的形式实现了运行时织入,而 AspectJ 采纳了编译期织入和装载期织入的形式。
  • 切面(Aspet):切面是由切点和加强(引介)组成的,它包含了对横切关注性能的定义,也包含了对连接点的定义。

Spring 主动拆卸的形式有哪些?

  1. no:不进行主动拆卸,而是手动设置 Bean 的依赖关系
  2. byName:依据 Bean 的名字进行主动拆卸
  3. byType:依据 Bean 的类型进行主动拆卸
  4. constructor:相似于 byType,不过是利用于结构器的参数,如果正好有一个 Bean 与结构器的参数类型雷同则能够主动拆卸,否则会导致谬误。
  5. autodetect:如果有默认的结构器,这通过 constructor 的形式进行主动拆卸,否则应用 byType 的形式进行主动拆卸。

Spring 中如何应用注解来配置 Bean?有哪些相干的注解?

在启动类上增加 @EnableAutoConfiguration 或者 @SpringBootApplication 来开启主动配置,而后应用以下的注解来标注须要由 Spring IOC 容器进行对象托管的类。

  1. @Component:其余所有类
  2. @Controller:controller 控制器
  3. @Service:service 业务逻辑层
  4. @Repository:dao 数据交互层
    这几个注解的作用其实都是雷同的,都是将类注入到 ioc 容器中,只是为了不便区别字面上有所不同罢了。

Spring MVC 的工作流程

  1. 客户端的所有申请都叫给前端管制 dispatcherServlet 来解决,它会负责调用零碎的其余模块来真正解决用户的申请。
  2. 前端控制器 DispatcherServlet 收到申请后,将依据申请的信息以及 HandlerMapping 的配置找到解决该申请的对应 Handler 处理器。
  3. spring 会通过 HandlerAdapter 对该处理器进行封装,而后用对立的接口对各种 Handler 中的办法进行调用。
  4. Handler 实现对用户申请的解决后,会返回一个 ModelAndView 对象给前端控制器 DispatcherServlet。
  5. DispatcherServlet 借助逻辑视图解析器 ViewResolver 来解析刚返回失去的 ModelAndView 对象
  6. 最初拿到真正的视图对象,浏览器对模型数据进行渲染
  7. 客户端失去响应,可能是一个一般的 html 页面,也可能是 xml 或者是 JSON 字符串,还能够是一张图片或者 PDF 文件。

ApplicationContext 通常的实现是什么?

  • FlieSystemXmlApplciationContext: 此容器从一个 XML 文件中加载 bean 是的定义,XML bean 配置文件的全路径名必须提供给他的构造函数。
  • ClassPathXmlApplicationContext: 此容器也从一个 XML 文件中加载 Beans 的定义,这里,你须要正确设置 classpath,因为这个容器将在 classpath 外面找到 bean 配置。
  • WebXmlApplicationContext:此容器加载一个 XML 文件,此文件定义了一个 web 利用的所有 bean。

Bean 工厂和 APlication contexts 有什么区别?

  • 相同点:两者都是通过 xml 配置文件加载 bean
  • 不同点:applicationContext 相比于 BeanFactory,提供了更多的扩大性能。BeanFactory 是提早加载,如果 Bean 的某一个属性没有注入,BeanFactory 加载后,直至第一次应用调用 getBean 办法才会抛出异样。而 ApplicationContext 则在初始化本身就进行了效验,这样有利于查看说依赖属性是否注入。所以通常状况下咱们抉择应用 ApplicationContext。

spring 有几种依赖注入形式

  1. 变量注入

    • 间接在变量下面应用 @Autowired 的既是变量注入
    • 长处就是注入形式简略,十分简洁。
    • 毛病:注入的对象不能用 final 润饰;可能会导致循环依赖的呈现;对于 IOC 容器以外的环境,除了应用反射来提供它须要的依赖,无奈复用该实现类;
  2. 结构器注入

    • 显式注明必须强制注入,通过强制指明依赖注入来保障这个类的运行,防止出现空指针异样。
    • 注入对象能够应用 final 润饰。
    • 非 IOC 容器环境也能够应用 new 实例化该类的对象。
    • 防止了循环依赖,如果真的存在循环依赖,spring 我的项目启动的时候就会报错。
    • 毛病就是当咱们须要注入的对象过多的时候,构造函数的代码会显得十分的臃肿。
  3. setter 办法注入

    • 依赖注入中应用的依赖是可选的,抉择依赖的意思是注入的依赖是能够为 NULL。
    • 容许在类结构实现后从新注入
    • 毛病就是注入对象不能应用 final 润饰

    总结:如果注入的属性是必选的属性,则通过结构器注入的形式;如果注入的属性是可选的,则通过 setter 注入的形式;至于变量注入,不倡议应用,尽管很省劲。

什么是 spring beans?

咱们的 spring 应用程序就是由一个个 spring beans 组成的,它们通过注解或者 xml 配置文件的形式定义,而后注入到的 IOC 容器中,由 IOC 容器治理整个生命周期。

spring 中的 bean 是线程平安的吗?

首先 spring IOC 容器自身并没有提供线程安全策略,因而咱们对于 bean 的线程平安问题,咱们须要联合具体的 bean 作用域来说:

  1. singleton:单例 bean,不会创立新的 bean,所有的线程都专用一个 bean 对象,因而可能会存在线程平安问题。
  2. prototype:原型 bean,因为每次都会创立一个 bean 对象,所以不会呈现线程平安问题。
    实际上大部分理论 spring bean 都是无状态的,即无需进行数据保留操作,只是进行数据的查问。这个时候即便是单例 bean 也是线程平安的,然而如果要进行数据保留的一些操作,这个时候就须要咱们开发者本人对线程平安进行一些保障操作了。例如将 singleton 变为prototype

Spring 如何解决线程并发问题?

  1. 个别状况下,只有无状态的 bean 才能够再多线程环境下共享,在 Spring 中,绝大部分 bean 都是以 singleton 申明的作用域,所以可能存在线程平安问题。所以咱们能够采纳 ThreadLocal 和线程同步机制来解决线程平安问题。
  2. ThreadLocal 采纳了空间换工夫的做法,为每一个线程提供一个独立的变量正本,从而隔离了多个线程对于对一个变量资源的拜访。
  3. 而线程同步机制则是对于可能存在线程平安问题的资源进行加锁,不同的线程在拜访加锁资源之前都须要获取锁资源,没有获取到的须要进行期待。这样就保障了同时只有一个线程对资源进行操作,也就解决了多线程资源并发的问题。然而因为要期待锁资源,所以是一种“工夫换空间”的做法。

主动拆卸有哪些局限性?

  1. 重写:你仍须要和配置来定义依赖,意味着重要重写主动拆卸。
  2. 根本数据类型:你不能主动拆卸简略的属性,如根本数据类型,String 字符串和类。
  3. 含糊个性:主动状态不如显示拆卸准确,如果有可能还是倡议应用显示拆卸。

你可始终了 spring 中注入一个 null 和一个空字符串嘛?

能够

@Autowired 和 @Resource 之间有什么区别?

  1. @Autowired 默认是依照类型进行拆卸注入的,、
  2. 而 @Resource 默认是依照名称来拆卸注入的,只有当找不到名称匹配的 bean 才会依照类型来拆卸。

@Qualifier 注解有什么用?

用来配合 @Autowired 注解更加精准的指定拆卸哪个 bean,因为 @AutorWried 是依照类型进行拆卸的,如果有多个同类型的 bean 须要被拆卸,单单应用 @AutoWried 注解是不行的,须要通过增加 @Qualifier 注解来指定 name 拆卸。

@RequestMapping 注解有什么用?

@RequestMapping 注解用于将特定 HTTP 申请办法映射到将解决响应申请的控制器重的特定类和特定办法。

Spring 事务的实质

spring 事务的实质其实就是对数据库事务的反对,如果没有数据库的事务反对,spring 是无奈提供事务性能的,真正的数据库层的事务提交和回滚是通过 binlog 或者 redo log 实现的。

说一下 Spring 的事务流传行为

spring 事务的流传行为就是说,当多个事务同时存在的时候,spring 如何解决这些事务的行为:

  1. propagation_required:如果以后没有事务,就创立一个新事务,如果以后存在事务,就退出该事务,该设置是最罕用的设置。
  2. propagation_supports:反对以后事务,如果以后存在事务,就退出该事务,如果以后不存在事务,就以非事务运行。
  3. propagation_mandatory:反对以后事务,如果以后存在事务,就退出该事务,如果以后不存在事务,就抛出异样。
  4. propagatin_requires_new:创立新的事务,无论以后是否曾经存在事务,都会创立新的事务。
  5. propagation_not_supported:以非事务形式执行操作,如果以后存在事务,就把以后事务挂起。
  6. propagation_never:以非事务形式执行,如果以后存在事务,则抛出异样。
  7. propagation_nested:如果以后存在事务,则在嵌套事务内执行。如果以后没有事务,这创立一个新的事务。

说一下 spring 的事务隔离?

spring 有五大隔离级别,默认值为 ISOLATION_DEFAULT(应用数据库的设置),其余四个隔离级别和数据库的隔离级别统一:

  1. ISOLATION_DEFAULT:用底层数据库的设置隔离级别,数据库设置的是什么我就用什么;
  2. SOLATION_READ_UNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就可被其余事务读取(会呈现幻读、脏读、不可反复读);
  3. ISOLATION_READ_COMMITTED:提交读,一个事务提交后能力被其余事务读取到(会造成幻读、不可反复读),SQL server 的默认级别;
  4. ISOLATION_REPEATABLE_READ:可反复读,保障屡次读取同一个数据时,其值都和事务开始时候的内容是统一,禁止读取到别的事务未提交的数据(会造成幻读),MySQL 的默认级别;
  5. ISOLATION_SERIALIZABLE:序列化,代价最高最牢靠的隔离级别,该隔离级别能避免脏读、不可反复读、幻读。

脏读:示意一个事务可能读取另一个事务中还未提交的数据。比方,某个事务尝试插入记录 A,此时该事务还未提交,而后另一个事务尝试读取到了记录 A。
不可反复读:是指在一个事务内,屡次读同一数据后果不统一。
幻读:是指在一个事务内,屡次读取的数据条数不统一。

Spring AOP and AspectJ AOP 有什么区别?AOP 都有哪些实现形式?

AOP 实现的关键在于代理模式,AOP 代理模式次要分为动态代理和动静代理。动态代理代表就为 AspectJ,而动静代理则以 Spring AOP 为代表。

  • AspectJ 是动态代理的加强,所谓动态代理,就是 AOP 框架会在编译阶段生成 AOP 代理类,因而也称为编译时加强,他会在编译阶段将 AscpectJ(切面)织入到 Java 字节码中,运行的时候就是加强之后的 aop 对象。
  • spring aop 应用的是动静代词,所谓的动静代词就是说 AOP 框架不会去批改字节码,而是每次运行时在内存中长期为办法生成一个 aop 对象,这个 aop 对象蕴含了对象的全副办法,并且在特定的切点还做了加强解决,并回调原对象的办法。

JDK 动静代理和 CGLIB 动静代理的区别?

  • JDK 代理只能对实现接口的类生成代理;CGLib 是针对类实现代理,对指定的类生成一个子类,并笼罩其中的办法,这种通过继承类的实现形式,不能代理 final 润饰的类。
  • JDK 代理应用的是反射机制实现 aop 的动静代理,CGLib 代理应用字节码解决框架 ASM,通过批改字节码生成子类。所以 jdk 动静代理的形式创立代理对象效率较高,执行效率较低,CGLib 创立效率较低,执行效率高。
  • JDK 动静代理机制是委托机制,具体说动静实现接口类,在动静生成的实现类外面委托 hanlder 去调用原始实现类办法,CGLib 则应用的继承机制,具体说被代理类和代理类是继承关系,所以代理类是能够赋值给被代理类的,如果被代理类有接口,那么代理类也能够赋值给接口。

动静代理和动静代理的区别?

动态代理与动静代理区别在于生成 AOP 代理对象的机会不同,动态代理在字节码生成的时候就曾经存在代理类了,而动静代理切实字节码文件生成后,内存中动静增加代理对象的。

正文完
 0