目录

Spring Interview Questions

亲爱的读者们,这些Spring Interview Questions专门设计用于让您熟悉在面试Spring时可能遇到的问题的本质。 根据我的经验,好的面试官在你的面试中几乎不打算问任何特定的问题,通常问题从这个主题的一些基本概念开始,然后他们继续基于进一步的讨论和你回答的内容:

Spring是企业Java的开源开发框架。 Spring Framework的核心功能可用于开发任何Java应用程序,但有一些扩展用于在Java EE平台之上构建Web应用程序。 Spring框架旨在通过启用基于POJO的编程模型,使J2EE开发更易于使用并促进良好的编程实践。

以下列出了使用Spring Framework的一些好处:

  • Lightweight - 弹簧在尺寸和透明度方面都很轻巧。 spring框架的基本版本大约为2MB。

  • Inversion of control (IOC) - 使用控制反转技术在弹簧中实现松耦合。 对象提供依赖关系,而不是创建或查找依赖对象。

  • Aspect oriented (AOP) - Spring支持面向方面的编程,并通过将应用程序业务逻辑与系统服务分离来实现内聚开发。

  • Container - Spring包含并管理应用程序对象的生命周期和配置。

  • MVC Framework - Spring的Web框架是一个设计良好的Web MVC框架,它提供了一个很好的替代Web框架,如Struts或其他过度设计或不太流行的Web框架。

  • Transaction Management - Spring提供了一致的事务管理接口,可以缩小到本地事务(例如,使用单个数据库)并扩展到全局事务(例如,使用JTA)。

  • Exception Handling - Spring提供了一个方便的API,用于将特定于技术的异常(例如,JDBC,Hibernate或JDO抛出)转换为一致的,未经检查的异常。

以下是Spring框架的模块:

  • 核心模块
  • Bean模块
  • 上下文模块
  • 表达语言模块
  • JDBC模块
  • ORM模块
  • OXM模块
  • Java消息传递服务(JMS)模块
  • 交易模块
  • Web模块
  • Web-Servlet模块
  • Web-Struts模块
  • Web-Portlet模块

Spring配置文件是一个XML文件。 此文件包含类信息,并描述了这些类是如何配置和相互引入的。

控制反转(IoC)是一个通用概念,它可以用许多不同的方式表达,而依赖注入只是控制反转的一个具体例子。

这个概念说你不是创建你的对象,而是描述它们应该如何创建。 您不能在代码中直接连接组件和服务,而是描述配置文件中哪些组件需要哪些服务。 然后,一个容器(IOC容器)负责将其全部挂起。

IoC的类型是 -

  • Constructor-based dependency injection - 当容器调用具有许多参数的类构造函数时,就完成了基于构造函数的DI,每个参数表示对其他类的依赖。

  • Setter-based dependency injection - 基于Setter的DI是在调用无参数构造函数或无参数静态工厂方法来实例化bean之后,通过容器调用bean上的setter方法来完成的。

由于您可以混合使用基于构造函数和基于Setter的DI,因此使用构造函数参数作为必需依赖项和使用可选依赖项的setter是一个很好的经验法则。 请注意,在setter上使用@Required注释可用于使setter所需的依赖项。

IOC或依赖注入的主要好处是 -

  • 它最大限度地减少了应用程序中的代码量。

  • 它使您的应用程序易于测试,因为它不需要单元测试用例中的任何单例或JNDI查找机制。

  • 以最小的努力和最少的侵入机制促进松散耦合。

  • IOC容器支持急切的实例化和延迟加载服务。

面向方面编程(AOP)是一种编程技术,它允许程序员模块化横切关注点或跨越典型责任划分的行为,例如日志记录和事务管理。 AOP的核心构造是方面,它将影响多个类的行为封装到可重用模块中。

Spring IoC创建对象,将它们连接在一起,配置它们,并管理从创建到销毁的整个生命周期。 Spring容器使用依赖注入(DI)来管理组成应用程序的组件。

有两种类型的IoC容器 -

  • Bean Factory container - 这是最简单的容器,为DI提供基本支持。在资源有限的情况下,BeanFactory通常是首选,如移动设备或基于applet的应用程序

  • Spring ApplicationContext Container - 此容器添加更多特定于企业的功能,例如从属性文件解析文本消息的功能以及将应用程序事件发布到感兴趣的事件侦听器的功能。

最常用的BeanFactory实现是XmlBeanFactory类。 此容器从XML文件读取配置元数据,并使用它来创建完全配置的系统或应用程序。

“应用程序上下文”的三个常用实现是 -

  • FileSystemXmlApplicationContext - 此容器从XML文件加载bean的定义。 在这里,您需要向构造函数提供XML bean配置文件的完整路径。

  • ClassPathXmlApplicationContext - 此容器从XML文件加载bean的定义。 在这里,您不需要提供XML文件的完整路径,但您需要正确设置CLASSPATH,因为此容器将在CLASSPATH中查找bean配置XML文件。

  • WebXmlApplicationContext - 此容器使用Web应用程序中的所有bean的定义加载XML文件。

以下是一些差异 -

  • 应用程序上下文提供了解析文本消息的方法,包括支持这些消息的i18n。

  • 应用程序上下文提供了加载文件资源(如图像)的通用方法。

  • 应用程序上下文可以将事件发布到注册为侦听器的bean。

  • 容器中的某些操作或容器中的bean(必须以bean工厂以编程方式处理)可以在应用程序上下文中以声明方式处理。

  • 应用程序上下文实现MessageSource,一个用于获取本地化消息的接口,实际的实现是可插入的。

构成应用程序主干并由Spring IoC容器管理的对象称为bean。 bean是一个由Spring IoC容器实例化,组装和管理的对象。 这些bean是使用您提供给容器的配置元数据创建的,例如,以XML 定义的形式。

bean定义包含称为配置元数据的信息,容器需要知道以下内容 -

  • 如何创建一个bean
  • Bean的生命周期细节
  • Bean的依赖关系

为Spring容器提供配置元数据有以下三种重要方法 -

  • 基于XML的配置文件。
  • 基于注释的配置
  • 基于Java的配置

检查以下示例 -

<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd">
   <bean id = "helloWorld" class = "com.iowiki.HelloWorld">
      <property name = "message" value = "Hello World!"/>
   </bean>
</beans>

在Spring中定义时,您可以选择声明该bean的作用域。 例如,要在每次需要时强制Spring生成一个新的bean实例,您应该将bean的scope属性声明为prototype 。 类似地,如果您希望每次需要Spring时返回相同的bean实例,您应该将bean的scope属性声明为singleton.

Spring Framework支持以下五个范围,其中三个范围仅在您使用支持Web的ApplicationContext时才可用。

  • singleton - 这将bean定义范围限定为每个Spring IoC容器的单个实例。

  • prototype - 这将单个bean定义范围包含任意数量的对象实例。

  • request - 这将bean定义范围限定为HTTP请求。 仅在Web感知Spring ApplicationContext的上下文中有效。

  • session - 将bean定义范围限定为HTTP会话。 仅在Web感知Spring ApplicationContext的上下文中有效。

  • global-session - 将bean定义范围限定为全局HTTP会话。 仅在Web感知Spring ApplicationContext的上下文中有效。

bean的默认范围是Spring框架的Singleton。

不,单例bean在Spring框架中不是线程安全的。

以下是Spring中bean生命周期的序列 -

  • Instantiate - 首先,spring容器从XML文件中查找bean的定义并实例化bean。

  • Populate properties - 使用依赖注入,spring填充bean定义中指定的所有属性。

  • Set Bean Name - 如果bean实现BeanNameAware接口,spring将bean的id传递给setBeanName()方法。

  • Set Bean factory - 如果Bean实现BeanFactoryAware接口,spring将beanfactory传递给setBeanFactory()方法。

  • Pre Initialization - 也称为bean的后处理。 如果有任何Bean BeanPostProcessors与bean关联,Spring调用postProcesserBeforeInitialization()方法。

  • Initialize beans - 如果bean实现了IntializingBean,则调用其afterPropertySet()方法。 如果bean具有init方法声明,则调用指定的初始化方法。

  • Post Initialization - 如果有任何与Bean关联的BeanPostProcessors,将调用它们的postProcessAfterInitialization()方法。

  • Ready to use - 现在应用程序可以使用bean了。

  • Destroy - 如果bean实现了DisposableBean,它将调用destroy()方法。

元素中的元素定义了一个所谓的内部bean。 内部bean定义不需要定义的id或名称; 容器忽略这些值。 它也忽略了范围标志。 内部bean总是匿名的,它们总是作为原型。

Spring提供了四种类型的集合配置元素,如下所示 -

  • 《list》 - 这有助于布线,即注入值列表,允许重复。

  • 《set》 - 这有助于连接一组值,但没有任何重复。

  • 《map》 - 这可用于注入一组名称 - 值对,其中name和value可以是任何类型。

  • 《props》 - 这可用于注入一组名称 - 值对,其中名称和值都是字符串。

Spring容器能够自动连接协作bean之间的关系。 这意味着可以通过检查BeanFactory的内容而不使用元素来自动让Spring解析bean的协作者(其他bean)。

自动装配功能有五种模式,可用于指示Spring容器使用自动装配进行依赖注入 -

  • no - 这是默认设置,这意味着没有自动装配,您应该使用显式bean引用进行连接。 你对这种布线没什么特别的。 这是您在依赖注入章节中已经看到的内容。

  • byName - 按属性名称自动装配。 Spring容器在XML配置文件中查看autowire属性设置为byName的bean的属性。 然后,它尝试匹配并将其属性与配置文件中由相同名称定义的bean相连。

  • byType - 按属性数据类型自动装配。 Spring容器在XML配置文件中查看autowire属性设置为byType的bean的属性。 然后,如果属性的类型与配置文件中的一个bean名称匹配,则会尝试匹配并连接属性。 如果存在多个这样的bean,则抛出致命异常。

  • constructor - 与byType类似,但type适用于构造函数参数。 如果容器中没有构造函数参数类型的一个bean,则会引发致命错误。

  • autodetect - Spring首先尝试通过构造函数使用autowire连接,如果它不起作用,Spring会尝试通过byType自动装配。

自动装配的限制是 -

  • Overriding possibility - 您仍然可以使用“constructor-arg”和“property”设置指定依赖项,这些设置将始终覆盖自动装配。

  • Primitive data types - 您无法自动装配所谓的简单属性,如基元,字符串和类。

  • Confusing nature - 自动装配不如显式布线精确,因此如果可能,请使用明确的布线。

是。

基于注释的配置提供了XML设置的替代方案,该配置依赖于字节码元数据来连接组件而不是角括号声明。 开发人员不是使用XML来描述bean连接,而是通过在相关的类,方法或字段声明上使用注释将配置移动到组件类本身。

默认情况下,Spring容器中未打开注释接线。 因此,在我们使用基于注释的连线之前,我们需要通过配置在我们的Spring配置文件中启用它。

此注释仅指示必须在配置时通过bean定义中的显式属性值或通过自动装配填充受影响的bean属性。 如果尚未填充受影响的bean属性,则容器将抛出BeanInitializationException。

此注释提供了对应在何处以及如何实现自动装配的更精细控制。 @Autowired注释可用于在setter方法上自动装配bean,就像@Required注释,构造函数,具有任意名称和/或多个参数的属性或方法一样。

当您创建多个相同类型的bean并且想要仅使用属性连接其中一个bean时,可能会出现这种情况,在这种情况下,您可以使用@Qualifier注释和@Autowired通过指定哪个精确bean来消除混淆将有线。

Spring有基于JSR-250的注释,包括@ PostConstruct,@ PreDestroy和@Resource注释。

  • @PostConstruct - 此注释可用作初始化回调的替代。

  • @PreDestroy - 此注释可用作销毁回调的替代。

  • @Resource - 此注释可用于字段或setter方法。 @Resource注释采用'name'属性,该属性将被解释为要注入的bean名称。 你可以说,它遵循名称自动装配语义。

基于Java的配置选项使您可以在没有XML的情况下编写大部分Spring配置,但可以使用少量基于Java的注释。

例如:注释@Configuration指示Spring IoC容器可以将该类用作bean定义的源。 @Bean注释告诉Spring,使用@Bean注释的方法将返回一个应该在Spring应用程序上下文中注册为bean的对象。

ApplicationContext中的事件处理是通过ApplicationEvent类和ApplicationListener接口提供的。 因此,如果bean实现了ApplicationListener ,那么每次将ApplicationEvent发布到ApplicationContext时,都会通知该bean。

Spring提供以下标准事件 -

  • ContextRefreshedEvent - 在初始化或刷新ApplicationContext时发布此事件。 这也可以使用ConfigurableApplicationContext接口上的refresh()方法引发。

  • ContextStartedEvent - 使用ConfigurableApplicationContext接口上的start()方法启动ApplicationContext时发布此事件。 您可以轮询数据库,也可以在收到此事件后重新启动任何已停止的应用程序。

  • ContextStoppedEvent - 使用ConfigurableApplicationContext接口上的stop()方法停止ApplicationContext时发布此事件。 收到此活动后,您可以进行必要的保养工作。

  • ContextClosedEvent - 使用ConfigurableApplicationContext接口上的close()方法关闭ApplicationContext时发布此事件。 封闭的环境达到其生命的终点; 它无法刷新或重新启动。

  • RequestHandledEvent - 这是一个特定于Web的事件,告诉所有bean已经为HTTP请求提供服务。

一个模块,其中包含一组提供交叉要求的API。 例如,日志记录模块将被称为AOP方面以进行日志记录。 根据要求,应用程序可以具有任意数量的方面。 在Spring AOP中,方面是使用常规类(基于模式的方法)或使用@Aspect注释(@AspectJ样式)注释的常规类来实现的。

Concern - 关注是我们希望在应用程序模块中拥有的行为。 关注点可以定义为我们想要实现的功能。 我们感兴趣的问题定义了我们的关注点。

Cross-cutting concern - 这是一个适用于整个应用程序的问题,它会影响整个应用程序。 例如,日志记录,安全性和数据传输是应用程序几乎每个模块都需要的问题,因此是跨领域的问题。

这代表了您可以插入AOP方面的应用程序中的一个点。 您还可以说,它是应用程序中使用Spring AOP框架执行操作的实际位置。

这是在方法执行之前或之后要采取的实际操作。 这是Spring AOP框架在程序执行期间调用的实际代码段。

这是一组应该执行建议的一个或多个连接点。 您可以使用表达式或模式指定切入点,我们将在AOP示例中看到。

介绍允许您向现有类添加新方法或属性。

由一个或多个方面建议的对象,该对象将始终是代理对象。 也称为建议对象。

编织是将方面与其他应用程序类型或对象链接以创建建议对象的过程。

编织可以在编译时,加载时或在运行时完成。

Spring方面可以使用下面提到的五种建议 -

  • before - 在方法执行before运行建议。

  • after - 在方法执行after运行建议而不管其结果如何。

  • after-returning - 仅在方法成功完成时才在方法执行后运行建议。

  • after-throwing - 仅在方法通过抛出异常退出时才在方法执行后运行建议。

  • around - 在调用建议方法之前和之后运行建议。

使用常规类以及基于XML的配置来实现方面。

@AspectJ指的是将方面声明为使用Java 5注释注释的常规Java类的样式。

借助Spring框架提供的模板类(称为JdbcTemplate),可以更有效地使用JDBC。

使用Spring JDBC框架可以减轻资源管理和错误处理的负担。 因此,它使开发人员编写语句和查询以从数据库获取数据。 JdbcTemplate提供了许多方便的方法,例如将数据库数据转换为基元或对象,执行预准备和可调用语句以及提供自定义数据库错误处理。

Spring支持两种类型的事务管理 -

  • Programmatic transaction management - 这意味着您已经在编程的帮助下管理了事务。 这为您提供了极大的灵活性,但很难维护。

  • Declarative transaction management - 这意味着您将事务管理与业务代码分开。 您只能使用注释或基于XML的配置来管理事务。

声明式事务管理优于程序化事务管理,但它不如程序化事务管理灵活,后者允许您通过代码控制事务。

Spring Web MVC框架提供模型 - 视图 - 控制器架构和现成的组件,可用于开发灵活且松散耦合的Web应用程序。 MVC模式导致应用程序的不同方面(输入逻辑,业务逻辑和UI逻辑)分离,同时在这些元素之间提供松散耦合。

Spring Web MVC框架是围绕处理所有HTTP请求和响应的DispatcherServlet设计的。

WebApplicationContext是普通ApplicationContext的扩展,它具有Web应用程序所需的一些额外功能。 它与普通的ApplicationContext不同之处在于它能够解析主题,并且知道它与哪个servlet相关联。

以下是Spring MVC优于Struts MVC的一些优点 -

  • Spring的MVC基于接口非常通用和灵活,但Struts强制Actions和Form对象具体继承。

  • Spring提供了拦截器和控制器,因此有助于将常见行为分解为处理许多请求。

  • Spring可以配置不同的视图技术,如Freemarker,JSP,Tiles,Velocity,XLST等。您还可以通过实现Spring View界面来创建自己的自定义视图机制。

  • 在Spring中,可以使用DI(IOC)配置MVC控制器,使其测试和集成变得容易。

  • Spring MVC的Web层比Struts Web层易于测试,因为它避免了强制具体继承以及控制器对调度程序servlet的显式依赖。

  • Struts强制你的控制器扩展Struts类,但是Spring没有,你可以选择扩展许多方便的Controller实现。

  • 在Struts中,Action通过在ActionMapping中定义ActionForwards或全局来耦合到视图。 SpringMVC具有HandlerMapping接口以支持此功能。

  • 使用Struts,通常在ActionForm的validate方法中执行(实现)验证。 在SpringMVC中,验证器是不依赖于Servlet API的业务对象,这使得在将域对象持久保存到数据库之前,可以在业务逻辑中重用这些验证器。

控制器提供对通常通过服务接口定义的应用程序行为的访问。 控制器解释用户输入并将其转换为由视图表示给用户的模型。 Spring以非常抽象的方式实现了一个控制器,使您可以创建各种各样的控制器。

@Controller注释指示特定类充当控制器的角色。 Spring不要求您扩展任何控制器基类或引用Servlet API。

@RequestMapping注释用于将URL映射到整个类或特定的处理程序方法。

使用spring访问hibernate有两种方法 -

  • 使用Hibernate模板和回调进行控制反转。

  • 扩展HibernateDAOSupport并应用AOP拦截器节点。

Spring支持以下ORM -

  • Hibernate
  • iBatis
  • JPA(Java持久性API)
  • TopLink
  • JDO(Java数据对象)
  • OJB

接下来是什么? (What is Next ?)

此外,您可以查看您对该主题所做的过去作业,并确保您能够自信地说出这些作业。 如果你更新鲜,那么面试官不会指望你会回答非常复杂的问题,而是你必须使你的基本概念非常强大。

↑回到顶部↑
WIKI教程 @2018