Spring面试总结,基于小林coding+个人总结

Spring面试总结

讲一下你对spring的理解

Spring 是一个轻量级的 Java 开发框架,它通过控制反转(IoC)和面向切面编程(AOP)等核心技术,为企业级应用提供了全面的解决方案。它整合了事务管理、Web 开发、数据访问等功能模块,具有模块化、非侵入性等特点。

核心特性:
  • 控制反转与依赖注入:IoC,将对象的创建和依赖关系的管理从代码中移除,转由 Spring 容器负责。DI:IoC 的具体实现方式,通过构造器、Setter 方法或字段注入,将依赖对象传递给目标对象。

  • 面向切面编程:Spring AOP 通过代理或字节码增强技术,将日志、事务等横切关注点模块化,定义切面(Aspect)、通知(Advice)、切入点(Pointcut)等概念,在不修改原有业务逻辑的前提下增强功能,实现了业务代码与系统服务的解耦,提升了代码的复用性和可维护性。

  • MVC分层框架:MVC 分层框架将应用分为 Model(数据与业务)、View(界面展示)、Controller(逻辑调度)三层,通过职责分离提升代码复用性与可维护性,广泛应用于 Spring MVC 等框架,是企业级开发的经典架构模式。

  • 事务管理:Spring 提供声明式事务管理,通过 @Transactional 注解和 AOP 机制,在方法层面定义事务边界,支持传播行为(如 REQUIRED)和隔离级别配置,确保数据操作的原子性和一致性,使事务管理代码与业务逻辑分离,简化了企业级应用的数据持久化操作。

    • 传播行为

      传播行为英文原名核心特性典型使用场景
      REQUIRED必须参与事务若无事务则新建,有则加入核心业务操作(如订单创建、资金转账)
      SUPPORTS支持事务存在事务时加入,否则非事务执行只读查询操作(提升性能)
      MANDATORY强制事务必须在已有事务中执行,无则抛异常依赖事务上下文的底层操作
      REQUIRES_NEW新建事务挂起当前事务,新建独立事务执行异步任务 / 日志记录(避免主事务影响)
      NOT_SUPPORTED不支持事务挂起当前事务,以非事务方式执行缓存更新 / 非关键数据操作
      NEVER禁止事务若存在事务则抛异常纯计算逻辑(无数据持久化需求)
      NESTED嵌套事务基于保存点实现子事务,外层回滚影响内层,内层回滚不影响外层分阶段操作(如支付前库存校验)
    • 隔离级别

      隔离级别脏读允许不可重复读允许幻读允许数据库默认场景性能消耗
      READ_UNCOMMITTED极少使用(数据一致性要求极低)最低
      READ_COMMITTEDOracle 默认级别(读多写少场景)较低
      REPEATABLE_READMySQL 默认级别(默认推荐)中等
      SERIALIZABLE金融 / 交易场景(强一致性要求)最高
      DEFAULT由数据库决定由数据库决定由数据库决定MySQL→REPEATABLE_READ Oracle→READ_COMMITTED依赖数据库
Spring的核心思想说说你的理解
概念核心思想解决的问题实现方式典型应用场景
IoC控制反转:将对象的创建和依赖关系的管理从代码转移到容器,由容器控制对象生命周期。传统代码中对象硬编码依赖导致的耦合度高、可测试性差问题。依赖查找(DL)、依赖注入(DI)。Spring 容器通过ApplicationContext管理 Bean 的生命周期。
DI依赖注入:IoC 的具体实现方式,通过构造器、Setter 或字段注入依赖对象。组件间依赖关系的手动管理繁琐,且依赖具体实现而非接口。构造器注入、Setter 注入、注解注入(如@Autowired)。服务层注入数据访问层组件:public UserService(UserRepository userRepository) {...}
AOP面向切面编程:将横切关注点(如日志、事务)模块化,通过代理或字节码增强织入目标代码。业务逻辑与系统服务(如日志、安全)耦合导致代码冗余、可维护性差。静态代理(编译时增强)、动态代理(运行时增强,如 JDK 动态代理、CGLIB)、字节码编织(如 AspectJ)、切面配置。统一日志记录、事务管理、权限校验等。
Spring IoC和AOP 介绍一下

Spring IoC 的核心是将对象的创建与依赖管理从程序代码中剥离,交由容器统一管控。开发者无需手动 new 对象,只需通过注解或配置描述依赖关系,容器会在运行时自动构建对象图并注入依赖。这种方式实现了对象间的松耦合,使代码更易测试和维护,例如服务层可直接通过@Autowired获取 DAO 实例,而无需关心其具体创建过程,是 Spring 框架简化开发的基础机制。

Spring AOP 通过分离 “业务逻辑” 与 “横切关注点”(如日志、事务),将重复逻辑封装为独立切面,利用动态代理、CGLIB代理等技术在运行时将切面逻辑织入目标方法。开发者通过@Aspect定义切面,用@Pointcut指定作用范围,@Before/@After等注解控制逻辑执行时机,避免在业务代码中硬编码重复逻辑。例如在服务方法调用前后自动记录日志,既保证业务代码纯净,又实现了逻辑复用,是提升代码可维护性的关键技术。

  • JDK动态代理和CGLIB代理讲一下

    • JDK动态代理

      JDK 动态代理是 Java 原生提供的基于接口的代理机制,通过java.lang.reflect.ProxyInvocationHandler在运行时动态生成代理类字节码。代理对象实现与目标对象相同的接口,方法调用通过反射转发至InvocationHandler处理,从而实现对目标方法的增强。其优势在于无需额外依赖、符合面向接口编程原则,是 Spring AOP 的默认选择(当目标对象实现接口时),但只能代理接口方法,无法处理未实现接口的类。

      具体执行流程:代理对象的方法调用会先跳转至InvocationHandlerinvoke方法,再通过反射调用目标对象的实际方法

    • CGLIB代理

      CGLIB 是基于继承的代理机制,通过 ASM 字节码库在运行时生成目标类的子类作为代理。代理类重写父类方法,并在调用时通过MethodInterceptor拦截,直接调用父类方法而非反射,因此性能略高。CGLIB 无需目标类实现接口,可代理未实现接口的类,但无法代理final类或方法,适用于 Spring AOP 中未实现接口的 Bean(如 Controller),是 JDK 动态代理的补充方案。

      具体执行流程: 代理对象的方法调用会先进入MethodInterceptorintercept方法,再通过MethodProxy.invokeSuper直接调用目标类的原始方法

Spring的aop介绍一下

概念以及思想在前几点已总结

  • 核心术语详解:
术语定义示例
切面(Aspect)封装横切逻辑的类,包含切点和通知的定义。@Aspect 注解标注的类,如 LogAspect
切点(Pointcut)定义横切逻辑作用的目标方法,通过表达式匹配方法签名。切点是连接点的一部分。execution(* com.service.*Service.*(..)) 匹配所有 Service 类的方法。
通知(Advice)横切逻辑的具体实现,分为 5 种类型,定义何时、如何增强目标方法。@Before 前置通知:在目标方法前执行日志记录。
连接点(Joinpoint)程序执行过程中的特定点(如方法调用、异常抛出),Spring AOP 仅支持方法调用。调用 UserService.save() 方法时的连接点。
目标对象(Target Object)被代理的原始对象,即被增强的业务对象。UserService 实例。
AOP 代理(Proxy)由 Spring 生成的代理对象,用于拦截方法调用并应用切面逻辑。通过 JDK 或 CGLIB 生成的代理对象,如 UserServiceProxy
  • 通知类型

    • @Before(前置通知):目标方法执行调用。
    • @After(后置通知):目标方法正常执行完毕后调用(无论是否有返回值)。
    • @AfterReturning(返回后通知):目标方法成功返回后调用,可获取返回值。
    • @AfterThrowing(异常通知):目标方法抛出异常后调用,可获取异常信息。
    • @Around(环绕通知):包裹目标方法,可在方法前后执行逻辑,甚至控制方法是否执行(最强大的通知类型)。
  • 通知类型执行顺序

    • 无异常:
      1. 环绕通知前置逻辑
      2. 前置通知(@Before)
      3. 目标方法执行
      4. 后置通知(@After)
      5. 返回通知(@AfterReturning,仅在目标方法正常返回时执行)
      6. 环绕通知后置逻辑
    • 抛出异常:
      1. 环绕通知前置逻辑
      2. 前置通知
      3. 目标方法执行(抛出异常)
      4. 异常通知(@AfterThrowing,替代返回通知执行)
      5. 后置通知(@After,无论是否异常都会执行)
      6. 环绕通知后置逻辑(若异常未被 @Around 捕获,可能不执行)
IOC和AOP是通过什么机制来实现的?
  • Ioc核心实现技术

    • 反射:Spring IOC容器利用Java的反射机制动态地加载类、创建对象实例及调用对象方法,反射允许在运行时检查类、方法、属性等信息,从而实现灵活的对象实例化和管理。
    • 依赖注入:IOC的核心概念是依赖注入,即容器负责管理应用程序组件之间的依赖关系。Spring通过构造函数注入、属性注入或方法注入,将组件之间的依赖关系描述在配置文件中或使用注解。
    • 工厂模式:Spring IOC容器通常采用工厂模式来管理对象的创建和生命周期。容器作为工厂负责实例化Bean并管理它们的生命周期,将Bean的实例化过程交给容器来管理。
    • 容器实现:Spring IOC容器是实现IOC的核心,通常使用BeanFactory或ApplicationContext来管理Bean。BeanFactory是IOC容器的基本形式,提供基本的IOC功能;ApplicationContext是BeanFactory的扩展,并提供更多企业级功能。
  • AOP核心实现技术

    Spring AOP的实现依赖于动态代理技术。动态代理是在运行时动态生成代理对象,而不是在编译时。它允
    许开发者在运行时指定要代理的接口和行为,从而实现在不修改源码的情况下增强方法的功能。

    Spring AOP支持两种动态代理:
    基于JDK的动态代理:使用java.lang.reflect.Proxy类和java.lang.reflect…InvocationHandler接口实现。这
    种方式需要代理的类实现一个或多个接口。
    **基于CGLIB的动态代理:**当被代理的类没有实现接口时,Spring会使用CGLIB.库生成一个被代理类的子
    类作为代理。CGLIB(Code Generation Library)是一个第三方代码生成库,通过继承方式实现代理。

依赖倒置,依赖注入,控制反转分别是什么?
  • 依赖倒置:依赖倒置是一种设计原则,要求程序设计中通过抽象(接口 / 抽象类)建立依赖关系,而非直接依赖具体实现类。例如,高层业务模块(如服务层)不直接调用低层数据访问模块(如 DAO)的具体实现,而是通过接口交互,使高层与低层解耦,便于代码扩展与维护,符合 “面向接口编程” 的理念。
  • 依赖注入:依赖注入是控制反转(IOC)的具体实现方式,指在创建对象时,通过构造器、setter 方法或字段注解等方式,将其依赖的其他对象由外部(如容器)传入,而非由对象自己创建。例如,Spring 中UserService若依赖UserRepository,无需在UserService中手动 newUserRepository,而是通过@Autowired让容器将UserRepository实例注入,实现对象间依赖关系的解耦。
  • 控制反转:控制反转是一种设计理念,指传统开发中对象的创建与依赖管理由程序代码自身控制,而 IOC 模式下,控制权 “反转” 给容器(如 Spring 容器):容器根据配置自动创建对象、注入依赖并管理其生命周期,应用代码只需从容器获取对象即可。例如,开发者无需手动管理 Bean 的创建,而是通过@Component等注解让容器负责,体现了 “被动接受控制” 的反转逻辑,最终降低代码耦合度。
怎么实现依赖注入?
  • 构造器注入:保证对象初始化时依赖已就绪

    // 构造器注入示例
    class UserService {
        private final UserDao userDao;
        
        // 通过构造器接收依赖对象(final修饰确保不可变)
        public UserService(UserDao userDao) {
            this.userDao = userDao;
        }
    }
    
  • Setter注入:灵活性高,但依赖可能未完全初始化

    class UserService {
        private UserDao userDao;
        
        // 通过setter方法注入依赖(非必需时可设为null)
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    }
    
  • 字段注入:代码简洁但隐藏依赖关系,不推荐生产代码

    // 字段注入示例(以Spring框架为例)
    class UserService {
        @Autowired // Spring注解实现字段注入
        private UserDao userDao; // 直接声明依赖字段
    }
    
动态代理和静态代理的区别

动态代理与静态代理的核心区别在于代理类的创建时机和灵活性:静态代理在编译期手动编写代理类,需与目标类实现相同接口或继承目标类,每个目标类对应独立代理类,扩展性较差;动态代理则在运行时通过反射(如 JDK 代理)或字节码生成技术(如 CGLIB)动态生成代理类,无需手动编写,可通过统一处理器处理多个目标类,适用于 AOP 等需要灵活增强的场景,相比静态代理更具扩展性与无侵入性。

spring是如何解决循环依赖的?
  1. 循环依赖在spring中有三种情况:

    第一种:通过构造方法进行依赖注入时产生的循环依赖问题。
    第二种:通过setter方法进行依赖注入且是在多例(原型)模式下产生的循环依赖问题。
    第三种:通过setter方法进行依赖注入且是在单例模式下产生的循环依赖问题

  • 只有第三种被解决了,详细方案步骤如下:

    以 A→B→A 循环为例的详细流程

    步骤 1:创建 A(暴露工厂到二级缓存)

    1. 实例化 A(半成品,未填充依赖)
    2.AObjectFactory 放入二级缓存:
       singletonFactories.put("a", () -> getEarlyBeanReference("a", mbd, a));
    3. 开始填充 A 的依赖(发现需要 B

步骤 2:创建 B(触发对 A 的循环依赖)

4. 实例化 B(半成品)
5.BObjectFactory 放入二级缓存
6. 开始填充 B 的依赖(发现需要 A7. 调用 getSingleton("a") 查找 A- 一级缓存无 A
   - 三级缓存无 A(早期引用尚未生成)
   - 二级缓存有 AObjectFactory → 调用工厂生成早期引用 earlyA
   - 将 earlyA 放入三级缓存 earlySingletonObjects
   - 从二级缓存移除 AObjectFactory
8. 将 earlyA 注入 B
9. 完成 B 的初始化,将 B 放入一级缓存

步骤 3:继续完成 A 的初始化

10. B 已在一级缓存,将 B 注入 A
11. 完成 A 的初始化
12.A 从三级缓存移至一级缓存
spring三级缓存的数据结构是什么?
  • 一级缓存(Singleton Objects):这是一个Map类型的缓存,存储的是已经完全初始化好的bean,即完全准备好可以使用的bean实例。键是bean的名称,值是bean的实例。这个缓存在DefaultSingletonBeanRegistry类中的singletonObjects属性中。
  • 二级缓存(Early Singleton Objects):这同样是一个Map类型的缓存,存储的是早期的bean引用,即已经实例化但还未完全初始化的bean。这些bean已经被实例化,但是可能还没有进行属性注入等操作。这个缓存在DefaultSingletonBeanRegistry类中的earlySingletonObjects属性中。
  • 三级缓存(Singleton Factories):这也是一个Map类型的缓存,存储的是ObjectFactory对象,这些对象可以生成早期的bean引用。当一个bean正在创建过程中,如果它被其他bean依赖,那么这个正在创建的bean就会通过这个ObjectFactory来创建一个早期引用,从而解决循环依赖的问题。这个缓存在DefaultSingletonBeanRegistry类中的singletonFactories属性中。
spring框架中都用到了哪些设计模式
  • 工厂设计模式:Spring使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。
  • 代理设计模式:Spring AOP 功能的实现。
  • 单例设计模式:Spring 中的 Bean 默认都是单例的。
  • 模板设计模式:Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。
  • 包装器设计模式:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
  • 观察者模式:Spring 事件驱动模型就是观察者模式很经典的一个应用。
  • 适配器模式:Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller。
spring 核心容器常用注解有什么
注解作用示例场景
@Component声明一个组件(Bean),自动被组件扫描发现通用组件类
@Repository声明数据访问层组件(DAO),提供持久层异常转换数据库访问类
@Service声明业务逻辑层组件(Service)业务处理类
@Controller声明 Web 控制器组件(MVC)Spring MVC 控制器
@RestController@Controller + @ResponseBody 的组合,返回 JSON 数据RESTful API 接口
@Configuration声明配置类,替代 XML 配置文件替代 applicationContext.xml
@Bean在配置类中声明一个 Bean,替代 XML 中的<bean>标签自定义 Bean 创建逻辑
@Autowired自动注入依赖(按类型匹配)字段、构造器、setter 方法
@Qualifier配合@Autowired,按名称指定注入的 Bean解决多实现类的歧义
@ResourceJSR-250 标准注解,按名称注入依赖(等价于@Autowired+@Qualifier替代@Autowired
@Value注入外部配置属性(如application.properties中的值)配置文件参数注入
@Scope指定 Bean 的作用域(如singletonprototype多例 Bean 配置
@Lazy延迟初始化 Bean(仅在首次使用时创建)资源消耗大的 Bean
Spring的事务什么情况下会失效?
  • 同一个类中方法内部调用:

    场景:在类的内部使用this.调用被@Transactional注解的方法。
    原因:Spring 事务基于 AOP 代理实现,必须通过代理对象调用方法才能触发事务拦截。若使用this.直接调用(如this.method()),会绕过代理对象,导致事务不生效。

    @Service
    public class UserService {
        public void saveUser() {
            this.saveUserWithTransaction(); // 内部调用绕过代理,事务失效
        }
        
        @Transactional
        public void saveUserWithTransaction() {
            // 数据库操作
        }
    }
    
  • 事务在非公开方法中失效:

    场景@Transactional注解应用在非public修饰的方法上(如默认访问修饰符、private)。
    原因:Spring 框架的设计限制 —— 源码中会跳过非public方法的事务拦截(TransactionAttributeSource接口明确要求仅处理public方法)。

    @Service
    public class OrderService {
        @Transactional
        void updateOrder() { // 非public方法,事务不生效
            // 数据库操作
        }
    }
    
  • 事务传播属性设置不当:

    场景@Transactionalpropagation属性配置错误,导致方法脱离事务管理。
    原因:不同传播属性决定了事务的行为,例如:

    • Propagation.NOT_SUPPORTED:挂起当前事务,在非事务环境中执行;
    • Propagation.NEVER:禁止事务,若存在事务则抛出异常。
    @Service
    public class AccountService {
        @Transactional(propagation = Propagation.NOT_SUPPORTED)
        public void transferMoney() {
            // 即使调用方有事务,当前方法也会在非事务环境中执行
        }
    }
    
  • 异常类型不匹配:

    场景:未正确处理异常类型,导致事务无法回滚(需注意:此场景可能被误认为 “事务失效”,但实际事务已生效,只是未触发回滚)。
    原因

    • 默认情况下,Spring 仅回滚RuntimeExceptionError类型的异常;
    • 若捕获异常后未重新抛出,或抛出的是检查异常(如Exception),事务会正常提交。
    @Service
    public class TransactionService {
        @Transactional
        public void process() {
            try {
                // 数据库操作
                throw new Exception("自定义检查异常"); // 非RuntimeException,默认不回滚
            } catch (Exception e) {
                // 捕获异常且不抛出,事务正常提交
            }
        }
    }
    
  • 多数据源场景下事务管理器错误:

    场景:在多数据源环境中,不同数据源的操作未被同一事务管理器管理。
    原因:单数据源时事务管理器自动生效,但多数据源需手动指定transactionManager。若未配置,跨数据源操作无法统一回滚(属于分布式事务问题)。

Spring的事务,使用this调用是否生效?

在 Spring 中使用this调用事务方法时,事务会失效。这是因为 Spring 事务基于 AOP 代理实现,而this引用指向的是目标对象本身,而非代理对象,导致 AOP 拦截器无法介入。

Bean的生命周期说一下?
  1. 实例化(Instantiation)
    通过构造器或工厂方法创建 Bean 实例。
  2. 属性注入(Population)
    填充 Bean 的依赖和属性(如@Autowired)。
  3. Aware 接口回调
    • BeanNameAware.setBeanName():注入 Bean 名称。
    • BeanFactoryAware.setBeanFactory():注入 BeanFactory。
    • ApplicationContextAware.setApplicationContext():注入应用上下文。
  4. BeanPostProcessor 前置处理
    所有BeanPostProcessor.postProcessBeforeInitialization()方法被调用(全局处理)。
  5. 初始化方法调用
    • InitializingBean.afterPropertiesSet()
    • @PostConstruct注解方法
    • 或 XML 配置的init-method
  6. BeanPostProcessor 后置处理
    所有BeanPostProcessor.postProcessAfterInitialization()方法被调用(全局处理)。
  7. Bean 就绪可用
    Bean 可被应用程序使用。
  8. 销毁阶段
    • 容器关闭时,调用DisposableBean.destroy()
    • @PreDestroy注解方法
    • 或 XML 配置的destroy-method
  • 初始化方法顺序

    BeanPostProcessor.postProcessBeforeInitialization(全局前置)→ @PostConstructInitializingBeaninit-method(优先级从高到低)→ BeanPostProcessor.postProcessAfterInitialization(全局后置)。

  • 销毁方法顺序

    @PreDestroyDisposableBeandestroy-method(优先级从高到低)。

Bean是否单例?

Spring 中的 Bean 默认都是单例的。每个Bean的实例只会被创建一次,并且会被存储在Spring容器的缓存中,以便在后续的请求中重复使用。这种单例模式可以提高应用程序的性能和内存效率。但是,Spring也支持将Bean设置为多例模式,即每次请求都会创建一个新的Bean实例。要将Bean设置为多例模式,可以在Bean定义中通过设置scope属性为"prototype"来实现。

Bean的单例和非单例,生命周期是否一样?
生命周期阶段单例(Singleton)原型(Prototype)
实例创建时机容器启动时(默认)或第一次被请求时(懒加载模式)创建唯一实例。每次被请求时(如getBean()调用或注入时)创建新实例。
实例数量整个容器中仅存在 1 个实例,所有引用指向同一对象。每次请求对应 1 个新实例,多次请求生成多个独立对象。
属性注入与初始化容器负责完成属性注入(如@Autowired)、BeanNameAware等接口回调、@PostConstruct初始化方法等,仅执行一次。容器同样负责属性注入和初始化操作,但每次创建新实例时都会重新执行(每次实例独立处理)。
容器管理范围从创建到销毁全程由容器管理,生命周期与容器绑定。容器仅负责创建和初始化,后续生命周期(如销毁)不由容器管理,需用户自行处理。
销毁阶段容器关闭时触发销毁逻辑(如DisposableBean接口的destroy()@PreDestroy方法)。容器不触发销毁逻辑,即使实现DisposableBean或配置destroy-method也不会执行。
与容器的生命周期绑定完全绑定:容器启动则创建,容器关闭则销毁。不绑定:实例创建后与容器脱离关系,容器关闭不影响已创建的原型实例。
适用场景无状态组件(如 Service、Repository),复用实例以减少资源消耗。有状态组件(如保存请求上下文的对象),避免多线程共享状态导致的安全问题。
Spring bean的作用域有哪些?
作用域生命周期管理实例数量线程安全性典型应用场景
Singleton容器管理(创建与销毁)每个容器 1 个实例需手动处理共享状态无状态服务、工具类
Prototype用户管理(仅创建)每次请求 1 个新实例天然安全(不共享)有状态组件、非线程安全对象
RequestHTTP 请求生命周期每个请求 1 个实例单线程环境请求参数处理器、请求级缓存
SessionHTTP 会话生命周期每个会话 1 个实例会话内单线程购物车、用户会话状态
ApplicationServletContext 生命周期每个应用 1 个实例需线程安全全局配置、应用级统计
WebSocketWebSocket 会话生命周期每个 WebSocket 会话 1 个实例会话内单线程WebSocket 消息处理器
在Spring中,在bean加载/销毁前后,如果想实现某些逻辑,可以怎么做?
  • 使用init-method和destroy-method
  • 实现InitializingBean和DisposableBean接口,然后分别实现afterPropertiesSet和destroy方法。
  • 使用@PostConstruct和@PreDestroy注解
  • 使用@Bean注解的initMethod和destroyMethod属性
  • 使用BeanPostProcessor(全局拦截),实现BeanPostProcessor接口,重写postProcessBeforeInitialization(初始化前)和postProcessAfterInitialization(初始化后)
Spring给我们提供了很多扩展点,这些有了解吗?
一、Bean 生命周期扩展点
  1. BeanPostProcessor
    允许在 Bean 初始化前后插入自定义逻辑,是 AOP 代理、属性加密等功能的底层实现机制。所有 Bean 初始化时都会触发,适合全局增强。
  2. BeanFactoryPostProcessor
    在 Bean 定义加载后、实例化前修改 BeanDefinition,可动态调整 Bean 配置(如替换占位符、修改属性值),典型应用是PropertySourcesPlaceholderConfigurer
  3. FactoryBean
    用于创建复杂 Bean 的工厂接口,可自定义对象的创建逻辑,Spring 内部如SqlSessionFactoryBean即采用此模式,适合封装第三方组件。
二、MVC 扩展点
  1. WebMvcConfigurer
    自定义 Spring MVC 配置,可注册拦截器、格式化器、视图解析器等,替代传统的web.xml配置,实现细粒度的 MVC 定制。
  2. HandlerInterceptor
    拦截 HTTP 请求和响应,可在请求处理前后执行逻辑(如登录验证、请求日志),支持对特定 URL 路径进行拦截。
  3. @ControllerAdvice 与 @ExceptionHandler
    全局异常处理机制,通过@ControllerAdvice定义全局处理器,结合@ExceptionHandler统一处理 Controller 层抛出的异常,返回规范化的错误响应。
三、配置类扩展点
  1. @Configuration + @Bean
    基于 Java 的配置方式,替代 XML 配置,可通过@Bean方法自定义 Bean 的创建和初始化过程,支持依赖注入和条件加载。
  2. @Import 与 ImportSelector
    用于导入其他配置类或动态选择配置类,实现模块化配置。ImportSelector可基于条件返回需导入的类名数组,常用于自动配置。
  3. @Conditional 与 Condition
    基于条件注册 Bean,可根据环境变量、类路径存在性等动态决定是否加载某个 Bean,是 Spring Boot 自动配置的核心机制。
MVC分层介绍一下
分层核心职责具体内容特点
Model(模型)管理应用数据和业务逻辑,是数据处理和业务决策的核心- 数据:实体类(如 User、Order)、临时计算数据(如统计结果) - 业务逻辑:数据验证(如手机号格式校验)、业务规则(如订单金额计算)、数据持久化(如数据库 CRUD)与 View、Controller 完全解耦,独立于界面和交互逻辑,稳定性高
View(视图)展示数据并与用户交互,是用户直接感知的界面- 数据展示:将 Model 传递的数据可视化(如网页表格、APP 列表) - 用户输入:接收用户操作(如表单提交、按钮点击)并传递给 Controller只关注 “如何展示”,不处理业务逻辑,可灵活替换(如从网页改为小程序界面)
Controller(控制器)作为 Model 与 View 的桥梁,接收请求、协调业务处理并返回结果- 接收请求:获取 View 传递的用户输入(如表单参数、URL 参数) - 调度逻辑:调用 Model 层处理业务(如调用 Service 方法) - 响应处理:将 Model 处理结果传递给 View,决定展示哪个界面不处理业务逻辑,仅负责 “调度”,降低 View 与 Model 的直接耦合

三层通过交互流程协作:用户操作 View → Controller 接收请求 → 调用 Model 处理业务 → Model 返回结果 → Controller 选择 View 展示结果。

了解SpringMVC的工作流程吗?
  • 用户发送请求至前端控制器DispatcherServlet,DispatcherServlet收到请求调用处理器映射器HandlerMapping。
  • 处理器映射器根据请求url找到具体的处理器,生成处理器执行链HandlerExecutionChain(包括处理器对象和处理器拦截器)一并返回给DispatcherServlet。
  • DispatcherServlet根据处理器Handler获取处理器适配器HandlerAdapter执行HandlerAdapter处理一系列的操作,如:参数封装,数据格式转换,数据验证等操作,
  • 执行处理器Handler(Controller,也叫页面控制器)。
  • Handler执行完成返回ModelAndView。
  • HandlerAdapter将Handler执行结果ModelAndView返回到DispatcherServlet。
  • DispatcherServlet将ModelAndView传给ViewReslover视图解析器
  • ViewReslover解析后返回具体View。
  • DispatcherServlet对View进行渲染视图(即将模型数据model填充至视图中)。
  • DispatcherServlet响应用户。
Handlermapping 和 Handleradapter有了解吗?
对比维度HandlerMapping(处理器映射器)HandlerAdapter(处理器适配器)
核心功能根据请求信息(URL、HTTP 方法、请求头等),找到处理请求的Handler(如@Controller中的方法、接口实现类等),并封装拦截器链。根据 Handler 的类型,适配并执行 Handler,处理参数绑定、数据转换、返回值处理等细节,统一调用逻辑。
处理阶段位于请求处理的早期阶段,在DispatcherServlet接收请求后首先被调用。位于HandlerMapping之后,在确定 Handler 后执行,负责调用 Handler 并返回结果。
输入信息HTTP 请求对象(HttpServletRequest),包含 URL、参数、请求方法等。Handler 对象(如具体方法或接口实现类)、HTTP 请求 / 响应对象。
输出结果HandlerExecutionChain(包含匹配的 Handler 和拦截器链)。ModelAndView(视图与模型数据)或直接写入响应体(如@ResponseBody标注的返回值)。
关键作用解决 “找谁处理请求” 的问题,实现请求到处理逻辑的映射。解决 “如何处理请求” 的问题,屏蔽不同 Handler 类型的调用差异,统一执行流程。
常见实现类RequestMappingHandlerMapping(处理注解式 Handler,如@RequestMapping方法)、BeanNameUrlHandlerMapping(根据 Bean 名映射 URL)。RequestMappingHandlerAdapter(适配注解式 Handler)、SimpleControllerHandlerAdapter(适配Controller接口实现类)。
设计意图通过灵活的映射规则(如注解、配置),支持多样化的请求路由需求。通过适配器模式,兼容不同类型的 Handler(注解式、接口式等),让DispatcherServlet无需关心具体调用方式。
示例场景当请求GET /users/1时,找到UserController@GetMapping("/users/{id}")标注的getUser方法。调用getUser方法时,自动将 URL 中的id=1转换为Long类型参数,执行方法后将返回的视图名封装为ModelAndView
SpringBoot比Spring好在哪里
  • 配置更简单:SpringBoot 通过 “自动配置” 机制,根据依赖自动生成默认配置,开发者仅需修改少量个性化配置(如端口、数据库连接)。
  • 部署更便捷:SpringBoot 内嵌 Tomcat、Jetty 等服务器,可直接打包为可执行 JAR,通过 java -jar 一键启动,无需额外配置服务器。
  • 依赖管理更高效:SpringBoot 提供 “Starter” 依赖(如 spring-boot-starter-web),自动管理依赖版本,避免版本兼容问题。
  • 开发效率更高:SpringBoot 开箱即用,默认集成常用功能(如日志、健康检查),且与 Spring 生态(如 Spring Cloud)无缝衔接,降低集成成本。
怎么理解SpringBoot中的约定大于配置

它通过预设合理默认值标准化项目结构,让开发者用最少的配置快速启动项目,同时保留灵活扩展的能力。

**自动化配置:**Spring Boot 提供了大量的自动化配置,通过分析项目的依赖和环境,自动配置应用程序的行为。开发者无需显式地配置每个细节,大部分常用的配置都已经预设好了。例如,引入spring-boot-starter-web后,Spring Boot会自动配置内嵌Tomcat和Spring MVC,无需手动编写XML。

**默认配置:**Spring Boot 为诸多方面提供大量默认配置,如连接数据库、设置 Web 服务器、处理日志等。开发人员无需手动配置这些常见内容,框架已做好决策。例如,默认的日志配置可让应用程序快速输出日志信息,无需开发者额外繁琐配置日志级别、输出格式与位置等。

**约定的项目结构:**Spring Boot 提倡特定项目结构,通常主应用程序类(含 main 方法)置于根包,控制器类、服务类、数据访问类等分别放在相应子包,如com.example.demo.controller放控制器类,com.example.demo.service放服务类等。此约定使团队成员更易理解项目结构与组织,新成员加入项目时能快速定位各功能代码位置,提升协作效率。

SpringBoot自动装配原理是什么?

SpringBoot自动装配是基于约定大于配置的理念,通过@SpringBootApplication注解中的@EnableAutoConfiguration触发,扫描META-INF/spring.factories中定义的自动配置类,利用条件注解(如@ConditionalOnClass)判断是否满足配置条件,自动向Spring容器注册如数据源、MVC组件等Bean,同时允许用户通过自定义配置覆盖默认配置,从而显著减少Spring应用的样板代码,提升开发效率。

SpringBoot 过滤器和拦截器说一下?
对比项过滤器(Filter)拦截器(Interceptor)
规范 / 框架Servlet 规范(容器层)Spring MVC 框架(应用层)
执行时机在 Servlet 之前 / 之后在 Controller 之前 / 之后、视图渲染前后
依赖注入不支持(Filter 由 Servlet 容器管理)支持(Interceptor 由 Spring 容器管理)
拦截范围所有请求(如静态资源、Servlet 请求)仅拦截 Spring MVC 处理的请求(不包括静态资源)
性能更高(直接由 Servlet 容器调用)略低(需要经过 Spring MVC 的 DispatchServlet)
使用场景全局请求处理(如编码、日志、跨域)业务相关拦截(如登录校验、权限控制)

过滤器(Filter)是 Servlet 规范中的组件,由 Servlet 容器管理,可拦截所有类型请求(包括静态资源、HTTP 请求等),在请求进入 Servlet 前或响应返回客户端前执行,支持全局处理(如编码设置、跨域处理),需通过 FilterRegistrationBean 或 @WebFilter 注册,不支持依赖注入,适用于容器级别的通用请求处理

拦截器(Interceptor)是 Spring MVC 框架的组件,由 Spring 容器管理,仅拦截 Spring MVC 处理的请求(不包括静态资源),在 Controller 调用前后、视图渲染前后执行,支持依赖注入(如注入 Service),通过 WebMvcConfigurer 注册,可针对特定 URL 进行细粒度控制(如登录校验、请求耗时统计),适用于业务相关的拦截逻辑。

Mybatis里的 # 和 $ 的区别?

Mybatis 在处理 #{} 时,会创建预编译的 SQL 语句,将 SQL 中的 #{} 替换为 ? 号,在执行 SQL 时会为预编译 SQL 中的占位符(?)赋值,调用 PreparedStatement 的 set 方法来赋值,预编译的 SQL 语句执行效率高,并且可以防止SQL 注入,提供更高的安全性,适合传递参数值。

Mybatis 在处理 ${} 时,只是创建普通的 SQL 语句,然后在执行 SQL 语句时 MyBatis 将参数直接拼入到 SQL 里,不能防止 SQL 注入,因为参数直接拼接到 SQL 语句中,如果参数未经过验证、过滤,可能会导致安全问题。

MybatisPlus和Mybatis的区别

CRUD操作:MybatisPlus通过继承BaseMapper接口,提供了一系列内置的快捷方法,使得CRUD操作更加简单,无需编写重复的SQL语句。

**代码生成器:**MybatisPlus提供了代码生成器功能,可以根据数据库表结构自动生成实体类、Mapper接口以及XML映射文件,减少了手动编写的工作量。

**通用方法封装:**MybatisPlus封装了许多常用的方法,如条件构造器、排序、分页查询等,简化了开发过程,提高了开发效率。

分页插件:MybatisPlus内置了分页插件,支持各种数据库的分页查询,开发者可以轻松实现分页功能,而在传统的MyBatis中,需要开发者自己手动实现分页逻辑

介绍一下服务熔断

服务熔断(Circuit Breaker)是分布式系统中的一种容错机制,用于防止级联故障和雪崩效应。当依赖的服务出现问题(如响应超时、频繁错误)时,熔断机制会暂时切断对该服务的调用,直接返回降级结果,避免资源浪费和故障扩散。

  • 工作原理
    1. 关闭状态(Closed)
      • 正常调用目标服务。
      • 记录失败次数(或错误率),若超过阈值则转为打开状态
    2. 打开状态(Open)
      • 立即返回降级结果(如缓存数据、默认值)。
      • 经过预设的冷却时间后,转为半开状态
    3. 半开状态(Half-Open)
      • 允许少量请求调用目标服务。
      • 若请求成功,认为服务已恢复,熔断器关闭
      • 若请求失败,认为服务仍未恢复,熔断器重新打开
介绍一下服务降级

服务降级是分布式系统应对压力和故障的 “主动防御机制”,通过牺牲局部非核心功能,保障整体系统的稳定性和核心业务的可用性。它与服务熔断相辅相成(熔断常触发降级),共同构成微服务架构中的容错体系,是高可用系统设计的重要组成部分。

负载均衡有哪些算法?

1. 轮询算法

  • 原理:按顺序轮流将请求分配给每个服务器,例如第 1 个请求给服务器 A,第 2 个给服务器 B,第 3 个再给服务器 A,循环往复。

2. 加权轮询算法

  • 原理:为每个服务器分配权重(如性能高的服务器权重高),请求按权重比例分配。例如服务器 A 权重 3、服务器 B 权重 1,则 A 接收 3 次请求后,B 接收 1 次,循环执行。

3. 随机算法

  • 原理:每次随机选择一个服务器处理请求,理论上概率均等。

4. 加权随机算法

  • 原理:为服务器分配权重,权重高的服务器被随机选中的概率更高(如权重 3 的服务器被选中的概率是权重 1 的 3 倍)。

5. 最少连接数算法

  • 原理:优先将请求分配给当前连接数最少的服务器,动态反映服务器负载。

6. 加权最少连接数算法

  • 原理:在最少连接数基础上,结合权重调整 —— 服务器权重越高,允许的 “可接受连接数” 越多。例如,服务器 A 权重 2、当前连接数 4;服务器 B 权重 1、当前连接数 3,则 A 的 “有效连接数” 为 4/2=2,B 为 3/1=3,因此优先选择 A。

7.IP哈希算法

  • 原理:****IP 哈希的原理是:对客户端的 IP 地址进行哈希计算得到一个数值,再将该数值与后端服务器的数量进行取模运算,最终的结果即为该客户端请求所分配到的服务器索引。

8. URL 哈希算法

  • 原理:对请求的 URL 路径进行哈希计算,将相同 URL 的请求分配到同一服务器。

9. 最小响应时间算法

  • 原理:优先选择响应时间最短的服务器(即处理请求最快的服务器)。

10.一致性哈希算法

  • **原理:**先构建一个范围固定的哈希环(如 0 到 2³²-1),将所有服务器节点通过哈希函数映射到环上;当客户端请求到来时,同样对其 IP 或请求参数进行哈希计算并映射到环上,然后按顺时针方向在环上寻找距离该哈希值最近的服务器节点,作为请求的处理节点。
如何实现一直均衡给一个用户?

基于用户标识的哈希映射(结合一致性哈希优化):首先为每个用户分配唯一标识(如用户 ID、登录 Token、IP 地址等),对该标识进行哈希计算后,通过一致性哈希算法映射到服务器集群。一致性哈希会将服务器节点分布在哈希环上,用户请求的哈希值会顺时针匹配最近的服务器。

微服务常用的组件有哪些?
  1. **服务注册与发现:**在微服务架构中,服务实例的地址会动态变化(如扩缩容、故障重启),服务注册与发现通过注册中心统一管理服务的注册信息(如 IP、端口),并提供查询功能。调用方无需硬编码服务地址,而是从注册中心获取最新的可用实例列表,实现服务间的自动发现与调用,避免了人工维护地址的复杂性,是微服务 “去中心化” 的基石。
  2. **服务通信:**微服务间需通过网络进行协作,服务通信解决了 “如何调用” 的问题。同步通信(如 REST API、RPC)适用于实时性要求高的场景,调用方需等待响应;异步通信(如消息队列)通过中间件解耦服务,适用于削峰填谷、最终一致性场景,提升系统弹性。选择通信方式需根据业务场景权衡实时性与吞吐量。
  3. **负载均衡:**将请求均匀分配到多个服务实例,避免单点过载,提升系统可用性与吞吐量。客户端负载均衡(如 Ribbon)在调用方内部实现,根据本地维护的实例列表选择节点;服务端负载均衡(如 Nginx)在流量入口层统一分发。负载均衡算法(如轮询、随机、最少连接)决定请求路由策略,需结合服务性能与请求特性优化配置。
  4. **API网关:**作为微服务的统一入口,聚合所有服务的 API,对外提供统一接口,屏蔽内部服务细节。其核心功能包括路由分发(根据 URL 将请求转发至对应服务)、认证授权(校验用户身份与权限)、限流熔断(保护后端服务)、协议转换(如 HTTP 转 RPC)等,简化了客户端与微服务的交互,同时集中处理跨服务的共性逻辑。
  5. **配置中心:**集中管理微服务的配置信息(如数据库连接、环境参数),替代传统的本地配置文件。配置中心支持动态刷新(修改配置后无需重启服务)、版本控制、环境隔离(开发 / 测试 / 生产环境配置分离)、灰度发布等特性,解决了分布式系统中配置分散、难以同步的问题,尤其适用于频繁变更配置的场景。
  6. **服务熔断与限流:**熔断机制在依赖服务出现故障(如响应超时、频繁错误)时,自动切断调用,直接返回降级结果(如缓存数据、默认值),防止故障扩散引发级联崩溃;限流则通过限制请求速率(如每秒 1000 次),保护服务不被过载流量压垮。两者结合使用,确保系统在异常情况下仍能保持核心功能可用,提升整体容错能力。
### 小林 Coding IT 资料汇总 小林 Coding 提供了一系列高质量的 IT 学习资料,主要集中在操作系统、计算机网络等领域。以下是相关内容的具体介绍: #### 操作系统领域 小林 Coding 整理了一份名为《图解操作系统》的学习资料[^1]。这份资料以直观易懂的方式解析了操作系统的核心原理与运作机制,适合不同水平的学习者。具体内容包括但不限于以下几个方面: - **操作系统概述**:介绍了操作系统的定义及其基本功能。 - **进程管理**:讲解了进程的概念、状态转换以及调度策略[^4]。 - **内存管理**:探讨了虚拟内存、分页与分段技术的应用场景。 - **文件系统**:分析了文件存储结构及访问控制方法。 - **设备管理**:描述了输入输出子系统的组成和工作流程。 - **安全与保护**:讨论了权限管理和防止攻击的技术手段。 此外,在多线程编程部分还提到了缓存一致性问题中的伪共享现象,并给出了优化建议[^3]。 #### 计算机网络领域 关于计算机网络方面的内容,《【计算机网络】小林coding阅读笔记》提供了详细的解读[^2]。文档围绕 OSI 七层模型展开叙述,解释每一层的功能以及各层间如何协作完成数据包从源节点到目标节点的传递过程。同时指出尽管理论上有严格的分层标准,但在实际应用中更倾向于采用 TCP/IP 协议族作为基础框架。 ```python # 示例代码展示简单的TCP连接建立逻辑 import socket def create_tcp_connection(host, port): try: client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.connect((host, port)) print(f"Connected to {host}:{port}") except Exception as e: print(f"Error connecting: {e}") create_tcp_connection('example.com', 80) ``` 以上就是有关于小林 Coding 所分享的部分 IT 技术资源概览。希望对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值