【Spring 面试突击 · 03】大厂高频面试题:从IoC容器底层原理到Spring Boot自动配置解析
目录
八、Spring AOP与AspectJ AOP的区别?AOP的实现方式?
一、Spring Boot如何启动Tomcat?
Spring Boot通过嵌入式Servlet容器实现Tomcat的自动启动,核心流程如下:
- 依赖触发:引入
spring-boot-starter-web时,会自动包含spring-boot-starter-tomcat(嵌入式Tomcat依赖)。 - 自动配置:Spring Boot的
EmbeddedServletContainerAutoConfiguration类会检测类路径下的Servlet容器依赖(如Tomcat),并自动配置嵌入式容器。 - 容器初始化:通过
TomcatServletWebServerFactory创建Tomcat实例,设置端口、线程池等参数(默认端口8080,可通过server.port修改)。 - 启动流程:Spring应用上下文刷新完成后,调用
WebServer的start()方法,启动Tomcat服务器,监听HTTP请求。
关键点:Spring Boot的“零配置”特性通过自动配置类和条件注解(如@ConditionalOnClass)实现,避免了传统Spring中繁琐的web.xml配置。
二、Spring Boot配置文件加载顺序
Spring Boot配置文件的加载顺序遵循“后加载的覆盖先加载的”原则,优先级从高到低如下:
- 命令行参数:通过
--key=value传递的参数(如java -jar app.jar --server.port=9090)。 - 环境变量:系统环境变量(如
SERVER_PORT=9090)。 - JVM系统属性:通过
-Dkey=value设置的参数(如-Dserver.port=9090)。 application-{profile}.properties:激活的Profile配置文件(如application-dev.properties)。application.properties:默认配置文件(位于src/main/resources或类路径根目录)。- jar包外的配置文件:与jar包同级目录下的
config文件夹中的配置文件。 - jar包内的配置文件:
src/main/resources/config目录下的配置文件。
注意:若多个配置文件存在相同key,优先级高的配置会覆盖优先级低的配置(例如命令行参数会覆盖application.properties中的配置)。
三、MyBatis的优缺点
优点:
- 学习成本低:基于原生SQL开发,开发者只需编写SQL语句和映射规则,无需学习复杂的ORM映射规则。
- SQL灵活可控:支持动态SQL(如
<if>、<foreach>标签),可根据业务逻辑动态生成SQL,适合复杂查询场景。 - 轻量级:与Spring等框架集成简单,无额外依赖,启动速度快。
- 缓存机制:支持一级缓存(SqlSession级别)和二级缓存(Mapper级别),可提升查询性能。
缺点:
- SQL维护成本高:SQL语句分散在XML或注解中,当表结构变更时,需手动修改所有相关SQL,易遗漏。
- 数据库移植性差:原生SQL通常依赖特定数据库语法(如MySQL的
LIMIT、Oracle的ROWNUM),切换数据库时需重写SQL。 - 对象映射繁琐:需手动配置ResultMap实现数据库字段与Java对象的映射,复杂场景下配置量大。
四、Hibernate与MyBatis的区别
| 对比维度 | Hibernate | MyBatis |
|---|---|---|
| ORM模式 | 全自动ORM框架,通过HQL(Hibernate Query Language)操作数据库,无需编写SQL。 | 半自动ORM框架,需手动编写SQL,通过XML或注解映射数据库字段与Java对象。 |
| 学习成本 | 学习曲线陡峭,需掌握HQL、缓存机制、事务管理等复杂概念。 | 学习成本低,基于原生SQL开发,开发者可快速上手。 |
| SQL灵活性 | SQL由框架自动生成,灵活性差,难以优化复杂查询。 | SQL完全由开发者控制,支持动态SQL,适合复杂业务场景。 |
| 数据库移植性 | 通过HQL屏蔽数据库差异,切换数据库时只需修改方言配置,无需修改代码。 | SQL依赖特定数据库语法,切换数据库时需重写SQL。 |
| 适用场景 | 快速开发、表结构稳定的项目(如CRUD为主的管理系统)。 | 复杂查询、高性能要求的项目(如电商、金融系统)。 |
五、Spring Context模块的理解
Spring Context模块是Spring框架的核心容器,基于BeanFactory构建,提供了更高级的容器功能:
- 应用上下文(ApplicationContext):扩展了
BeanFactory,支持自动装配、国际化、事件发布、资源加载等功能,是Spring应用的核心接口。 - Bean生命周期管理:负责Bean的创建、初始化、依赖注入、销毁等全生命周期管理,支持通过
@PostConstruct、@PreDestroy注解自定义生命周期回调。 - AOP支持:通过
ApplicationContext自动注册AOP代理,实现面向切面编程(如事务管理、日志记录)。 - 事件驱动模型:支持发布-订阅模式,开发者可通过
ApplicationEvent和ApplicationListener实现事件监听。
核心作用:Spring Context模块将Bean的管理从“工厂模式”升级为“容器模式”,通过依赖注入和面向切面编程,降低了组件间的耦合度,提升了应用的可扩展性。
六、什么是Spring依赖注入?
依赖注入(Dependency Injection, DI)是Spring框架实现控制反转(Inversion of Control, IoC)的核心机制,其本质是将对象的依赖关系由容器动态注入,而非由对象自行创建。
依赖注入的三种方式:
- 构造器注入:通过构造方法注入依赖对象,适用于强制依赖(如Service层依赖DAO层)。
@Component public class UserService { private final UserDao userDao; @Autowired public UserService(UserDao userDao) { this.userDao = userDao; } } - Setter注入:通过Setter方法注入依赖对象,适用于可选依赖(如配置类的属性注入)。
@Component public class UserService { private UserDao userDao; @Autowired public void setUserDao(UserDao userDao) { this.userDao = userDao; } } - 字段注入:通过
@Autowired注解直接注入依赖对象,代码简洁但不推荐(破坏了类的封装性,不利于单元测试)。@Component public class UserService { @Autowired private UserDao userDao; }
优点:依赖注入通过解耦组件间的依赖关系,使代码更易测试、维护和扩展,是Spring框架实现“高内聚、低耦合”的核心手段。
七、什么是Spring Bean?
Spring Bean是Spring框架管理的Java对象,由Spring IoC容器负责创建、配置和管理。Bean的定义包含以下核心信息:
- 类信息:Bean对应的Java类(如
UserService.class)。 - 作用域:Bean的生命周期范围,支持
singleton(单例,默认)、prototype(原型)、request、session等。 - 依赖关系:Bean的依赖对象(通过依赖注入实现)。
- 生命周期回调:Bean的初始化方法(如
@PostConstruct)和销毁方法(如@PreDestroy)。
Bean的创建方式:
- 注解驱动:通过
@Component、@Service、@Repository等注解标记类,Spring会自动扫描并注册为Bean。 - XML配置:在
applicationContext.xml中通过<bean>标签定义Bean。 - Java配置:通过
@Configuration和@Bean注解在Java类中定义Bean。
核心作用:Spring Bean是Spring框架实现控制反转和依赖注入的基础,通过容器管理Bean的生命周期和依赖关系,降低了组件间的耦合度。
八、Spring AOP与AspectJ AOP的区别?AOP的实现方式?
Spring AOP与AspectJ AOP的区别:
| 对比维度 | Spring AOP | AspectJ AOP |
|---|---|---|
| 织入时机 | 运行时织入(通过动态代理实现),性能稍低。 | 编译时织入(通过AspectJ编译器)或类加载时织入,性能更高。 |
| 功能范围 | 仅支持方法级别的连接点(如方法执行前后)。 | 支持字段访问、构造器调用、异常处理等更广泛的连接点。 |
| 依赖关系 | 依赖Spring框架,需与Spring容器集成。 | 独立于Spring框架,可单独使用。 |
| 配置方式 | 支持注解(如@Aspect)和XML配置,与Spring生态无缝集成。 | 支持注解和AspectJ特有的语法(如pointcut),配置更灵活。 |
AOP的实现方式:
- JDK动态代理:基于Java反射机制,为目标对象的接口生成代理类,适用于实现了接口的Bean。
- CGLIB代理:基于ASM字节码操作框架,为目标类生成子类代理,适用于未实现接口的Bean。
- AspectJ织入:通过AspectJ编译器或类加载器,在编译时或类加载时将切面逻辑织入目标类,性能最优。
九、Spring通知的类型
Spring AOP的通知(Advice)定义了切面在连接点的执行时机,共有5种类型:
- 前置通知(Before):在目标方法执行前执行,通过
@Before注解定义。@Before("execution(* com.example.service.*.*(..))") public void beforeMethod() { System.out.println("前置通知:方法执行前"); } - 后置通知(After):在目标方法执行后执行(无论方法是否抛出异常),通过
@After注解定义。 - 返回通知(AfterReturning):在目标方法正常返回后执行,可通过
returning属性获取返回值,通过@AfterReturning注解定义。@AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result") public void afterReturning(Object result) { System.out.println("返回通知:方法返回值为" + result); } - 异常通知(AfterThrowing):在目标方法抛出异常后执行,可通过
throwing属性获取异常信息,通过@AfterThrowing注解定义。 - 环绕通知(Around):在目标方法执行前后都执行,可通过
ProceedingJoinPoint控制目标方法的执行,是最强大的通知类型,通过@Around注解定义。@Around("execution(* com.example.service.*.*(..))") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("环绕通知:方法执行前"); Object result = joinPoint.proceed(); // 执行目标方法 System.out.println("环绕通知:方法执行后"); return result; }
十、Spring AOP中关注点与横切关注点的区别
关注点(Concern):指应用中需要实现的核心业务逻辑(如用户注册、订单支付),是应用的主要功能模块。
横切关注点(Cross-cutting Concern):指贯穿多个业务模块的通用功能(如日志记录、事务管理、安全控制),这些功能与核心业务逻辑无关,但又需要在多个模块中重复实现。
区别:
- 范围不同:关注点是业务功能(如“用户注册”),横切关注点是通用功能(如“日志记录”)。
- 耦合度不同:关注点通常与业务模块高度耦合,横切关注点通过AOP技术与业务模块解耦,实现“模块化”管理。
- 实现方式不同:关注点通过业务类实现,横切关注点通过切面(Aspect)实现,避免了代码重复和耦合。
示例:在电商系统中,“下单”是关注点(核心业务),而“事务管理”是横切关注点(贯穿下单、支付、库存等多个模块),通过AOP将事务管理与业务逻辑解耦,提升了代码的可维护性。
更多推荐

所有评论(0)