目录

一、Spring Boot如何启动Tomcat?

二、Spring Boot配置文件加载顺序

三、MyBatis的优缺点

四、Hibernate与MyBatis的区别

五、Spring Context模块的理解

六、什么是Spring依赖注入?

七、什么是Spring Bean?

八、Spring AOP与AspectJ AOP的区别?AOP的实现方式?

九、Spring通知的类型

十、Spring AOP中关注点与横切关注点的区别


一、Spring Boot如何启动Tomcat?

Spring Boot通过嵌入式Servlet容器实现Tomcat的自动启动,核心流程如下:

  1. 依赖触发:引入spring-boot-starter-web时,会自动包含spring-boot-starter-tomcat(嵌入式Tomcat依赖)。
  2. 自动配置:Spring Boot的EmbeddedServletContainerAutoConfiguration类会检测类路径下的Servlet容器依赖(如Tomcat),并自动配置嵌入式容器。
  3. 容器初始化:通过TomcatServletWebServerFactory创建Tomcat实例,设置端口、线程池等参数(默认端口8080,可通过server.port修改)。
  4. 启动流程:Spring应用上下文刷新完成后,调用WebServer的start()方法,启动Tomcat服务器,监听HTTP请求。

关键点:Spring Boot的“零配置”特性通过自动配置类和条件注解(如@ConditionalOnClass)实现,避免了传统Spring中繁琐的web.xml配置。

二、Spring Boot配置文件加载顺序

Spring Boot配置文件的加载顺序遵循“后加载的覆盖先加载的”原则,优先级从高到低如下:

  1. 命令行参数:通过--key=value传递的参数(如java -jar app.jar --server.port=9090)。
  2. 环境变量:系统环境变量(如SERVER_PORT=9090)。
  3. JVM系统属性:通过-Dkey=value设置的参数(如-Dserver.port=9090)。
  4. application-{profile}.properties:激活的Profile配置文件(如application-dev.properties)。
  5. application.properties:默认配置文件(位于src/main/resources或类路径根目录)。
  6. jar包外的配置文件:与jar包同级目录下的config文件夹中的配置文件。
  7. jar包内的配置文件:src/main/resources/config目录下的配置文件。

注意:若多个配置文件存在相同key,优先级高的配置会覆盖优先级低的配置(例如命令行参数会覆盖application.properties中的配置)。

三、MyBatis的优缺点

优点:

  1. 学习成本低:基于原生SQL开发,开发者只需编写SQL语句和映射规则,无需学习复杂的ORM映射规则。
  2. SQL灵活可控:支持动态SQL(如<if>、<foreach>标签),可根据业务逻辑动态生成SQL,适合复杂查询场景。
  3. 轻量级:与Spring等框架集成简单,无额外依赖,启动速度快。
  4. 缓存机制:支持一级缓存(SqlSession级别)和二级缓存(Mapper级别),可提升查询性能。

缺点:

  1. SQL维护成本高:SQL语句分散在XML或注解中,当表结构变更时,需手动修改所有相关SQL,易遗漏。
  2. 数据库移植性差:原生SQL通常依赖特定数据库语法(如MySQL的LIMIT、Oracle的ROWNUM),切换数据库时需重写SQL。
  3. 对象映射繁琐:需手动配置ResultMap实现数据库字段与Java对象的映射,复杂场景下配置量大。
四、Hibernate与MyBatis的区别
对比维度HibernateMyBatis
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构建,提供了更高级的容器功能:

  1. 应用上下文(ApplicationContext):扩展了BeanFactory,支持自动装配、国际化、事件发布、资源加载等功能,是Spring应用的核心接口。
  2. Bean生命周期管理:负责Bean的创建、初始化、依赖注入、销毁等全生命周期管理,支持通过@PostConstruct、@PreDestroy注解自定义生命周期回调。
  3. AOP支持:通过ApplicationContext自动注册AOP代理,实现面向切面编程(如事务管理、日志记录)。
  4. 事件驱动模型:支持发布-订阅模式,开发者可通过ApplicationEvent和ApplicationListener实现事件监听。

核心作用:Spring Context模块将Bean的管理从“工厂模式”升级为“容器模式”,通过依赖注入和面向切面编程,降低了组件间的耦合度,提升了应用的可扩展性。

六、什么是Spring依赖注入?

依赖注入(Dependency Injection, DI)是Spring框架实现控制反转(Inversion of Control, IoC)的核心机制,其本质是将对象的依赖关系由容器动态注入,而非由对象自行创建。

依赖注入的三种方式:

  1. 构造器注入:通过构造方法注入依赖对象,适用于强制依赖(如Service层依赖DAO层)。
    @Component
    public class UserService {
        private final UserDao userDao;
        @Autowired
        public UserService(UserDao userDao) {
            this.userDao = userDao;
        }
    }
  2. Setter注入:通过Setter方法注入依赖对象,适用于可选依赖(如配置类的属性注入)。
    @Component
    public class UserService {
        private UserDao userDao;
        @Autowired
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    }
  3. 字段注入:通过@Autowired注解直接注入依赖对象,代码简洁但不推荐(破坏了类的封装性,不利于单元测试)。
    @Component
    public class UserService {
        @Autowired
        private UserDao userDao;
    }

优点:依赖注入通过解耦组件间的依赖关系,使代码更易测试、维护和扩展,是Spring框架实现“高内聚、低耦合”的核心手段。

七、什么是Spring Bean?

Spring Bean是Spring框架管理的Java对象,由Spring IoC容器负责创建、配置和管理。Bean的定义包含以下核心信息:

  1. 类信息:Bean对应的Java类(如UserService.class)。
  2. 作用域:Bean的生命周期范围,支持singleton(单例,默认)、prototype(原型)、request、session等。
  3. 依赖关系:Bean的依赖对象(通过依赖注入实现)。
  4. 生命周期回调:Bean的初始化方法(如@PostConstruct)和销毁方法(如@PreDestroy)。

Bean的创建方式:

  1. 注解驱动:通过@Component、@Service、@Repository等注解标记类,Spring会自动扫描并注册为Bean。
  2. XML配置:在applicationContext.xml中通过<bean>标签定义Bean。
  3. Java配置:通过@Configuration和@Bean注解在Java类中定义Bean。

核心作用:Spring Bean是Spring框架实现控制反转和依赖注入的基础,通过容器管理Bean的生命周期和依赖关系,降低了组件间的耦合度。

八、Spring AOP与AspectJ AOP的区别?AOP的实现方式?

Spring AOP与AspectJ AOP的区别:

对比维度Spring AOPAspectJ AOP
织入时机运行时织入(通过动态代理实现),性能稍低。编译时织入(通过AspectJ编译器)或类加载时织入,性能更高。
功能范围仅支持方法级别的连接点(如方法执行前后)。支持字段访问、构造器调用、异常处理等更广泛的连接点。
依赖关系依赖Spring框架,需与Spring容器集成。独立于Spring框架,可单独使用。
配置方式支持注解(如@Aspect)和XML配置,与Spring生态无缝集成。支持注解和AspectJ特有的语法(如pointcut),配置更灵活。

AOP的实现方式:

  1. JDK动态代理:基于Java反射机制,为目标对象的接口生成代理类,适用于实现了接口的Bean。
  2. CGLIB代理:基于ASM字节码操作框架,为目标类生成子类代理,适用于未实现接口的Bean。
  3. AspectJ织入:通过AspectJ编译器或类加载器,在编译时或类加载时将切面逻辑织入目标类,性能最优。
九、Spring通知的类型

Spring AOP的通知(Advice)定义了切面在连接点的执行时机,共有5种类型:

  1. 前置通知(Before):在目标方法执行前执行,通过@Before注解定义。
    @Before("execution(* com.example.service.*.*(..))")
    public void beforeMethod() {
        System.out.println("前置通知:方法执行前");
    }
  2. 后置通知(After):在目标方法执行后执行(无论方法是否抛出异常),通过@After注解定义。
  3. 返回通知(AfterReturning):在目标方法正常返回后执行,可通过returning属性获取返回值,通过@AfterReturning注解定义。
    @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
    public void afterReturning(Object result) {
        System.out.println("返回通知:方法返回值为" + result);
    }
  4. 异常通知(AfterThrowing):在目标方法抛出异常后执行,可通过throwing属性获取异常信息,通过@AfterThrowing注解定义。
  5. 环绕通知(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):指贯穿多个业务模块的通用功能(如日志记录、事务管理、安全控制),这些功能与核心业务逻辑无关,但又需要在多个模块中重复实现。

区别:

  1. 范围不同:关注点是业务功能(如“用户注册”),横切关注点是通用功能(如“日志记录”)。
  2. 耦合度不同:关注点通常与业务模块高度耦合,横切关注点通过AOP技术与业务模块解耦,实现“模块化”管理。
  3. 实现方式不同:关注点通过业务类实现,横切关注点通过切面(Aspect)实现,避免了代码重复和耦合。

示例:在电商系统中,“下单”是关注点(核心业务),而“事务管理”是横切关注点(贯穿下单、支付、库存等多个模块),通过AOP将事务管理与业务逻辑解耦,提升了代码的可维护性。

更多推荐