被面试官问烂的25道 Spring 常见面试题

点击上方"Java学习之道",选择"关注"公众号

每天早晨,干货准时奉上!

本文来自“武哥聊编程” 

今天跟大家分享下Spring 常见面试题的知识。

1 Spring框架是什么?它的主要模块有哪些?

Spring框架是一个Java平台,提供全面的基础设施支持开发Java应用程序。Spring处理基础设施部分,这样你就可以专注于应用程序部分。Spring框架内,把一级对象通过设计模式封装起来,您可以放心的集成到您自己的应用程序而不用关注他们如何在后台工作。

目前,Spring框架由功能组织成大约20个模块。这些模块分为核心容器、数据访问/集成、Web,AOP(面向切面的编程)、instrument(支持和类加载器的实现来在特定的应用服务器上使用)、消息、和测试,如下列图所示。

被面试官问烂的25道 Spring 常见面试题_第1张图片

2 使用Spring框架的好处是什么?

下面是一些使用Spring框架的好处的列表:

通过依赖注入(DI)方式,在构造方法或者java bean属性上,依赖关系是明确的和明显的。

IoC容器往往是轻量级的,特别是与EJB容器相比。这是有利于在有限的内存和CPU资源的计算机上开发和部署应用程序。

Spring不重新发明轮子,相反,它利用一些现有的技术如几个ORM框架,日志框架,JEE,quartz和JDK计时器,其他视图技术等。

Spring是模块化的。尽管包和类很重要,你只关心你需要的模块,忽略其它模块。

在Spring测试应用程序很简单,因为依赖环境的代码被移入到框架本身。此外,通过使用JavaBean-style pojo方式,使用依赖注入注入测试数据变得更容易。

Spring的web框架是一个设计良好的web MVC框架,它可以很好的替代其它web框架如struts或者其它web框架。

Spring提供了一致的事务管理界面,可以管理小到一个本地事务(例如,使用一个数据库)和大到全局事务(例如,使用JTA)。

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

依赖注入和控制反转是对同一件事情的不同描述,从某个方面讲,就是它们描述的角度不同。

依赖注入是从应用程序的角度在描述,可以把依赖注入描述完整点:应用程序依赖容器创建并注入它所需要的外部资源;

而控制反转是从容器的角度在描述,描述完整点:容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源。

在Java中,依赖注入可能发生三种方法:

构造方法注入

setter方法注入

接口注入

4 Spring框架的IOC是怎么样的?

org.springframework.beans和org.springframework.context包是Spring框架IoC容器的基础。

BeanFactory接口提供了一个高级的配置机制来管理任意属性的对象。

ApplicationContext接口基于BeanFactory构建的(是一个子接口)并添加其他功能,如Spring的AOP功能,信息资源处理(用于国际化)、事件传播和应用程序层的特定上下文如在web应用程序中使用WebApplicationContext。

org.springframework.beans.factory.BeanFactory是Spring IoC容器真是展现,负责管理上述bean。BeanFactory接口是Spring IoC容器接口的核心。

5 BeanFactory和ApplicationContext之间的区别?

一个BeanFactory就像包含bean集合的工厂类。BeanFactory在内部持有多个Bean的定义,当客户端请求bean时,将bean进行实例化。

初始化时BeanFactory能够保持对象的依赖关系。这减轻了负担从bean本身和bean客户机的配置。BeanFactory在一个bean的生命周期也能其作用,它可以调用bean的自定义初始化和销毁方法。

表面上看,applicationContext和BeanFactory是一样。同样加载bean定义,将bean连接在一起,分发bean。但applicationContext还提供:

一种解析消息的手段,包括对国际化的支持。

一个更通用的加载文件资源的方法。

bean事件注册为监听器。

三个常用的ApplicationContext实现是:

ClassPathXmlApplicationContext:它从classpath路径下的一个XML文件加载
context的,将Context作为classpath下的资源。加载应用程序classpath下的
context使用的代码如下:ApplicationContext context = new ClassPathXmlApplicationContext(“bean.xml”);
FileSystemXmlApplicationContext:它从文件系统的一个XML文件加载上下文定义的。
从文件系统加载应用程序上下文通过如下代码实现。
ApplicationContext context = new FileSystemXmlApplicationContext(“bean.xml”);

XmlWebApplicationContext:它从一个web应用程序中包含的XML文件加载context。

6 将Spring配置应用程序的方式有哪些呢?

配置spring到您的应用程序有三种方式:

基于XML的配置

基于注解的配置

基于java的配置

7 基于xml的Spring配置是什么样子的?

在Spring框架中,bean所需的依赖和服务在定义在配置文件中,配置文件通常是XML格式。通常这些配置文件都以标签开始,含有大量的bean定义和特定于应用程序的配置选项。Spring XML配置的主要目标是让所有spring组件通过使用XML配置文件。

这意味着不会出现任何其他类型的Spring配置(如通过Java类注释或配置)。Spring XML配置中使用Spring命名空间提供的XML标记中使用的配置;Spring命名空间主要有:context、bean、jdbc、tx, aop, mvc等。

 
    
    
         
    

最简单的让您的应用程序加载配置文件和配置运行时组件方式是在web.xml文件中配置DispatcherServlet,如下所示:


  Archetype Created Web Application
   
  
        spring
            
                org.springframework.web.servlet.DispatcherServlet
            
        1
    
 
    
        spring
        /
        

8 基于java的Spring配置是什么样子的?

在支持spring的新java配置组件中,@Configuration注解的类和@Bean注解的方法是核心组件。

@Bean注解用于通过方法来实例化,配置和初始化一个新的由Spring IoC容器管理的对象。@Bean注解和元素扮演相同的角色。

在一个类上使用@Configuration注解,其主要用途是作为bean定义的来源。此外, 在同一个类中@Configuration类允许inter-bean定义通过简单地调用实现依赖关系。最简单的@Configuration注解类如下:

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

上面注解类等价于基于XML配置文件如下:


    

为了使这样的配置能生效,需要使用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.howtodoinjava包将被扫描,寻找任何带注解@Component的类,这些类将在容器内登记为Spring bean。

如果你使用以上的方式配置一个web应用程序,那么需要AnnotationConfigWebApplicationContext类来使之生效。AnnotationConfigWebApplicationContext的使用可以通过配置Spring ContextLoaderListener的servlet listener,Spring MVC DispatcherServlet等。


    
    
        contextClass
        
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        
    
 
    
    
        contextConfigLocation
        com.howtodoinjava.AppConfig
    
 
    
    
        org.springframework.web.context.ContextLoaderListener
    
 
    
    
        dispatcher
        org.springframework.web.servlet.DispatcherServlet
        
        
            contextClass
            
                org.springframework.web.context.support.AnnotationConfigWebApplicationContext
            
        
        
        
            contextConfigLocation
            com.howtodoinjava.web.MvcConfig
        
    
 
    
    
        dispatcher
        /app/*
    

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

从Spring 2.5就可以使用注解来配置依赖注入。而不是使用XML来描述一个bean的注入,你可以通过使用注解相关的类,方法或字段声明将bean配置的移到注解类本身。

注释注入执行XML注入之前,因此后者配置将会覆盖前者属性连接通过这两种方法。

默认情况下,spring容器没有打开自动注解功能。所以在使用具有spring注解之前,我们需要在我们的Spring配置文件启用它。如果你想在Spring应用程序中使用的自动注解,考虑配置文件上加上下面的配置。


   
   

一旦配置了,表明在Spring中您可以开始使用属性,方法和构造函数的自动注入。

一些重要的注解:

@required: @ required注解适用于bean属性setter方法。

@autowired: @ autowired注解可以适用于bean属性setter方法,non-setter方法、构造函数和属性。

@qualifier: @ qualifier注解加上@ autowired可以用来消除多个bean混乱来保证唯一的bean注入。

jsr - 250注释:Spring支持基于jsr - 250的注解如@Resource、@PostConstruct和@PreDestroy。

10 请解释一下Spring Bean的生命周期?

一个Spring bean的生命周期很容易理解。当一个bean实例化时可能需要执行一些初始化动作进入使bean达到一个可用的状态。同样,当不再需要bean时,将bean从容器中移除,可能需要销毁。

Spring beanFactory通过Spring容器负责管理bean的生命周期。bean的生命周期包括可以大体分类为两类的回调方法

初始化后的回调方法

销毁前的回调方法

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

InitializingBean和DisposableBean回调接口

其他知道接口为特定的行为

定制的init()和destroy()方法在bean配置文件

@PostConstruct和@PreDestroy注解

例如, customInit()和 customDestroy()方法生命周期方法的例子。


    

11 Spring Bean的作用域scope有哪些?

spring容器中的bean有5中scope,分别是:

单例singleton:默认情况下都是单例的,它要求在每个spring 容器内不论你请求多少次这个实例,都只有一个实例。单例特性是由beanfactory本身维护的。

原型prototype:这个bean的实例和单例相反,一个新的请求产生一个新的bean实例。

请求request:在一个请求内,将会为每个web请求的客户端创建一个新的bean实例。一旦请求完成后,bean将失效,然后被垃圾收集器回收掉。

会话session:就像请求范围,这样可以确保每个用户会话bean的一个实例。当用户结束其会话,bean失效。

全局会话global-session:应用到Portlet应用程序。基于Servlet的应用程序和会话相同。

12 spring的内部Bean是什么?

在Spring框架中,当一个bean只用于一个特定属性,建议将它声明为一个内在的bean。内部bean同时支持setter注入属性和构造函数注入“constructor-arg”。

例如,假设一个Customer类的引用Person类。在我们的应用程序中,我们将只创建一个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声明是这样的:


    
        
        
            
            
            
        
    

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

Spring框架不对单例的bean做任何多线程的处理。单例的bean的并发问题和线程安全是开发人员的责任。

而实际上,大多数spring bean没有可变状态(例如服务和DAO的类),这样的话本身是线程安全的。但如果您的bean有可变状态(例如视图模型对象),这就需要你来确保线程安全。

这个问题最简单和明显的解决方案是改变bean Scope,可变的bean从“单例”到“原型”。

14 如何在Spring里注入Java集合?请给个例子好吗?

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

:帮助注入一组值,允许重复。

:帮助注入一组值,不允许重复。

< map>:帮助注入一个K-V的集合,名称和值可以是任何类型的。

:帮助注入一个名称-值对集合,名称和值都是字符串。

让我们看看每种类型的例子。


 
   
   
 
      
      
        
           INDIA
           Pakistan
           USA
           UK
        
      
 
     
     
        
           INDIA
           Pakistan
           USA
           UK
        
      
 
     
     
         
        
           
           
           
           
        
 
      
       
      
    
        
            [email protected]
            [email protected]
        
    
 
   
 

15 如何将一个java.util.属性注入到Spring Bean ?

第一个方法是使用标记如下。


  
    
    
        
            [email protected]
            [email protected]
        
    
 

可以使用“util:“名称空间创建bean的属性文件,并使用bean的setter方法注入。


16 解释一下Spring Bean的自动注入是怎么样的?

在spring框架中,在配置文件中设置bean的依赖是一个很好的办法,但spring容器也能够自动注入不同bean之间的关系。这意味着,通过检查BeanFactory的内容它可以为您的bean自动注入其他bean。

可以为每个bean指定是否自动注入,因此可以支持一些Bean支持自动注入,而一些bean不会自动注入。

下面从XML配置文件摘录了自动根据名称注入的bean。


除了提供的自动装配模式bean配置文件,也可以在bean类中指定自动装配使用 @Autowired注释。

注意:在bean类使用@Autowired注解,您必须在spring应用程序中先启用下面的注解。


也可以通过在配置文件使用AutowiredAnnotationBeanPostProcessorbean来完成。


现在,当注释配置已经启用,您可以自由使用@Autowired来自动注入bean依赖关系,以你喜欢的方式。

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

17 请解释一下不同的bean自动注入模式?

在Spring有五个自动注入模式。让我们逐个讨论。

no:默认情况下,spring框架的自动注入选项,即默认情况不开启自动注入。这意味着你必须使用标签在bean定义中显式地设置依赖项。

byName:这个选项使基于bean的名称的依赖项注入。当自动装配在bean属性,用属性名搜索匹配的bean定义配置文件。如果找到这样的bean,注入属性。如果没有找到这样的bean,就会产生一个错误。

byType:该选项允许基于bean的类型的依赖项注入。当在bean属性需要自动注入时,使用属性类的类型来搜索匹配的bean定义配置文件。如果找到这样的bean,注入属性。如果没有找到这样的bean,就会产生一个错误。

constructor:构造方法类似于byType自动注入,但适用于构造方法的参数。在自动注入bean时,它在所有构造函数参数类型中寻找匹配的构造函数的类类型参数,然后进行自动注入,。请注意,如果在容器中没有一个bean构造函数参数类型满足,会抛出一个致命错误。

autodetect:自动侦测使用两种模式即构造函数或byType模式的自动注入。首先它将试图寻找有效的构造方法参数,如果发现构造方法模式则选择。如果没有构造方法中定义bean,或者明确的默认无参构造方法,则选择byType模式自动注入。欢迎关注公众号"Java学习之道",查看更多干货!

18 怎么打开基于注释的自动注入的?

要启用@Autowired,你必须注册AutowiredAnnotationBeanPostProcessor,你可以用两种方式。

1. 在bean配置文件使用


    

2. 直接将AutowiredAnnotationBeanPostProcessor放到bean配置文件。


    

19 能否用例子解释一下@ required注解吗?

在大规模的应用程序中,IoC容器中可能会有成百上千的bean声明,以及它们之间的依赖关系通常是非常复杂的。

setter注入的缺点之一是,很难给你检查出所需的所有属性是否已经注入。

为了克服这个问题,您可以设置bean的“dependency-check”属性,可以设置四个属性的其中之一即 none, simple, objects or all (没有一个是默认选项)。

在现实生活中应用程序中,您将不会感兴趣检查所有上下文中的bean属性配置文件。而你想要检查一些特定的bean是否已设置特定的属性。在这种情况下,Spring的依赖项检查功能将不再适用。

为了解决这个问题,您可以使用@Required注解。在bean属性使用@Required注解的setter方法类文件如下:

public class EmployeeFactoryBean extends AbstractFactoryBean
{
    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容器中。


如果@Required注解的任何属性没有设置,这个bean的处理器会抛出一个BeanInitializationException异常。

20 能否用例子解释一下@ autowired注解吗?

@Autowired注解提供了更细粒度的控制,以及应该如何完成自动注入。@Autowired注解和@Required注解一样,可用于bean的自动注入,它可以作用于构造方法,属性或具有任意名称和/或多个参数的方法。

例如,您可以使用@Autowired注解的setter方法来代替在XML配置文件中的元素。当Spring找到一个@Autowired注解的方法,它尝试使用byType自动注入的方法。

您可以将@Autowired应用到构造方法。一个构造方法使用@Autowired注解表明,即使在XML文件没有配置bean的元素,当创建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();
   }
}

没有构造方法参数的配置。


 
   
 
   
   
   
 
   
   
   
 

21 能否用例子讲解一下@qualifier注解吗?

@Qualifier限定哪个bean应该被自动注入。当Spring无法判断出哪个bean应该被注入时,@Qualifier注解有助于消除歧义bean的自动注入。

参见下面的例子,

public class Customer
{
    @Autowired
    private Person person;
}

我们有两个bean定义为Person类的实例。


 

    

 

    

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应该被autowired的。

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

22 构造方法注入和setter注入之间的区别吗?

有以下几点明显的差异:

在Setter注入,可以将依赖项部分注入,构造方法注入不能部分注入,因为调用构造方法如果传入所有的参数就会报错。

如果我们为同一属性提供Setter和构造方法注入,Setter注入将覆盖构造方法注入。但是构造方法注入不能覆盖setter注入值。显然,构造方法注入被称为创建实例的第一选项。

使用setter注入你不能保证所有的依赖都被注入,这意味着你可以有一个对象依赖没有被注入。在另一方面构造方法注入直到你所有的依赖都注入后才开始创建实例。

在构造函数注入,如果A和B对象相互依赖:A依赖于B,B也依赖于A,此时在创建对象的A或者B时,Spring抛出ObjectCurrentlyInCreationException。所以Spring可以通过setter注入,从而解决循环依赖的问题。

23 spring框架的事件类型有哪些?

Spring的ApplicationContext具有代码层上支持事件和监听器的功能。我们可以创建bean监听通过ApplicationContext发布的事件。ApplicationContext里的事件处理通过提供ApplicationEvent类和ApplicationListener接口来完成。所以如果一个bean实现了ApplicationListener接口,当一个ApplicationEvent发布到ApplicationContext时,该bean将接到通知。

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

Spring提供了以下5标准事件:

ContextRefreshedEvent:当ApplicationContext初始化或刷新时发布这个事件。这个事件也可以通过ConfigurableApplicationContext接口的refresh()方法来触发。

ContextStartedEvent:当ApplicationContext被ConfigurableApplicationContext接口的start()方法启动时发布这个事件。你可以在收到这一事件后查询你的数据库或重启/启动任何停止的应用程序。

ContextStoppedEvent:当ApplicationContext被ConfigurableApplicationContext接口的stop()方法关闭时发布这个事件。你可以在收到这一事件后做一些清理工作。

ContextClosedEvent:当ApplicationContext时被ConfigurableApplicationContext接口的close()方法关闭时发布这个事件。一个终结的上下文达到生命周期结束;它不能刷新或重启。

RequestHandledEvent:这是一个网络自身的事件,告诉所有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
    }
}

发布这个事件:

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

24 FileSystemResource和ClassPathResource之间的区别吗?

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

在ClassPathResource中Sping查找文件使用ClassPath,因此spring-config.xml应该包含在类路径下。

一句话,ClassPathResource在类路径下搜索和FileSystemResource在文件系统下搜索。

25 列举一下Spring框架使用的一些设计模式?

有很多不同的设计模式,但有一些明显的:

代理——在AOP大量使用,还有远程模块。

单例——spring配置文件中定义的bean默认是单例的。

模板方法——广泛使用处理重复逻辑的代码。例如RestTemplate, JmsTemplate, JpaTemplate.

前端控制器——Spring提供了DispatcherServlet,确保传入请求被分派到你的控制器。

视图助手——Spring有许多定制JSP标记,和velocity宏,协助在视图层分离展示代码。

依赖注入——BeanFactory / ApplicationContext的核心概念。

工厂模式——BeanFactory创建一个对象的实例

参考文献:https://howtodoinjava.com/interview-questions/top-spring-interview-questions-with-answers

今天就分享这么多,如果觉得文章对你有一丢丢帮助,请点右下角【在看】,让更多人看到该文章。

▽想查看更多Java面试题?

-- 完 --

 | 更多精彩文章 -


  • Zookeeper入门面试题

  • 如何优雅地处理 Java 异常

  • 11个代码质量审核和管理工具,程序员必备!

  • Java是世界上最好的语言!

  • 为什么说重启能解决90%的问题

  • 为什么你不回我微信了?

  • 微服务为什么一定要Zookeeper?


写留言   

觉得有用就点个在看 

你可能感兴趣的:(被面试官问烂的25道 Spring 常见面试题)