【Java面试】SpringBoot篇

简介: 【Java面试】SpringBoot篇

Spring和SpringBoot的关系和区别?

他们都是Spring生态的产品。

Spring Framework是一个容器框架。

SpringBoot他不是一个框架,他是一个可以快速构建基于Spring的脚手架,里面包含了Spring和各自框架,为开发Spring生态其他框架铺平道路。他是为了更快的去开发Spring生态的整个系统而诞生的。

2者不是一个层面的东西,没有可比性。

谈谈你对SpringBoot的理解,它有哪些特性?

从本质上来说,Spring Boot就是Spring,它做了那些没有它你自己也会去做的Spring Bean配置。Spring Boot使用“约定优于配置”的理念让你的项目快速地运行起来,使用Spring Boot很容易创建一个能独立运行、准生产级别、基于Spring框架的项目,使用Spring Boot你可以不用或者只需要很少的Spring配置

简而言之,Spring Boot本身并不提供Spring的核心功能,而是作为Spring的脚手架框架,以达到快速构建项目、预置三方配置、开箱即用的目的。Spring Boot有如下的优点:

  • 可以快速构建项目,内置许多starter自动配置,开箱即用;
  • 可以对主流开发框架的无配置集成;
  • 项目可独立运行,无需外部依赖Servlet容器;
  • 提供运行时的应用监控;
  • 内置web容器,无需依赖外部web服务器,省略了web.xml,直接运行jar文件就可以启动web项目
  • 可以极大地提高开发、部署效率;
  • 管理了第三方依赖的版本,减少版本冲突问题
  • 简化开发,采用JavaConfig的方式可以使用零xml的方式开发项目
  • 可以与云计算天然集成。

SpringBoot的核心注解

  1. @SpringBootApplication注解:这个注解标识了一个SpringBoot工程,它实际上是另外三个注解的组合,这三个注解是@SpringBootConfiguration,@EnableAutoConfguration,@ComponentScan。
  2. @SpringBootConfiguration:这个注解实际就是一个@Configuration,表示启动类也是一个配置类。
  3. @EnableAutoConfguration:向Spring容器中导入了一个Selector,用来加载ClassPath下spring.factories中所定义的自动配置类,将这些自动加载为配置Bean。
  4. @Conditional也很关键,如果没有它我们无法在自定义应用中进行定制开发
    @ConditionalOnBean
    @ConditionalOnClass
    @ConditionalOnExpression

说说你对SpringBoot自动配置的理解

自动装配简单来说就是自动吧第三方的bean加载到IOC容器中去。不需要开发人员在去写bean相关的配置。在sb项目中只要在启动类上加上@SpringBootApplication注解就可以实现自动装配。这个注解是一个复合注解,真正去实现自动装配的注解是@EnableAutoConfiguration。自动装配的实现主要依靠三个核心的技术。

第一个是引入starter。启动依赖组件的时候,这个组件里面必须包含@Configuration配置类,而在这个配置类中我们需要通过@Bean这个注解去声明要加载到IOC容器中的对象。

第二个是这个配置类是放在第三方的jar包中的。然后通过sb中的约定优于配置这样的一个理念,去吧这个配置类的全路径放在classpath:/META-INF/spring.factories文件里面。这样sb就可以知道第三方jar包里面这个配置类的位置。这个步骤主要使用到了spring中的SpringFactoriesLoader来完成的。

第三个是sb拿到所有第三方jar包里面的声明的配置类之后,在通过Spring提供的ImportSelector这样的一个接口,来实现对这些配置类的动态加载。从而去完成自动装配这样一个动作。

在我看来呢,sb是约定优于配置这一理念的产物,所以在很多的地方都会看到这一思想。它的出现让开发人员可以更加聚焦于业务代码的开发,而不需要去关心和业务无关的配置。其实自动装配的思想,在SpringFrameword3.x中的@Enable注解已经有了体现。这是一个模块

驱动注解,也就是我们只要添加这个注解,就能自动开启某个功能。而不需要针对这个功能去做bean的配置。enbale的底层也是自动帮我们去完成一个模块相关bean的注入的。

为什么SpringBoot的jar包可以直接运行?

  1. SpringBoot提供了一个插件spring-boot-maven-plugin用于把程序打包成一个可执行的jar包。
  2. Spring Boot应用打包之后,生成一个Fat jar(jar包中包含jar,比较臃肿,所以叫Fat.jar),包含了应用依赖的jar包和Sprirg Boot loader相关的类。
  3. java -jar会去找jar中的manifest文件,在那里面找到真正的启动类。
    这是因为Java已经定义了java -jar这个命令去加载jar包中的manifest文件,并且以这个文件中的Main-Class后面的路径来找到启动类。
  4. Fat jar的启动Main函数是JarLauncher,它负责创建一个LaunchedURLClassLoader来加载boot-lib下面的jar,并以一个新线程启动应用的Main函数。

SpringBoot的启动原理(还在改进)

会不会自定义Starter?大概实现过程?

我们需要在我们自定义的starter中的resources下创建文件夹META-INF并在METE-INF下创建文件spring.factories。

然后在里面设定你要自动配置的配置类的全路径。格式为

之后我们编写我们的配置类,并且在配置类中通过@Bean注解把要注入IOC容器中的bean进行声明。

SpringBoot读取配置文件的原理是什么?加载顺序是怎么样的?

通过事件监听的方式读取配置文件:ConfigFileApplicationListener

优先级从高到低,高优先级的配置覆盖低优先级的配置,所有配置会形成互补配置。

SpringBoot的默认日志实现框架是什么?怎么切换成别的?

默认的日志框架是logback。

SpringBoot项目的日志门面使用的是slf4j,而SpringBoot默认使用的是logback提供的桥接器,因此SpringBoot默认会使用logback进行日志功能。

想要切换日志,那么需要做如下操作:

1:将logback的场景启动器排除(slf4j只能运行有一个桥接器)

2:添加新的日志的场景启动器

3:添加新的日志的配置文件

目前springboot已经为我们提供了logfj2和logback的starter,因此我们可以直接开箱即用。

但是如果要使用logfj,那么就需要首先排除logbakc的依赖,然后添加log4j的桥接器,然后再添加log4j的配置文件。

说说你在开发的时候怎么在SpringBoot上进行扩展?

如果想要对某个功能进行扩展,那么首先得了解这个功能是如何进行配置的,因此我可能会先去查看这个功能的官方文档,之后大致了解之后,会查看底层源码。

这里我以AOP为例吧。

我们知道AOP默认使用的是cglib来进行动态代理,那么如果我想要它使用JDK提供的动态代理怎么办呢?

那么此时就得去查看AOP对应的配置类了。

我知道SpringBoot项目中的配置类一般名称为XxxAutoConfiguration。

因此我就会搜索AopAutoConfiguration。然后查找启动的可能的配置属性。

一般查看@Condition注解里面可能会有某个属性的开关。

那么如果找到了,那么只需要去配置文件中进行属性的修改配置即可。

当然,有些自动配置类提供对外的扩展接口,实现接口也可以进行扩展,比如我们的SpringMvc。

如果我们要对SpringMvc进行扩展,那么我们只要实现WebMvcConfigurer这个接口即可。

所以我一般都会选择看源码这种方式。IDEA非常方便,搜索对应的XxxAutoConfiguration即可。

SpringBoot是如何选择使用Jetty还是Tomcat的?

我们知道,我们是可以获取到SpringBoot要进行加载的Bean的类型的,那么如果我们获取到了所有要加载的Bean,那么此时就可以通过这些Bean对象来选择是使用Jetty还是Tomcat。

比如我定义了Tomcat,那么我就选择加载Tomcat,反之我可以加载Jetty。如果都定义或者都没有定义,那么会进行报错。其中没有名字报错是因为你明明把这个项目声明为了一个Web项目,结果你没有对应的服务器,或者就是你只能选择一个服务器,结果你给我定义了多个服务器,那么我选那个?所以会报错。那么如果流程正常,我就会创建这个Bean,也就是Tomcat或者Jetty服务器。

但是其实SpringBoot默认把Jetty,Tomcat,Undertow三个Web服务器都声明为了Bean,那么很明显会出现冲突。所以此时就通过@Condition进行条件判断来选择加载那个Bean。

所以其大致流程为:

首先通过getWebServerFactory方法来获取一个ServletWebServerFactory对象,其中Jetty和Tomcat都实现了这个接口。

那么如果返回的是Tomcat的ServerFatory,那么之后的getWebServer方法返回的就是Tomcat这个web服务,反之就是Jetty。在这个方法中,Tomcat和Jetty都会在其中创建自己,然后作为一个对象返回。

那么我们知道SpringBoot默认使用的是Tomcat,那么要做到这样,只要保证我们的依赖中只有Tomcat而没有Jetty和Undertow即可。

所以此时我们引入的web-starter中,其中默认就是帮助我们引入了Tomcat这个依赖,所以,默认使用的就是Tomcat。而我们只需要使用exclude去排除tomcat依赖,并且引入我们需要的服务器,就可以转换服务器的类型。

并且,我们知道默认的Tomca的端口是8080,原因是因为SpringBoot项目中默认把这个端口写死在了Tomcat服务器的父类中。那么如果我们想要修改这个端口,就需要使用Spring提供的后置处理----BeanPostProcess来进行对端口的修改。

最终追述到ServerProperties这个配置类即可。其中有一个port属性,这个属性就会覆盖原有的Tomcat的端口。


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
1天前
|
Java Maven 开发者
深入剖析Spring Boot在Java Web开发中的优势与应用
深入剖析Spring Boot在Java Web开发中的优势与应用
|
2天前
|
存储 缓存 Java
面试官:什么是Java内存模型?
面试官:什么是Java内存模型?
14 0
面试官:什么是Java内存模型?
|
3天前
|
缓存 监控 架构师
阿里面试:Java开发中,应如何避免OOM
在Java开发中,OutOfMemoryError(OOM)错误一直是令开发者头疼的问题,也是Java面试中出现核心频率很高的问题。 那么我们究竟怎么样才能够有效正确的管理内存,日常开发中究竟要注意哪些核心技巧来避免OOM错误。 本文将带大家一起学习10个避免OOM的实用小技巧,让大家在工作中能够有的放矢,避免OOM错误的飞来横祸。
21 1
|
4天前
|
Java
【Java专题_03】使用springboot发送邮件
【Java专题_03】使用springboot发送邮件
18 2
|
4天前
|
XML 监控 druid
【Java专题_02】springboot+mybatis+pagehelper分页插件+druid数据源详细教程
【Java专题_02】springboot+mybatis+pagehelper分页插件+druid数据源详细教程
27 0
|
4天前
|
开发框架 安全 Java
【Java专题_01】springboot+Shiro+Jwt整合方案
【Java专题_01】springboot+Shiro+Jwt整合方案
23 0
|
4天前
|
前端开发 Java 数据库连接
认识Java中最常用的框架:Spring、Spring MVC、Spring Boot、MyBatis和Netty
Spring框架 Spring是一个轻量级的开源框架,用于构建企业级应用。它提供了广泛的功能,包括依赖注入、面向切面编程、事务管理、消息传递等。Spring的核心思想是控制反转(IoC)和面向切面编程(AOP)。
25 3
|
22天前
|
安全 IDE Java
【2024java面试题无需C币下载】终结空指针异常:Java开发者的生存指南
【2024java面试题无需C币下载】终结空指针异常:Java开发者的生存指南
27 1
|
22天前
|
缓存 Java 数据库
2024java面试题无需C币下载 速度之战:全方位解决Java接口慢响应问题
2024java面试题无需C币下载 速度之战:全方位解决Java接口慢响应问题
55 1
|
24天前
|
Java 数据库连接 mybatis
JAVA框架技术之十八节springboot课件上手教程(二)
JAVA框架技术之十八节springboot课件上手教程
54 0
JAVA框架技术之十八节springboot课件上手教程(二)

相关产品

  • 云迁移中心