java面试题之spring篇

这篇博客详细探讨了Spring框架的核心概念,包括IoC(控制反转)、AOP(面向切面编程)以及Bean之间的依赖关系。文章还讨论了Spring的单例模式实现、事务管理、BeanFactory与ApplicationContext的区别,以及Spring中的注解、事务传播属性和Spring Boot的特点。通过这些面试常见问题,读者可以深入了解Spring框架的工作原理和优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.Spring是什么?作用是什么?

Spring是一个轻量级的JavaEE框架,它主要解决企业应用中的复杂性问题。Spring框架有三个核心部分:IoC容器、AOP和数据访问/集成层。Spring中的IoC容器提供了一种对象创建和对象之间关系管理的机制,以实现松散耦合和可扩展性。AOP提供了一种很好的方式来实现横向关注点的处理,如事务管理,安全检查,缓存等。数据访问/集成层则提供了许多针对不同数据持久化技术的实现,比如JDBC,ORM和NoSQL。

2.你对IoC(控制反转 Inversion of Control)是怎么理解的?

IoC是一种设计思想,通过将对象之间的依赖关系交给容器来管理,从而实现松散耦合。在Spring中,IoC容器扮演了一个中心角色,负责创建对象,装配对象之间的依赖关系,并管理它们的整个生命周期。IoC还提供了一些高级功能,如AOP和事件驱动等,可以进一步增强应用程序的可维护性和可扩展性。

3.什么是AOP(面向切面编程 Aspect Oriented Programming)?

AOP是一种编程范式,它能够在程序运行期间动态地将代码切入到原有代码的流程中,从而实现横向关注点的处理,如日志记录、事务管理和安全检查等。在Spring中,AOP是通过代理模式来实现的,在创建Bean时为Bean生成一个代理对象,代理对象能够拦截指定方法的调用,并在执行前或执行后执行特定操作。

4.Spring中Bean之间的依赖关系是怎样的?

在Spring中,Bean之间的依赖关系主要通过构造函数注入、Setter方法注入和自动注入来实现。构造函数注入是通过Bean的构造方法注入其他Bean作为参数来实现;Setter方法注入是通过Bean的Setter方法来注入其他Bean;自动注入则是通过IoC容器在Bean创建时自动发现并注入其他Bean,可以通过设置@Autowired或@Resource注解来完成。

5.Spring框架中的单例模式是怎样实现的?

在Spring中,默认情况下,所有的Bean都是单例的。当IoC容器创建一个Bean时,它会缓存该Bean的实例,并在后续请求中返回相同的实例。这种机制可以提高应用程序的性能并减少内存消耗,但也需要注意线程安全和状态管理等问题。

6.Spring中的事务管理是如何实现的?

Spring通过AOP在运行时动态地将事务相关的逻辑切入到指定的方法中,从而实现事务管理。通常情况下,Spring使用声明式事务管理来管理事务。开发者可以通过@Transactional注解或XML配置文件来定义事务范围、传播属性以及回滚规则等。

7.Spring的优势是什么?

序号

好处

说明

1

轻量

Spring 是轻量的,基本的版本大约2MB。

2

控制反转

Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,<br>而不是创建或查找依赖的对象们。

3

面向切面编程(AOP)

Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。

4

容器

Spring 包含并管理应用中对象的生命周期和配置。

5

MVC框架

Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。

6

事务管理

Spring 提供一个持续的事务管理接口,<br>可以扩展到上至本地事务下至全局事务(JTA)。

7

异常处理

Spring 提供方便的API把具体技术相关的异常 <br>(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked 异常。

8.解释一下Spring中的BeanFactory和ApplicationContext有什么区别。

一、什么是BeanFactory?

BeanFactory是Spring框架的最底层接口,是Spring框架的基础设施,里面包含了各种对于Bean的定义,读取Bean的配置文档,管理Bean的加载、实例化,控制Bean的生命周期,维护Bean之间的依赖关系。
通俗的讲,BeanFactory最最典型的功能:getBean,BeanFactory帮助我们创建对象,我们通过getBean从而去拿到创建完成的对象,而不是自己手动去new。(如下图, 很多getBean方法)
表面上BeanFactory只能getBean,实际上,控制反转、基本的依赖注入、直到Bean的生命周期的各种功能都由它的实现类提供

二、什么是ApplicationContext?

ApplicationContext是BeanFactory的子接口,由BeanFactory派生而来,通常成为Spring上下文,具有BeanFactory的基本功能。大概理解为BeanFactory有的,ApplicationContext都有(如下图)。
此外,ApplicationContext扩展了BeanFactory接口的功能
国际化
通配符方式获取一组 Resource 资源
整合 Environment 环境(能通过它获取各种来源的配置信息)
事件发布与监听,实现组件之间的解耦

三、BeanFactory与ApplicationContext的联系和区别

区别1(功能上)
如上述介绍所说:BeanFactory是Spring的最底层接口,定义了IOC的基本功能,包含:各种Bean的定义、加载、实例化、依赖注入以及生命周期的管理。ApplicationContext接口继承了BeanFactory,除了提供BeanFactory所具有的基本功能以外,它还提供了更完整的框架功能:他还继承了MessageSource,因此还支持国际化,资源文件访问等功能;

区别2(加载形式)
BeanFactory在初始化容器的时候,并未实例化Bean,直到需要使用某个Bean(调用getBean()方法) 时才实例目标Bean,导致不能及时发现可能存在的一些配置上的问题。
ApplicationContext 则在初始化应用上下文时就实例化所有单实例的Bean,我们可以及时的发现配置中有可能存在的问题;由于ApplicationContext启动后加载了所有的单实例Bean,所以运行时速度比较快;唯一的不足在于它占用内存空间,配置的Bean较多时,启动会比较慢。

区别3(后处理器BeanPostProcessor 、BeanFactoryPostProcessor )
BeanFactory与ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor使用,BeanFactory使用需要手动注册,ApplicationContext则自动注入。(不懂看后面的篇幅会有解释)

总结
ApplicationContext 包含 BeanFactory 的所有特性,通常推荐使用前者。但是也有一些限制情形,比如移动应用内存消耗比较严苛,在那些情景中,使用更轻量级的 BeanFactory 是更合理的。然而,在大多数企业级的应用中,ApplicationContext 是首选。
简而言之,BeanFactory提供了配置框架和基本功能,ApplicationContext增加了更多针对企业的功能。ApplicationContext是BeanFactory的一个完整的超集。

9.Spring中的注解有哪些?

Spring中的常用注解有:

1)@Component、@Service、@Repository、@Controller:用于标识Bean的角色。

2)@Autowired、@Resource:用于自动装配Bean。

3)@PostConstruct、@PreDestroy:用于指定初始化和销毁方法。

4)@Transactional:用于声明式事务管理。

5)@Scope:用于指定Bean作用域。

10.Spring MVC框架的流程是怎样的?

Spring MVC的处理流程如下:

1)客户端向服务器发起请求。

2)DispatcherServlet接收到请求并将请求发送给处理器映射器进行处理器的映射查找。

3)处理器映射器将请求的URL映射到相应的控制器(Controller)上,并返回处理器及其拦截器(如果有)。

4)DispatcherServlet调用处理器适配器(Adapter)执行映射的处理器(Controller)。

5)处理器(Controller)执行后返回ModelAndView对象。

6)DispatcherServlet将ModelAndView对象交给视图解析器(ViewResolver)进行解析。

7)视图解析器(ViewResolver)解析出对应的视图(View)。

8)DispatcherServlet将Model数据和View视图进行渲染后返回给客户端。

11.Spring Boot是什么?与传统的Spring框架有什么区别?

Spring Boot是一种基于Spring的快速应用开发框架,它能够让开发者更加快速地搭建基于Spring的应用程序,并提供了自动化配置、快速启动等便利功能。相比传统的Spring框架,Spring Boot具有更简洁的配置方式和更快的启动速度,同时还提供了更多的功能和特性支持。

12.解释一下Spring的生命周期。

在Spring中,Bean的生命周期包括以下几个阶段:

1)实例化:当IoC容器读取到Bean的定义后,创建一个新的Bean实例。

2)属性注入:IoC容器将Bean中声明的依赖关系和配置信息注入到Bean中。

3)BeanPostProcessor前置处理:如果Bean中定义了BeanPostProcessor接口的实现类,它们将在Bean初始化之前被调用。

4)初始化:如果Bean实现了InitializingBean接口,则在所有属性都被设置完毕后调用afterPropertiesSet()方法。同时,也可以通过@Bean(initMethod = "init")来指定Bean的初始化方法。

5)BeanPostProcessor后置处理:如果Bean中定义了BeanPostProcessor接口的实现类,它们将在Bean初始化之后被调用。

6)销毁:如果Bean实现了DisposableBean接口,则在容器关闭或者该Bean被从容器中移除时调用destroy()方法。同时,也可以通过@Bean(destroyMethod = "destroy")来指定Bean的销毁方法。

13.Spring中的IOC如何管理对象?

在Spring中,IOC通过Bean工厂来管理对象,Bean工厂是提供了一种对象创建和对象之间关系管理的机制。它在读取配置文件时会自动创建和装配对象,并缓存这些对象以便后续使用。开发者可以通过构造器注入、Setter方法注入和自动注入等方式来管理对象之间的依赖关系。

14.Spring中的AOP的具体实现方式有哪些?

Spring中实现AOP的主要方式有两种:JDK动态代理和CGLIB代理。JDK动态代理又叫接口代理,它是基于Java反射机制实现的,要求目标对象必须实现至少一个接口;CGLIB代理则是基于字节码操作实现的,当目标对象没有实现接口时,它就会使用CGLIB代理。通常情况下,Spring默认使用JDK动态代理来实现AOP,但如果目标对象没有实现任何接口,则会自动切换到使用CGLIB代理。

15.Spring中的JdbcTemplate是什么?使用JdbcTemplate需要做哪些配置?

JdbcTemplate是Spring提供的一个对JDBC访问的封装,它简化了JDBC操作的繁琐和冗长,能够提高开发效率。使用JdbcTemplate需要在Spring的配置文件中配置基本数据源信息、配置JdbcTemplate Bean以及为JdbcTemplate Bean配置数据源。

16.解释一下Spring中的循环依赖问题。

循环依赖指两个或多个Bean之间相互引用,形成了一个无限循环调用的情况。在Spring容器中,如果存在循环依赖,但是都是单例模式的Bean,则可以通过Spring容器提前暴露正在创建的Bean,从而避免循环依赖问题。如果存在循环依赖且其中一方是原型模式的Bean,则Spring无法处理这种情况。

17.Spring中的事件驱动机制是怎样的?有哪些默认事件?

Spring中的事件驱动机制基于观察者模式实现。当一个Bean发生事件时,它会创建一个事件对象并将其发布到Spring容器上。容器中所有对该事件对象感兴趣的Bean都会收到事件通知并进行相应的处理。Spring中默认的事件有:ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent和ContextClosedEvent。

18.Spring的MVC框架中,HandlerAdapter的作用是什么?

HandlerAdapter是Spring MVC框架中的一个重要组件,它的作用是将请求交给相应的处理器(Controller)进行处理,并负责调用处理器的方法来生成ModelAndView对象。

19.@Autowired和@Resource注解用来干嘛的?

@Autowired和@Resource注解是用于自动装配Bean的。@Autowired是Spring提供的注解,可以在Setter方法上、构造函数上、类属性上进行标注,用于自动注入匹配类型的Bean。@Resource是JavaEE提供的注解,可以在Setter方法上或类属性上进行标注,用于自动注入指定名称和类型匹配的Bean。

20.Spring中的事务传播属性有哪些?

事务传播行为类型

说明

REQUIRED

如果当前事务管理器中没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择,是默认的传播行为。

SUPPORTS

支持当前事务,如果当前事务管理器中没有事务,就以非事务方式执行。

MANDATORY

使用当前的事务,如果当前事务管理器中没有事务,就抛出异常。

REQUIRES_NEW

新建事务,如果当前事务管理器中存在事务,把当前事务挂起,然后会新建一个事务。

NOT_SUPPORTED

以非事务方式执行操作,如果当前事务管理器中存在事务,就把当前事务挂起。

NEVER

以非事务方式执行,如果当前事务管理器中存在事务,则抛出异常。

NESTED

如果当前事务管理器中存在事务,则在嵌套事务内执行;如果当前事务管理器中没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

注意:这7种传播行为有个前提,他们的事务管理器是同一个的时候,才会有上面描述中的表现行为。

21.什么是依赖注入?

在Spring创建对象的过程中,把对象依赖的属性注入到对象中。依赖注入主要有两种方式:构造器注入和属性注入。

22.BeanFactory和ApplicationContext有什么区别?

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

两者区别如下:

1、功能上的区别。BeanFactory是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。

ApplicationContext接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能,如继承MessageSource、支持国际化、统一的资源文件访问方式、同时加载多个配置文件等功能。

2、加载方式的区别。BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。

而ApplicationContext是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 ApplicationContext启动后预载入所有的单例Bean,那么在需要的时候,不需要等待创建bean,因为它们已经创建好了。

相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

3、创建方式的区别。BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。

4、注册方式的区别。BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。

23.Bean的作用域

1、singleton:单例,Spring中的bean默认都是单例的。

2、prototype:每次请求都会创建一个新的bean实例。

3、request:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。

4、session:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP session内有效。

5、global-session:全局session作用域。

24.@Autowired和@Resource的区别?

Autowire是spring的注解。默认情况下@Autowired是按类型匹配的(byType)。如果需要按名称(byName)匹配的话,可以使用@Qualifier注解与@Autowired结合。@Autowired 可以传递一个required=false的属性,false指明当userDao实例存在就注入不存就忽略,如果为true,就必须注入,若userDao实例不存在,就抛出异常。

public class UserServiceImpl implements UserService {
    //标注成员变量
    @Autowired
    @Qualifier("userDao1")
    private UserDao userDao;   
 }

Resource是j2ee的注解,默认按 byName模式自动注入。@Resource有两个中重要的属性:name和type。name属性指定bean的名字,type属性则指定bean的类型。因此使用name属性,则按byName模式的自动注入策略,如果使用type属性,则按 byType模式自动注入策略。倘若既不指定name也不指定type属性,Spring容器将通过反射技术默认按byName模式注入。

@Resource(name="userDao")
private UserDao  userDao;//用于成员变量

//也可以用于set方法标注
@Resource(name="userDao")
public void setUserDao(UserDao userDao) {
   this.userDao= userDao;
}

上述两种自动装配的依赖注入并不适合简单值类型,如int、boolean、long、String以及Enum等,对于这些类型,Spring容器也提供了@Value注入的方式。

@Value和@Autowired、@Resource类似,也是用来对属性进行注入的,只不过@Value是用来从Properties文件中来获取值的,并且@Value可以解析SpEL(Spring表达式)。

比如,jdbc.properties文件如下:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&allowMultiQueries=true
jdbc.username=root
jdbc.password=root

利用注解@Value获取jdbc.url和jdbc.username的值,实现如下:





public class UserServiceImpl implements UserService {
    //占位符方式
    @Value("${jdbc.url}")
    private String url;
    //SpEL表达方式,其中代表xml配置文件中的id值configProperties
    @Value("#{configProperties['jdbc.username']}")
    private String userName;
​
}

25.Spring 事务实现方式有哪些?

事务就是一系列的操作原子执行。Spring事务机制主要包括声明式事务和编程式事务。

  • 编程式事务:通过编程的方式管理事务,这种方式带来了很大的灵活性,但很难维护。
  • 声明式事务:将事务管理代码从业务方法中分离出来,通过aop进行封装。Spring声明式事务使得我们无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。使用 @Transactional 注解开启声明式事务。

@Transactional相关属性如下:

属性类型描述
valueString可选的限定描述符,指定使用的事务管理器
propagationenum: Propagation可选的事务传播行为设置
isolationenum: Isolation可选的事务隔离级别设置
readOnlyboolean读写或只读事务,默认读写
timeoutint (in seconds granularity)事务超时时间设置
rollbackForClass对象数组,必须继承自Throwable导致事务回滚的异常类数组
rollbackForClassName类名数组,必须继承自Throwable导致事务回滚的异常类名字数组
noRollbackForClass对象数组,必须继承自Throwable不会导致事务回滚的异常类数组
noRollbackForClassName类名数组,必须继承自Throwable不会导致事务回滚的异常类名字数组

26.BeanFactory与FactoryBean的区别

BeanFactory:管理Bean的工厂

BeanFactory是Spring框架中的一个核心接口,用于管理和维护Bean的定义、创建和生命周期。它是Spring IoC(控制反转)容器的基础,负责从配置文件或者注解中读取Bean的定义信息,并根据需要创建相应的Bean实例。BeanFactory的主要职责包括:

解析配置文件,读取Bean的定义信息。
实例化Bean,处理依赖注入。
管理Bean的作用域和生命周期。
以下是一个简单的示例,演示了如何使用BeanFactory创建和管理Bean:

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class MainApp {
    public static void main(String[] args) {
        BeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
        MyBean myBean = (MyBean) factory.getBean("myBean");
        myBean.sayHello();
    }
}

FactoryBean:定制化的Bean创建

与BeanFactory不同,FactoryBean是一个接口,允许开发者创建定制化的Bean创建逻辑。通过实现FactoryBean接口,开发者可以控制Bean的创建过程,从而实现更加灵活和复杂的Bean实例化。FactoryBean的主要特点包括:

定制化:通过FactoryBean,可以创建复杂的Bean实例,实现更加灵活的初始化逻辑。
实现接口:FactoryBean接口包含两个主要方法:getObject()用于返回Bean实例,getObjectType()用于返回Bean的类型。
以下是一个简单的示例,展示了如何使用FactoryBean创建Bean:

import org.springframework.beans.factory.FactoryBean;

public class MyFactoryBean implements FactoryBean<MyBean> {
    @Override
    public MyBean getObject() throws Exception {
        // 实现定制化的Bean创建逻辑
        return new MyBean("Hello from FactoryBean");
    }

    @Override
    public Class<?> getObjectType() {
        return MyBean.class;
    }
}

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        MyBean myBean = (MyBean) context.getBean("myFactoryBean");
        myBean.sayHello();
    }
}

BeanFactory与FactoryBean的区别

虽然BeanFactory和FactoryBean都与Bean的创建和管理有关,但它们在功能和使用上存在显著的区别:

功能不同:BeanFactory负责管理和创建Bean,而FactoryBean是一个接口,允许开发者实现定制化的Bean创建逻辑。
角色不同:BeanFactory是Spring框架的核心,负责整个Bean的管理;而FactoryBean是Bean的创建方式之一,用于定制化的Bean实例化。
使用方式不同:BeanFactory通常通过配置文件或者注解来实现Bean的管理和创建;而FactoryBean需要开发者实现自定义的工厂类,提供定制化的Bean创建逻辑。

总结

通过本文的深入解析,我们了解了BeanFactory和FactoryBean在Spring框架中的作用和区别。BeanFactory负责整个Bean的管理和创建,而FactoryBean允许开发者实现定制化的Bean创建逻辑,从而实现更加灵活和复杂的Bean实例化。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨会停rain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值