当前位置: 首页 > news >正文

spring 面试题

一、Spring 基础概念

  1. 什么是 Spring 框架?
    • Spring 是一个开源的 Java 应用程序框架,它提供了一种轻量级的、非侵入式的方式来构建企业级应用。Spring 的核心功能包括依赖注入(Dependency Injection,DI)、面向切面编程(Aspect - Oriented Programming,AOP)、事务管理、数据访问等,旨在简化企业级 Java 开发,提高开发效率和代码的可维护性。
  2. Spring 框架的核心模块有哪些?
    • 核心容器(Core Container)
      • spring - core:提供了框架的基本核心功能,如 IOC(控制反转)和依赖注入(DI)的基础实现。
      • spring - beans:提供了 BeanFactory,这是 Spring 框架的核心工厂接口,用于管理和配置应用程序中的对象(beans)。
      • spring - context:建立在核心容器之上,提供了一种更高级的应用程序上下文(ApplicationContext),它是 BeanFactory 的子接口,除了具有 BeanFactory 的功能外,还提供了诸如国际化、事件传播、资源加载等附加功能。
      • spring - context - support:提供了对第三方库(如缓存、邮件、调度等)的集成支持。
    • AOP(Aspect - Oriented Programming)
      • spring - aop:提供了面向切面编程的基础架构,允许在运行时将横切关注点(如日志记录、安全检查等)织入到应用程序的核心业务逻辑中。
      • spring - aspectj:对 AspectJ 框架的集成支持,AspectJ 是一种功能强大的 AOP 实现,Spring - aspectj 使得在 Spring 应用中可以使用 AspectJ 的注解和语法进行更灵活的 AOP 编程。
    • 数据访问与集成(Data Access/Integration)
      • spring - jdbc:提供了对 JDBC(Java Database Connectivity)的简化操作,包括数据库连接的获取、SQL 语句的执行、结果集的处理等,减少了编写 JDBC 代码的繁琐。
      • spring - tx:提供了事务管理的抽象层,支持编程式事务和声明式事务,可与多种底层事务管理器(如 JDBC 事务、JTA 事务等)集成。
      • spring - orm:对多种对象 - 关系映射(ORM)框架(如 Hibernate、MyBatis 等)提供集成支持,方便在 Spring 应用中使用 ORM 框架进行数据库操作。
    • Web(Spring Web)
      • spring - web:提供了基础的 Web 开发功能,如 Web 应用上下文、Servlet 集成、文件上传等。
      • spring - webmvc:Spring 的 MVC(Model - View - Controller)框架,用于构建 Web 应用程序,实现了请求处理、视图渲染、模型绑定等功能。
      • spring - webflux:提供了基于反应式编程(Reactive Programming)的 Web 框架,适用于构建高性能、非阻塞的 Web 应用,如处理大量并发请求的微服务。
  3. 解释一下控制反转(IOC)和依赖注入(DI)的概念。
    • 控制反转(Inversion of Control,IOC)
      • 在传统的编程模式中,对象的创建和对象间的依赖关系是由程序代码直接控制的。而在 IOC 模式下,这种控制权被转移到了容器(如 Spring 容器)中。程序代码不再负责对象的创建和依赖关系的维护,而是由容器来负责创建对象,并将它们装配在一起。这就好比在传统模式下,你自己做饭(自己创建和管理对象),而在 IOC 模式下,你去餐馆吃饭(由容器来提供和管理对象)。
    • 依赖注入(Dependency Injection,DI)
      • 依赖注入是实现控制反转的一种具体方式。它是指当一个对象(依赖方)需要依赖于另一个对象(被依赖方)时,由容器在创建依赖方对象时,将被依赖方对象注入到依赖方对象中。依赖注入有三种常见的方式:
      • 构造函数注入(Constructor Injection):通过构造函数将依赖对象传入。例如:
        public class MyService {private MyRepository myRepository;public MyService(MyRepository myRepository) {this.myRepository = myRepository;}
        }

        ** setter 注入(Setter Injection)**:通过 setter 方法将依赖对象传入。例如:

        public class MyService {private MyRepository myRepository;public void setMyRepository(MyRepository myRepository) {this.myRepository = myRepository;}
        }

        字段注入(Field Injection):直接在类的字段上使用注解注入依赖对象,但这种方式会使类与 Spring 框架耦合较紧密,例如:

        public class MyService {@Autowiredprivate MyRepository myRepository;
        }

二、Spring Bean

  1. Spring Bean 的生命周期是怎样的?
    • 实例化(Instantiation)
      • Spring 首先根据配置(如 XML 配置、注解等)确定要创建的 Bean 类型,然后使用 Java 反射机制创建 Bean 的实例。例如,对于一个简单的使用 @Component 注解的类:
        @Component
        public class MyBean {public MyBean() {// 这是构造函数,在实例化时被调用}
        }

        属性赋值(Populate Properties)

      • 在实例化后,Spring 会对 Bean 的属性进行赋值。如果使用了依赖注入,会将依赖的其他 Bean 注入到当前 Bean 中。例如:
        @Component
        public class MyBean {@Autowiredprivate AnotherBean anotherBean;
        }

        • 这里 Spring 会找到 AnotherBean 的实例并注入到 MyBean 的 anotherBean 属性中。
      • 初始化(Initialization)
        • 执行 Bean 的初始化方法。有两种常见的初始化方式:
          • 实现 InitializingBean 接口
            @Component
            public class MyBean implements InitializingBean {@Overridepublic void afterPropertiesSet() throws Exception {// 初始化逻辑}
            }

            使用 @PostConstruct 注解

            @Component
            public class MyBean {@PostConstructpublic void init() {// 初始化逻辑}
            }

                         

  • 使用(In - use)
    • 初始化完成后,Bean 就可以被应用程序使用了,例如被其他组件调用方法等。
  • 销毁(Destruction)
    • 当容器关闭时,会销毁 Bean。如果 Bean 实现了 DisposableBean 接口,会调用其 destroy 方法:
@Component
public class MyBean implements DisposableBean {@Overridepublic void destroy() throws Exception {// 销毁逻辑}
}

或者使用 @PreDestroy 注解来定义销毁方法:

@Component
public class MyBean {@PreDestroypublic void cleanUp() {// 销毁逻辑}
}
  1. 如何配置 Spring Bean?有哪些方式?
    • 基于 XML 配置
      • 在 XML 文件中定义 Bean,例如:

        xml

        <?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="myBean" class="com.example.MyBean"><property name="propertyName" value="propertyValue"/></bean>
        </beans>
        

        这里定义了一个 id 为 myBean 的 Bean,其类是 com.example.MyBean,并设置了一个属性。
    • 基于注解配置
      • 使用 Spring 的注解来标识 Bean 及其配置。常见的注解有:
        • @Component:通用的组件注解,用于标识一个普通的 Spring 组件。例如:

          java

          @Component
          public class MyComponent {// 组件逻辑
          }
          
        • @Service:用于标识业务逻辑层的组件,通常在服务类上使用。例如:

          java

          @Service
          public class MyService {// 服务逻辑
          }
          
        • @Repository:用于标识数据访问层(如数据库操作)的组件,例如:

          java

          @Repository
          public class MyRepository {// 数据访问逻辑
          }
          
        • @Controller:用于标识 Web 应用中的控制器组件,例如在 Spring MVC 中:

          java

          @Controller
          public class MyController {// 控制器逻辑
          }
          
        • @Configuration 和 @Bean:用于 Java 配置类来定义 Bean。例如:

          java

          @Configuration
          public class AppConfig {@Beanpublic MyBean myBean() {return new MyBean();}
          }
          
    • 基于 Java 配置(Java - based configuration)
      • 除了 @Configuration 和 @Bean 的方式外,还可以通过继承特定的抽象类来配置 Spring。例如,继承 WebMvcConfigurerAdapter(在 Spring 5 中已被 WebMvcConfigurer 取代)来配置 Spring MVC:

        java

        @Configuration
        public class WebMvcConfig extends WebMvcConfigurer {// 配置视图解析器等@Overridepublic void configureViewResolvers(ViewResolverRegistry registry) {// 配置逻辑}
        }
        

三、Spring AOP

  1. 什么是面向切面编程(AOP)?Spring AOP 的原理是什么?
    • 面向切面编程(AOP)
      • AOP 是一种编程范式,它允许将横切关注点(如日志记录、安全检查、事务管理等)从应用程序的核心业务逻辑中分离出来,以独立的模块(切面)进行处理。这样可以提高代码的模块化程度和可维护性。例如,在一个没有 AOP 的应用中,如果每个业务方法都需要添加日志记录代码,会导致日志记录代码分散在各个业务方法中,而使用 AOP,可以将日志记录逻辑定义在一个切面中,然后自动织入到需要的业务方法中。
    • Spring AOP 原理
      • Spring AOP 主要基于动态代理(Dynamic Proxy)技术。当一个目标对象(被代理对象)需要被织入切面逻辑时,Spring 会根据目标对象是否实现接口来选择使用 JDK 动态代理或 CGLIB 动态代理。
        • JDK 动态代理
          • 如果目标对象实现了接口,Spring 会使用 JDK 动态代理。JDK 动态代理是通过实现目标对象的接口来创建代理对象的。例如,有一个接口和实现类:

            java

            public interface MyInterface {void doSomething();
            }
            public class MyClass implements MyInterface {@Overridepublic void doSomething() {// 业务逻辑}
            }
            

            Spring 会创建一个实现 MyInterface 的代理对象,在代理对象的 doSomething 方法中,会在调用目标对象的 doSomething 方法前后添加切面逻辑。
        • CGLIB 动态代理
          • 如果目标对象没有实现接口,Spring 会使用 CGLIB(Code Generation Library)动态代理。CGLIB 是通过字节码生成技术来创建目标对象的子类作为代理对象。例如,有一个没有实现接口的类:

            java

            public class MyClass {public void doSomething() {// 业务逻辑}
            }
            

            Spring 会生成一个 MyClass 的子类作为代理对象,在子类的 doSomething 方法中添加切面逻辑。
  2. Spring AOP 中的通知(Advice)有哪些类型?
    • 前置通知(Before Advice)
      • 在目标方法执行之前执行的通知。例如,在一个方法调用前记录日志:

        java

        import org.aspectj.lang.JoinPoint;
        import org.aspectj.lang.annotation.Aspect;
        import org.aspectj.lang.annotation.Before;@Aspect
        public class LoggingAspect {@Before("execution(* com.example.service.MyService.*(..))")public void beforeAdvice(JoinPoint joinPoint) {System.out.println("Before method: " + joinPoint.getSignature().getName());}
        }
        
    • 后置通知(After Advice)
      • 在目标方法执行之后执行的通知。有两种类型:
        • 正常返回后执行的后置通知(After Returning Advice)
          • 当目标方法正常返回时执行。例如:

            java

            import org.aspectj.lang.JoinPoint;
            import org.aspectj.lang.annotation.AfterReturning;
            import org.aspectj.lang.annotation.Aspect;@Aspect
            public class LoggingAspect {@AfterReturning(pointcut = "execution(* com.example.service.MyService.*(..))", returning = "result")public void afterReturningAdvice(JoinPoint joinPoint, Object result) {System.out.println("After returning method: " + joinPoint.getSignature().getName() + ", result: " + result);}
            }
            
        • 无论是否抛出异常都执行的后置通知(After Finally Advice)
          • 这种通知类似于 try - finally 块中的 finally 语句块,无论目标方法是否抛出异常都会执行。例如:

            java

            import org.aspectj.lang.JoinPoint;
            import org.aspectj.lang.annotation.After;
            import org.aspectj.lang.annotation.Aspect;@Aspect
            public class LoggingAspect {@After("execution(* com.example.service.MyService.*(..))")public void afterFinallyAdvice(JoinPoint joinPoint) {System.out.println("After finally method: " + joinPoint.getSignature().getName());}
            }
            
    • 环绕通知(Around Advice)
      • 环绕通知可以在目标方法执行前后都添加逻辑,它可以完全控制目标方法的执行。例如:

        java

        import org.aspectj.lang.ProceedingJoinPoint;
        import org.aspectj.lang.annotation.Around;
        import org.aspectj.lang.annotation.Aspect;@Aspect
        public class LoggingAspect {@Around("execution(* com.example.service.MyService.*(..))")public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {System.out.println("Before method in around advice: " + pjp.getSignature().getName());Object result = pjp.proceed();System.out.println("After method in around advice: " + pjp.getSignature().getName());return result;}
        }
        
    • 异常通知(After Throwing Advice)
      • 当目标方法抛出异常时执行的通知。例如:
        import org.aspectj.lang.JoinPoint;
        import org.aspectj.lang.annotation.AfterThrowing;
        import org.aspectj.lang.annotation.Aspect;@Aspect
        public class LoggingAspect {@AfterThrowing(pointcut = "execution(* com.example.service.MyService.*(..))", throwing = "ex")public void afterThrowingAdvice(JoinPoint joinPoint, Exception ex) {System.out.println("Method: " + joinPoint.getSignature().getName() + " threw exception: " + ex.getMessage());}
        }
        

相关文章:

  • 对于C++中的STL,push_back()和emplace_back()有什么区别?
  • SQL Server连接异常 证书链是由不受信任的颁发机构颁发的
  • 融合AI助力医疗提效,华奥系医务系统助力医院数字化升级!
  • 出现Invalid bound statement (not found)问题的原因可能有哪些
  • 关于PyCharm新版本出现大量空的`jcef_xx.log`文件的解决方法
  • Copilot重磅更新:引用文件夹创建Word文档
  • .NET Core 数据库ORM框架用法简述
  • 在企业微信中,回调地址 redirect_uri 是允许包含端口号
  • Seata客户端@GlobalTransactional核心源码解析
  • 微信小程序中使用 多线程 Worker
  • 自定义实现elementui的锚点
  • StarRocks Lakehouse 如何重构大数据架构?
  • 腾讯云服务器性能提升全栈指南(2025版)
  • 爬虫逆向思维
  • Azure Monitor 实战指南:全方位监控应用与基础设施
  • ubuntu 部署moodle
  • 动态规划降低空间复杂度例题及简化
  • Dockerfile最佳实践:构建高效、安全的容器镜像
  • vue3 打字机效果
  • 【SAM2代码解析】数据集处理3--混合数据加载器(DataLoader)
  • 周劼已任中国航天科技集团有限公司董事、总经理、党组副书记
  • 澎湃回声丨23岁小伙“被精神病”8年续:今日将被移出“重精”管理系统
  • “五一”假期预计全社会跨区域人员流动量超14亿人次
  • 五一小长假,带着小狗去上海音乐厅
  • 浙江官宣:五一假期,没电、没气、没油车辆全部免费拖离高速
  • 哈莉·贝瑞、洪常秀等出任戛纳主竞赛单元评委