《面试1v1》Spring基础

作者简介:王哥,CSDN2022博客总榜Top100、博客专家
技术交流:定期更新Java硬核干货,不定期送书活动
王哥多年工作总结:Java学习路线总结, 点击 突击面试
数十万人的面试选择: 面试说人话系列《面试1v1》

我是 javapub,一名 Markdown 程序员从‍,八股文种子选手。


《面试1v1》 连载中…


我是 javapub,一名 Markdown 程序员从‍,八股文种子选手。

面试官: 想请你简单介绍一下 Spring 框架,它的核心特性是什么?

候选人: Spring 是一个开源框架,目的是简化 JavaEE 开发。它的核心特性有:

  1. IoC(Inverse of Control):通过 DI(Dependency Injection)实现将对象间的依赖关系交给 Spring 管理。
  2. AOP(Aspect Oriented Programming):面向切面编程,可以在程序运行期间动态的将某段代码切入到指定的方法、指定的位置进行运行。
  3. Portlet MVC:Spring 提供 MVC 框架可以快速开发 Web 应用。
  4. 事务管理:Spring 提供广泛的事务管理接口,支持 JDBC、Hibernate 等事务管理。
  5. Spring 统一一体化了其他框架和技术,如:Struts、Hibernate、Quartz 等。
    面试官(笑):你说的真是五花八门,让我有点晕,来聊点具体的吧。Spring 是如何工作的,它如何用于构建 Web 应用程序?

候选人: 好的,Spring 的工作原理主要是 IoC 容器。对 Web 应用来说,Spring MVC 是基于 JavaEE 的 Model-View-Controller 设计模式构建的,主要工作流程是:

  1. 浏览器发送请求到 DispatcherServlet。
  2. DispatcherServlet 接收请求后会转交给 HandlerMapping 得到请求对应的 Handler。
  3. HandlerMapping 将 Handler 映射到 HandlerAdapter。
  4. HandlerAdapter 调用 Handler 处理请求,Handler 会返回一个 ModelAndView。
  5. ViewResolver 解析 ModelAndView,找到正确的 View。
  6. DispatcherServlet 将 View 返回给浏览器。

通过这个流程,Spring MVC 应用了 MVC 模式,实现了业务逻辑、控制逻辑、表现逻辑的分离,使我们可以更加专注于业务开发。

面试官: 你说的很具体,我明白了。那么 Spring 可以在哪些实际场景中使用?开发人员在使用 Spring 时常犯哪些错误?

候选人: Spring 可以应用在很多实际场景中:

  1. Web 应用:Spring MVC 是 Spring 体系中最为成熟的框架,可以用来开发网站、BBS、博客等 Web 应用。
  2. 企业应用:Spring 提供事务管理、数据访问等功能,非常适用于开发企业级应用。
  3. 微服务:Spring Boot 提供了快速开发单个微服务的能力,配合 Spring Cloud 可以开发微服务架构的系统。
  4. Android 应用:Spring for Android 提供了在 Android 应用中使用 Spring 的能力。

开发人员在使用 Spring 时常犯的几个错误:

  1. 容器管理对象依赖关系错乱:未正确配置 bean 的依赖关系,导致依赖注入错误。
  2. 上下文目录 problemas:beans.xml 配置文件放在了非上下文目录,导致 Spring 无法识别。
  3. 事务管理错误:未正确配置事务属性,导致事务管理不生效。
  4. AOP 误用:滥用 AOP 或错误使用 AOP 导致 sistem 过于复杂或 AOP 不生效。
  5. 未考虑扩展性:在开发初期未考虑系统扩展性,导致系统难以演进。

面试官: 那么如何使基于 Spring 的应用程序更高效、更可扩展?

候选人: 这里有几点建议:

  1. 采用模块化设计,遵循高内聚低耦合原则,每个模块保持高内聚,模块之间低耦合。
  2. 使用设计模式,如工厂模式、单例模式、代理模式等,提高系统扩展性。
  3. 应用 AOP,通过预置切点在不修改源代码的情况下增加新功能。
  4. 使用 Spring 的事件机制,通过事件监听器监听事件,当事件触发时执行相应逻辑。
  5. 应用 Spring 的 Profile 功能,可以根据环境部署不同的 bean,提高系统灵活性。
  6. 使用 Spring Boot 依赖管理和自动配置的能力,简化构建过程,提高开发效率。
  7. 应用微服务架构,将单体应用拆分成职责单一、松耦合的服务,更容易扩展和升级。
  8. 使用缓存技术,如 Redis 缓存数据库查询结果,降低数据库压力,提高系统吞吐量。

面试官: 很棒,你对 Spring 和高可扩展系统的理解很透彻!最后一个问题,Spring 的源码中 IoC 容器的实现你可以大致描述一下吗?

候选人: 可以的,IoC 容器的实现主要在 AbstractApplicationContext 及其子类 ClassPathXmlApplicationContext 和FileSystemXmlApplicationContext 中。主要流程是:

  1. 容器启动时会调用 refresh() 方法,其中会调用 obtainFreshBeanFactory() 方法初始化 DefaultListableBeanFactory,此为 IoC 容器的核心。
// AbstractApplicationContext.java
public void refresh() throws BeansException, IllegalStateException {
   // 初始化 BeanFactory
   DefaultListableBeanFactory beanFactory = obtainFreshBeanFactory();
}

  1. 然后会调用 loadBeanDefinitions(beanFactory) 方法加载 bean 定义,主要通过 XmlBeanDefinitionReader 解析 bean 定义文件。
// AbstractXmlApplicationContext.java  
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // Create a new XmlBeanDefinitionReader for the given BeanFactory.
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
  
    // Configure the bean definition reader with this context's
    // resource loading environment.
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
  
    // Allow a subclass to provide custom initialization of the reader,
    // then proceed with actually loading the bean definitions.
    initBeanDefinitionReader(beanDefinitionReader);
    loadBeanDefinitions(beanDefinitionReader);
}
  1. bean 实例化阶段会调用 getBean() 方法,通过工厂方法或构造器实例化 bean。
  2. 实例化 bean 后,会对 bean 进行属性注入、初始化以及其他Aware接口回调。
  3. bean 的生命周期至此结束,容器会对 bean 进行管理,直至容器关闭。
    这就是 IoC 容器实现的大致流程,关键是 bean 定义资源的加载和解析,以及 bean 的实例化及生命周期管理。IoC 容器屏蔽了 bean 之间的依赖关系,使 bean 的使用者可以零配置使用 bean。

面试官: 你的解释很到位,IoC 容器的源码分析确实需要对它的原理有深入了解。最后一个问题,在你的项目中是如何设计一个高并发的系统的?

候选人: 设计一个高并发系统,有以下几点建议:

  1. 选择高性能技术栈:选择支持高并发的语言(Java、Go 等)和框架(Spring、Vert.x 等)。
  2. 采用分布式和微服务架构:将系统拆分为多个单一职责的服务,部署在不同服务器上,可以实现高可用和负载均衡。
  3. 选择高性能存储:使用能支撑高并发读写的数据库,如 Redis、Kafka 等。对关系型数据库进行分库分表、添加缓存等优化。
  4. 限流与降级:使用限流手段控制流量,避免被高流量打垮;使用降级策略保证核心服务可用。
  5. 缓存与异步:对频繁读取数据的接口使用缓存;对非关键性计算使用异步处理,避免线程阻塞。
  6. 服务治理:使用服务注册与发现、熔断器、网关等手段管理各服务。
  7. 线程模型优化:根据业务选择恰当的线程模型。如对大量短连接使用线程池;对长连接使用主从 Reactor 线程模型等。
  8. 利用好硬件资源:合理分配 CPU 和内存资源给应用;利用好多核 CPU 进行并行计算等。
  9. 测试与监控:进行压力测试,监控系统的负载、吞吐量和延迟指标,并进行优化。
  10. 容错和自动恢复:设计稳定的容错方案,当系统发生故障时可以自动检测并恢复。
    这些方面搭配得当,可以设计一个高性能、高并发的系统。但需要权衡系统复杂性,在满足需求前提下保持最简实现。

面试官: 很棒,你在高并发系统设计方面有很强的理解力和丰富经验。

《面试1v1》Spring基础_第1张图片

最近我在更新《面试1v1》系列文章,主要以场景化的方式,讲解我们在面试中遇到的问题,致力于让每一位工程师拿到自己心仪的offer,感兴趣可以关注JavaPub追更!


《面试1v1》 连载中…


目录合集:

Gitee:https://gitee.com/rodert/JavaPub

GitHub:https://github.com/Rodert/JavaPub

http://javapub.net.cn

你可能感兴趣的:(《面试1v1》,spring,面试,java,jvm,后端)