Spring 面试问答

Spring 面试问答

原文: https://howtodoinjava.com/interview-questions/top-spring-interview-questions-with-answers/

我已经尝试收集了这些Spring 面试问题,您可能会在下一次技术面试中面对这些问题。 对于其他 Spring 课程,我将分别分享面试问题和答案。 如果您能提出以前面试中遇到过的更多类似 Spring 面试问题,并考虑提出它们作为专家级 Spring 面试问题,我将不胜感激。 我将它们添加到此列表中。 这对于其他学习者也将有很大的帮助。

Spring 面试题

1.什么是 Spring Framework? 它的主要模块是什么? 2.使用 Spring Framework 有什么好处? 3.什么是控制反转(IoC)和依赖注入? 4.在 Spring Framework 中解释 IoC? 5. BeanFactoryApplicationContext之间的区别? 6.您可以通过多种方式将 Spring 配置到我们的应用程序中? 7.什么是基于 Spring XML 的配置? 8.什么是基于 Spring Java 的配置? 9.什么是基于 Spring 注解的配置? 10.解释 Spring Bean 的生命周期吗? 11.什么是不同的 Spring Bean 范围? 12. Spring 中的内部 bean 是什么? 13. 单例 bean 在 Spring Framework 中线程安全吗? 14.如何在 Spring 中注入 Java 集合? 举个例子? 15.如何将java.util.Properties注入 Spring Bean? 16.解释 Spring Bean 自动装配吗? 17.解释 Bean 自动装配的不同模式吗? 18.如何打开基于注解的自动装配? 19.用示例解释@Required注解? 20.用示例解释@Autowired注解? 21.用示例解释@Qualifier注解? 22.构造函数注入和 setter 注入之间的区别? 23. Spring 框架中不同类型的事件是什么? 24. FileSystemResourceClassPathResource之间的区别? 25.列举一些 Spring 框架中使用的设计模式吗?

1. 什么是 Spring 框架? 它的主要模块是什么?

Spring 框架是一个 Java 平台,为开发 Java 应用程序提供全面的基础架构支持。 Spring 处理基础结构部分,因此您可以专注于应用程序部分。 在其内部,Spring 框架将形式化的设计模式编码为一流的对象,您可以将它们集成到自己的应用程序中,而不必担心它们在后端如何工作。

目前,Spring 框架由组织为约 20 个模块的功能组成。 这些模块分为核心容器,数据访问/集成,Web,AOP(面向切面的编程),规范,消息传递和测试,如图所示。 下图。

spring modules

阅读更多: Spring 框架教程

2. 使用 Spring 框架有什么好处?

以下是使用 Spring Framework 的一些主要好处的清单:

  • 使用 依赖注入(DI) 方法,依赖在构造函数或 JavaBean 属性中是显式的且显而易见的。
  • IoC 容器往往是轻量级的,特别是例如与 EJB 容器相比时。 这对于在内存和 CPU 资源有限的计算机上开发和部署应用程序很有用。
  • Spring 并没有彻底改变这种状况,它确实利用了一些现有技术,例如几个 ORM 框架,日志记录框架,JEE,Quartz 和 JDK 计时器以及其他视图技术。
  • Spring 以模块化的方式组织。 即使包和类的数量很多,您也只需要担心需要的包而忽略其余的包。
  • 测试用 Spring 编写的应用程序 很简单,因为依赖于环境的代码已移入该框架。 此外,通过使用 JavaBean 风格的 POJO,使用依赖注入来注入测试数据变得更加容易。
  • Spring 的 Web 框架是精心设计的 Web MVC 框架,它提供了 Struts 之类的 Web 框架或其他经过精心设计或不太受欢迎的 Web 框架的绝佳替代。
  • Spring 提供了一个一致的事务管理接口,该接口可以按比例缩小到本地事务(例如,使用单个数据库),并可以扩大到全局事务(例如,使用 JTA)。

3. 什么是控制反转(IoC)和依赖注入?

在软件工程中,控制反转(IoC)是一种编程技术,其中对象耦合在运行时由汇编程序对象绑定,并且通常在编译时使用静态分析是未知的。 在传统编程中,业务逻辑的流程由静态分配给彼此的对象确定。 在控制反转的情况下,流程依赖于由汇编程序实例化的对象图,并且通过抽象定义对象交互来使流程成为可能。 绑定过程是通过“依赖注入”实现的。

控制反转是一种设计示例,旨在为您的应用程序的目标组件(实际上是在工作的组件)提供更多控制。

依赖注入是一种模式,用于创建其他对象依赖的对象实例,而在编译时不知道将使用哪个类来提供该功能。 控制反转依赖于依赖项注入,因为需要一种机制来激活提供特定功能的组件。 否则,如果框架不再受控制,框架将如何知道要创建哪些组件?

在 Java 中,依赖项注入可能通过 3 种方式发生:

  1. 构造函数注入
  2. 二传手注入
  3. 接口注入

4. 在 Spring Framework 中解释 IoC?

org.springframework.beansorg.springframework.context软件包为 Spring Framework 的 IoC 容器提供了基础。BeanFactory接口提供了一种高级配置机制,能够管理任何性质的对象。ApplicationContext接口建立在BeanFactory之上(它是一个子接口),并添加了其他功能,例如集成更容易消息资源处理(用于国际化),事件传播和特定于应用程序层的上下文,例如WebApplicationContext用于 Web 应用程序。

org.springframework.beans.factory.BeanFactory是 Spring IoC 容器的实际表示,该容器负责包含和管理上述 bean。BeanFactory接口是 Spring 中的中央 IoC 容器接口。

5. BeanFactoryApplicationContext之间的区别?

BeanFactory就像一个工厂类,其中包含一组 bean。 BeanFactory 在其内部保存多个 Bean 的 Bean 定义,然后在客户要求时实例化 Bean。 BeanFactory能够在实例化协作对象之间创建关联。 这消除了 bean 本身和 bean 客户端的配置负担。 BeanFactory也参与了 bean 的生命周期,调用了自定义的初始化和销毁​​方法。

从表面上看,应用程序上下文与 Bean 工厂相同。 两者都装入 bean 定义,将 bean 装在一起,并根据请求分配 bean。 但它也提供:

  1. 解决文本消息的方法,包括对国际化的支持。
  2. 加载文件资源的通用方法。
  3. 注册为监听器的 bean 的事件。

ApplicationContext的三种常用实现是:

  1. ClassPathXmlApplicationContext:它从位于类路径中的 XML 文件中加载上下文定义,将上下文定义视为类路径资源。 使用代码从应用程序的类路径中加载应用程序上下文。

    ApplicationContext context = new ClassPathXmlApplicationContext(bean.xml);
    
  2. FileSystemXmlApplicationContext:它从文件系统中的 XML 文件加载上下文定义。 使用代码从文件系统中加载应用程序上下文。

    ApplicationContext context = new FileSystemXmlApplicationContext(bean.xml);
    
  3. XmlWebApplicationContext:它从 Web 应用程序中包含的 XML 文件中加载上下文定义。

6. 您可以通过多种方式将 Spring 配置到我们的应用程序中?

您可以通过 3 种方式在应用程序中配置 spring:

  1. 基于 XML 的配置
  2. 基于注解的配置
  3. 基于 Java 的配置

7. 什么是基于 Spring XML 的配置?

在 Spring 框架中,bean 需要的依赖项和服务在配置文件中指定,配置文件通常以 XML 格式。 这些配置文件通常以<beans>标记开头,并包含许多 bean 定义和特定于应用程序的配置选项。

Spring XML 配置的主要目标是使用 xml 文件配置所有 Spring 组件。 这意味着将不存在任何其他类型的 Spring 配置(例如注解或通过 Java 类进行的配置)。

Spring XML 配置使用 Spring 命名空间使配置中使用的 XML 标记集可用。 Spring 的主要名称空间包括:contextbeanjdbctxaopmvcaso

<beans>

	<!-- JSON Support -->
	<bean name="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
	<bean name="jsonTemplate" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>

	<bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/>

</beans>

在下面仅配置DispatcherServlet的最简单的web.xml文件将为您的应用程序加载配置文件并为您配置运行时组件。

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <servlet>
		<servlet-name>spring</servlet-name>
			<servlet-class>
				org.springframework.web.servlet.DispatcherServlet
			</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>spring</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

8. 什么是基于 Spring Java 的配置?

Spring 的新 Java 配置支持中的主要工件是@Configuration注解的类和@Bean注解的方法。

@Bean注解用于指示方法实例化,配置和初始化要由 Spring IoC 容器管理的新对象。 @Bean注解与<bean/>元素具有相同的作用。

@Configuration注解一个类表示该类的主要目的是作为 Bean 定义的来源。 此外,@Configuration类允许通过简单地调用同一类中的其他@Bean方法来定义 Bean 之间的依赖关系。 最简单的@Configuration类如下:

@Configuration
public class AppConfig 
{
    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

上面的 java 配置的等效 XML 配置为:

<beans>
    <bean id="myService" class="com.howtodoinjava.services.MyServiceImpl"/>
</beans>

要实例化此类配置,您将需要AnnotationConfigApplicationContext类的帮助。

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}

要启用组件扫描,只需注解您的@Configuration类,如下所示:

@Configuration
@ComponentScan(basePackages = "com.howtodoinjava")
public class AppConfig  {
    ...
}

在上面的示例中,将扫描com.acme包,查找任何带有@Component注解的类,并将这些类注册为容器内的 Spring bean 定义。

如果在 Web 应用程序中使用上述配置,则将使用AnnotationConfigWebApplicationContext类。 在配置 Spring ContextLoaderListener Servlet 监听器,Spring MVC DispatcherServlet等时,可以使用此实现。

<web-app>
    <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext instead of the default XmlWebApplicationContext -->
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>

    <!-- Configuration locations must consist of one or more comma- or space-delimited fully-qualified @Configuration classes. Fully-qualified packages may also be specified for component-scanning -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.howtodoinjava.AppConfig</param-value>
    </context-param>

    <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Declare a Spring MVC DispatcherServlet as usual -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext instead of the default XmlWebApplicationContext -->
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>
                org.springframework.web.context.support.AnnotationConfigWebApplicationContext
            </param-value>
        </init-param>
        <!-- Again, config locations must consist of one or more comma- or space-delimited and fully-qualified @Configuration classes -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>com.howtodoinjava.web.MvcConfig</param-value>
        </init-param>
    </servlet>

    <!-- map all requests for /app/* to the dispatcher servlet -->
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>
</web-app>

9. 什么是基于 Spring 注解的配置?

从 Spring 2.5 开始,可以使用注解配置依赖项注入。 因此,可以使用相关类,方法或字段声明上的注解,而不是使用 XML 来描述 bean 的连接,而可以将 bean 配置移入组件类本身。 注解注入在 XML 注入之前执行,因此对于通过两种方法连接的属性,后一种配置将覆盖前者。

默认情况下,Spring 容器中的注解装配未打开。 因此,在使用基于注解的连接之前,我们需要在 Spring 配置文件中启用它。 因此,如果您想在 Spring 应用程序中使用任何注解,请考虑使用以下配置文件。

<beans>

   <context:annotation-config/>
   <!-- bean definitions go here -->

</beans>

一旦配置了<context:annotation-config/>,就可以开始注解代码,以指示 Spring 应该自动将值连接到属性,方法和构造函数中。

在这种类型的配置中,很少使用的重要注解是:

  1. @Required@Required注解适用于 bean 属性设置器方法。
  2. @Autowired@Autowired注解可以应用于 bean 属性设置器方法,非设置器方法,构造函数和属性。
  3. @Qualifier@Qualifier注解与@Autowired一起使用,可以通过指定要连接的确切 bean 来消除混淆。
  4. JSR-250 注解:Spring 支持基于 JSR-250 的注解,包括@Resource@PostConstruct@PreDestroy注解。

10. 解释 Spring Bean 的生命周期吗?

易于理解的是 Spring bean 的生命周期。 实例化 Bean 时,可能需要执行一些初始化以使其进入可用状态。 同样,当不再需要 bean 并将其从容器中删除时,可能需要进行一些清理。

Spring bean 工厂负责管理通过 spring 容器创建的 bean 的生命周期。 bean 的生命周期由回调方法组成,这些方法可以大致分为两类

  1. 发布初始化回调方法
  2. 销毁前回调方法

Spring 框架提供了以下 4 种方法来控制 bean 的生命周期事件

  • InitializingBeanDisposableBean回调接口
  • 其他用于特定行为的Aware接口
  • Bean 配置文件中的自定义init()destroy()方法
  • @PostConstruct@PreDestroy注解

例如,customInit()customDestroy()方法是生命周期方法的示例。

<beans>
    <bean id="demoBean" class="com.howtodoinjava.task.DemoBean" init-method="customInit" destroy-method="customDestroy"></bean>
</beans>

阅读更多信息:SpringBean 生命周期

11. Spring Bean 范围有哪些不同?

可以在五个 bean 范围中创建 spring 容器中的 bean。 所有作用域名称都是不言自明的,但请明确说明它们,以免产生任何疑问。

  1. 单例:此 bean 范围是默认值,它强制容器在每个 spring 容器中只有一个实例,而不管您请求实例的时间是多少。 这种单例行为由 bean 工厂本身维护。
  2. 原型:该 bean 作用域只是反转单例作用域的行为,每次每次请求 bean 都产生一个新实例。
  3. 请求:在此 bean 作用域内,将为客户端的每个 Web 请求创建一个新的 bean 实例。 请求完成后,bean 将超出范围并被垃圾回收。
  4. 会话:就像请求范围一样,这确保了每个用户会话一个 bean 实例。 用户结束会话后,bean 不在范围内。
  5. 全局会话:全局会话是连接到 Portlet 应用程序的东西。 当您的应用程序在 Portlet 容器中工作时,它是由一定数量的 Portlet 构建的。 每个 portlet 都有其自己的会话,但是如果要在应用程序中为所有 portlet 全局存储变量,则应将其存储在全局回话中。 此作用域与基于 Servlet 的应用程序中的会话作用域没有任何特殊作用。

阅读更多:SpringBean 范围

12. 什么是 Spring Bean?

在 Spring 框架中,每当一个 bean 仅用于一个特定属性时,建议将其声明为一个内部 bean。 内部 bean 在 setter 注入property和构造函数注入constructor-arg中均受支持。

例如,假设我们引用了Person类的一个Customer类。 在我们的应用程序中,我们将只创建Person类的一个实例,并在Customer中使用它。

public class Customer 
{
	private Person person;

	//Setters and Getters
}

public class Person 
{
	private String name;
	private String address;
	private int age;

	//Setters and Getters
}

现在,内部 bean 声明将如下所示:

<bean id="CustomerBean" class="com.howtodoinjava.common.Customer">
	<property name="person">
		<!-- This is inner bean -->
		<bean class="com.howtodoinjava.common.Person">
			<property name="name" value="adminis"></property>
			<property name="address" value="India"></property>
			<property name="age" value="34"></property>
		</bean>
	</property>
</bean>

13. 在 Spring 框架中,单例 bean 线程安全吗?

对于单例 bean 的多线程行为,Spring 框架不做任何事情。 开发人员有责任处理单例 bean 的并发问题和 线程安全

实际上,大多数 SpringBean 没有可变状态(例如服务和 DAO 锁类),因此线程安全性很小。 但是如果您的 bean 处于可变状态(例如,查看模型对象),那么您需要确保线程安全。 解决此问题的最简单,最明显的方法是将可变 Bean 的范围从singleton更改为property

14. 如何在 Spring 中注入 Java 集合? 举个例子?

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

  • <list>:这有助于装配,即注入值列表,允许重复。
  • <set>:这有助于装配一组值,但没有重复项。
  • <map>:这可以用于注入名称-值对的集合,其中名称和值可以是任何类型。
  • <prop>:这可用于注入名称-值对的集合,其中名称和值均为字符串。

我们来看每种类型的示例。

<beans>

   <!-- Definition for javaCollection -->
   <bean id="javaCollection" class="com.howtodoinjava.JavaCollection">

      <!-- java.util.List -->
      <property name="customList">
        <list>
           <value>INDIA</value>
           <value>Pakistan</value>
           <value>USA</value>
           <value>UK</value>
        </list>
      </property>

     <!-- java.util.Set -->
     <property name="customSet">
        <set>
           <value>INDIA</value>
           <value>Pakistan</value>
           <value>USA</value>
           <value>UK</value>
        </set>
      </property>

     <!-- java.util.Map -->
     <property name="customMap">

		<map>
           <entry key="1" value="INDIA"/>
           <entry key="2" value="Pakistan"/>
           <entry key="3" value="USA"/>
           <entry key="4" value="UK"/>
        </map>

      </property>

	  <!-- java.util.Properties -->
	<property name="customProperies">
		<props>
			<prop key="admin">admin@nospam.com</prop>
			<prop key="support">support@nospam.com</prop>
		</props>
	</property>

   </bean>

</beans>

15. 如何将java.util.Properties注入 Spring Bean?

第一种方法是使用<prop>标签,如下所示。

<bean id="adminUser" class="com.howtodoinjava.common.Customer">

	<!-- java.util.Properties -->
	<property name="emails">
		<props>
			<prop key="admin">admin@nospam.com</prop>
			<prop key="support">support@nospam.com</prop>
		</props>
	</property>

</bean>

您也可以使用util:命名空间从属性文件创建属性 bean,并使用 bean 引用进行 setter 注入。

<util:properties id="emails" location="classpath:com/foo/emails.properties" />

16. 解释 Spring Bean 自动装配吗?

在 spring 框架中,遵循配置文件中的 bean 依赖关系是一个好的做法,但是 spring 容器也能够自动装配协作 bean 之间的关系。 这意味着可以通过检查BeanFactory的内容来自动让 Spring 为您的 bean 解决协作者(其他 bean)。 自动装配 为每个 bean 指定,因此可以为某些 bean 启用,而其他 bean 将不会自动装配。

XML 配置文件的以下摘录显示了按名称自动装配的 Bean。

<bean id="employeeDAO" class="com.howtodoinjava.EmployeeDAOImpl" autowire="byName" />

除了 bean 配置文件中提供的自动装配模式外,还可以使用@Autowired注解在 bean 类中指定自动装配。 要在 bean 类中使用@Autowired注解,必须首先使用以下配置在 spring 应用程序中启用注解。

<context:annotation-config />

使用配置文件中的AutowiredAnnotationBeanPostProcessor bean 定义可以实现相同的目的。

<bean class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

现在,启用注解配置后,您可以使用@Autowired随意地自动绑定 bean 依赖项。

@Autowired
public EmployeeDAOImpl ( EmployeeManager manager ) {
    this.manager = manager;
}

17. 解释 Bean 自动装配的不同模式吗?

Spring 框架中有五种自动装配模式。 让我们一一讨论。

  1. off:该选项是 spring 框架的默认选项,表示自动装配为 OFF。 您必须使用 bean 定义中的标签显式设置依赖项。
  2. byName:此选项启用基于 bean 名称的依赖项注入。 在 Bean 中自动装配属性时,属性名称用于在配置文件中搜索匹配的 Bean 定义。 如果找到这样的 bean,则将其注入属性。 如果找不到这样的 bean,则会引发错误。
  3. byType:此选项启用基于 bean 类型的依赖项注入。 在 bean 中自动装配属性时,属性的类类型用于在配置文件中搜索匹配的 bean 定义。 如果找到这样的 bean,则将其注入属性。 如果找不到这样的 bean,则会引发错误。
  4. constructor:构造函数自动装配与byType相似,但适用于构造函数参数。 在启用自动装配的 bean 中,它将查找构造函数参数的类类型,然后按类型对所有构造函数参数进行自动装配。 请注意,如果容器中没有一个完全属于构造函数参数类型的 bean,则会引发致命错误。
  5. autodetect:通过自动检测进行自动装配使用两种模式之一,即构造函数或byType模式。 首先它将尝试寻找带有参数的有效构造函数,如果找到,则选择构造函数模式。 如果在 bean 中没有定义构造函数,或者存在显式的默认 no-args 构造函数,则选择byType自动装配模式。

18. 如何打开基于注解的自动装配?

要启用@Autowired,您必须注册AutowiredAnnotationBeanPostProcessor,并且可以通过两种方式进行。

1.在 bean 配置文件中包含<context:annotation-config >

<beans>
	<context:annotation-config />
</beans>

2.将AutowiredAnnotationBeanPostProcessor直接包含在 bean 配置文件中。

<beans>
	<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
</beans>

19. 用示例解释@Required注解?

在生产规模的应用程序中,可能在 IoC 容器中声明了成百上千个 bean,并且它们之间的依赖关系通常非常复杂。 setter 注入的缺点之一是,您很难检查是否已设置所有必需的属性。 为了解决这个问题,您可以设置<bean>依赖项检查属性,并设置四个属性之一,即无,简单,对象或全部(默认为无)。

在现实生活中的应用程序中,您将不需要检查上下文文件中配置的所有 Bean 属性。 相反,您只想检查是否仅在某些特定的 Bean 中设置了特定的属性集。 Spring 使用依赖项检查属性的依赖项检查功能在这种情况下将无法为您提供帮助。 因此,要解决此问题,可以使用@Required注解。

要在类文件中的 bean 属性的 setter 方法上使用@Required注解,如下所示:

public class EmployeeFactoryBean extends AbstractFactoryBean<Object>
{
    private String designation;

    public String getDesignation() {
        return designation;
    }

    @Required
    public void setDesignation(String designation) {
        this.designation = designation;
    }

    //more code here
}

RequiredAnnotationBeanPostProcessor是一个 Spring bean 后处理器,用于检查是否已设置所有带有@Required注解的 bean 属性。 要启用此 bean 后处理器进行属性检查,必须在 Spring IoC 容器中注册它。

<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />

如果尚未设置任何带有@Required的属性,则此 bean 后处理器将抛出BeanInitializationException

20. 用示例解释@Autowired注解?

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

例如。 您可以在 setter 方法上使用@Autowired注解,以摆脱 XML 配置文件中的<property>元素。 当 Spring 找到用于 setter 方法的@Autowired注解时,它将尝试通过在方法上键入自动装配来执行

您也可以将@Autowired应用于构造函数。 构造函数@Autowired注解指示即使在 XML 文件中配置 Bean 时不使用<constructor-arg>元素,创建该 Bean 时也应自动构造该构造函数。

public class TextEditor {
   private SpellChecker spellChecker;

   @Autowired
   public TextEditor(SpellChecker spellChecker){
      System.out.println("Inside TextEditor constructor." );
      this.spellChecker = spellChecker;
   }

   public void spellCheck(){
      spellChecker.checkSpelling();
   }
}

而且它的配置没有构造函数参数。

<beans>

   <context:annotation-config/>

   <!-- Definition for textEditor bean without constructor-arg -->
   <bean id="textEditor" class="com.howtodoinjava.TextEditor">
   </bean>

   <!-- Definition for spellChecker bean -->
   <bean id="spellChecker" class="com.howtodoinjava.SpellChecker">
   </bean>

</beans>

21. 用示例解释@Qualifier注解?

@Qualifier表示哪个 bean 可以在字段上自动装配。 如果 Spring 否则无法使用@Qualifier注解消除 Bean 引用的歧义。

参见下面的示例,它将自动将person bean 连接到客户的person属性中。

public class Customer 
{
	@Autowired
	private Person person;
}

对于Person类,我们有两个 bean 定义。

<bean id="customer" class="com.howtodoinjava.common.Customer" />

<bean id="personA" class="com.howtodoinjava.common.Person" >
	<property name="name" value="lokesh" />
</bean>

<bean id="personB" class="com.howtodoinjava.common.Person" >
	<property name="name" value="alex" />
</bean>

Spring 会知道应该自动装配哪个人的 bean? 没有。 在上面的示例中运行时,它会在下面的异常中命中:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: 
	No unique bean of type [com.howtodoinjava.common.Person] is defined: 
		expected single matching bean but found 2: [personA, personB]

要解决上述问题,您需要@Quanlifier告诉 Spring 应该自动装配哪个 bean。

public class Customer 
{
	@Autowired
	@Qualifier("personA")
	private Person person;
}

22. 构造函数注入和 setter 注入之间的区别?

请在下面找到明显的区别:

  1. 在 Setter 注入中,可能会部分注入依赖项,这意味着如果我们有 3 个依赖项(如intstringlong),那么如果使用 setter 注入,则不必注入所有值。 如果您不注入,它将采用这些原语的默认值。 在构造函数注入中,不可能部分注入依赖项,因为调用构造函数时必须正确传递所有参数,否则,可能会出错。
  2. 如果我们为同一属性编写 setter 和构造函数注入,则 Setter 注入将覆盖构造函数注入值。 但是,构造函数注入不能覆盖 setter 注入的值。 显而易见,因为首先要调用构造函数才能创建实例。
  3. 使用 setter 注入,您不能保证是否注入了某些依赖关系,这意味着您可能拥有不完全依赖关系的对象。 另一切面,在准备好依赖项之前,构造函数注入不允许您构造对象。
  4. 在构造函数注入中,如果对象 A 和 B 相互依赖,即 A 依赖于 B,反之亦然,则 Spring 在创建 A 和 B 的对象时会抛出ObjectCurrentlyInCreationException,因为在创建 B 之前无法创建对象,反之亦然 。 因此 spring 可以通过 setter 注入解决循环依赖关系,因为对象是在调用 setter 方法之前构造的。

23. Spring 框架中有哪些不同类型的事件?

Spring 的ApplicationContext提供了在代码中支持事件和监听器的功能。 我们可以创建 bean 来监听通过ApplicationContext发布的事件。 通过ApplicationEvent类和ApplicationListener接口提供ApplicationContext中的事件处理。 因此,如果 bean 实现ApplicationListener,则每次ApplicationEvent发布到ApplicationContext时,都会通知该 bean。

public class AllApplicationEventListener implements ApplicationListener < ApplicationEvent > 
{
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) 
	{
        //process event
    }
}

Spring 提供以下 5 个标准事件

  1. ContextRefreshedEvent:在初始化或刷新ApplicationContext时,将发布此事件。 也可以使用ConfigurableApplicationContext接口上的refresh()方法来提高它。
  2. ContextStartedEvent:使用ConfigurableApplicationContext接口上的start()方法启动ApplicationContext时,将发布此事件。 您可以轮询数据库,也可以在收到此事件后重新/启动任何已停止的应用程序。
  3. ContextStoppedEvent:当使用ConfigurableApplicationContext接口上的stop()方法停止ApplicationContext时,将发布此事件。 收到此活动后,您可以进行必要的整理工作。
  4. ContextClosedEvent:当使用ConfigurableApplicationContext接口上的close()方法关闭ApplicationContext时,将发布此事件。 关闭的环境已经到了生命的尽头。 它不能刷新或重新启动。
  5. RequestHandledEvent:这是一个特定于 Web 的事件,告诉所有 Bean HTTP 请求已得到服务。

除上述之外,您可以通过扩展ApplicationEvent类来创建自己的自定义事件。 例如

public class CustomApplicationEvent extends ApplicationEvent 
{ 
	public CustomApplicationEvent ( Object source, final String msg ) 
	{
		super(source);
		System.out.println("Created a Custom event");
	}
}

要监听此事件,请创建如下监听器:

public class CustomEventListener implements ApplicationListener < CustomApplicationEvent > 
{
	@Override
    public void onApplicationEvent(CustomApplicationEvent applicationEvent) {
		//handle event
	}
}

要发布此事件,您将需要ApplicationContext实例的帮助。

CustomApplicationEvent customEvent = new CustomApplicationEvent( applicationContext, "Test message" );
applicationContext.publishEvent ( customEvent ); 

24. FileSystemResourceClassPathResource之间的区别?

FileSystemResource中,您需要提供spring-config.xml(Spring 配置)文件相对于您的项目的路径或文件的绝对位置。

ClassPathResource中,spring 使用ClassPath查找文件,因此spring-config.xml应该包含在类路径中。 如果src中有spring-config.xml,则由于src默认情况下位于类路径中,因此我们只能给出其名称。

一句话,ClassPathResource在类路径中查找,而FileSystemResource在文件系统中查找。

25. 举出 Spring 框架中使用的一些设计模式吗?

有很多使用不同设计模式的负载,但是有一些显而易见的负载:

  • 代理-在 AOP 和远程调用中大量使用。
  • 单例 – Spring 配置文件中定义的 bean 默认为单例。
  • 模板方法 – 广泛用于处理样板重复代码,例如RestTemplateJmsTemplateJpaTemplate
  • 前端控制器 – Spring 提供DispatcherServlet以确保传入的请求被分派到您的控制器。
  • 视图助手 -Spring 具有许多自定义 JSP 标签和速度宏,以帮助将代码与视图中的表示分离。
  • 依赖项注入 – 以整个BeanFactory / ApplicationContext概念为中心。
  • 工厂模式-用于创建对象实例的BeanFactory

阅读更多:编写 Spring 配置文件的最佳实践

请分享最新的 Spring 面试问题,您可能在任何面试中都遇到过这些问题。

学习愉快!

参考文献:

Spring beans 文档 Spring 事务 Spring AOP 官方指南