欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

springboot启动类

发布时间:2023/12/18 49 豆豆
生活随笔 收集整理的这篇文章主要介绍了 springboot启动类 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、简单回顾
  • 二、run方法的入参
  • 三、ComponentScan的扫描范围
  • 总结


前言

提示:这里可以添加本文要记录的大概内容:

springboot启动流程有很多文章都介绍得很详细了,今天我们换种方式来讨论下启动类。


提示:以下是本篇文章正文内容,下面案例可供参考

一、简单回顾

1、首先快速创建一个springboot项目,编写一个测试接口。

@RestController public class UserController {@RequestMapping("/test")public String getNameById(String id){System.out.println("测试接口入参,id="+id);return "lili";} }


接口正常,这是我们按默认方式创建项目。我们的启动类也很简单就是默认创建的。

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);} }

2、下面我们来改造下启动类,demo1:将启动类的注解去掉,run方法入参换一个配置类

import com.jy.demo.config.AopConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;//@SpringBootApplication public class DemoApplication {public static void main(String[] args) {SpringApplication.run(AopConfig.class, args);} } import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.*;/*** @Author jy* @Date 2022/4/2 15:38* @Version 1.0*/ @Configuration @ComponentScan(basePackages = "com.jy.demo.controller") //@EnableAspectJAutoProxy @EnableAutoConfiguration //@Import(JyAfterFilter.class) public class AopConfig {}

启动服务测试接口,发现服务正常启动,接口调用也是正常

从目前来看这样操作是没有问题。那么我们再来试试demo2的方式修改,先新建两个类具体位置如图


从图片中可以看出,main所在的类在app包下,配置类在最外层,这时我用TestApplication启动,服务也是正常运行,测试接口也是正常调用成功

3、我们再修改下代码,demo3:配置类也改一下

import com.jy.demo.config.AopConfig; import org.springframework.boot.SpringApplication;/*** @Author jy* @Date 2022/7/20 15:43* @Version 1.0*/ public class TestApplication {public static void main(String[] args) {SpringApplication.run(AopConfig.class, args);} }

服务启动依然正常,接口测试也正常

我们几种修改都能正常启动,接口也正常调用,那么为什么可以呢?

二、run方法的入参

1、首先我们还是回顾下spring的注解模式

public class Demo9 {public static void main(String[] args) {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AopConfig.class);applicationContext.publishEvent(new ApplicationEvent("监听事件推送") {});Apple bean = applicationContext.getBean(Apple.class);bean.setId(1);System.out.println(bean);} } public void register(Class<?>... componentClasses) {Assert.notEmpty(componentClasses, "At least one component class must be specified");StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register").tag("classes", () -> Arrays.toString(componentClasses));this.reader.register(componentClasses);//注意这行代码!!!!registerComponentClass.end();}

传入的参数就是一个配置类,spring先将这个配置类注入容器,然后在BeanFactoryPostProccsor的实现中处理配置类带来的该处理的对象。具体的操作可以看看Configuration注解解析,而springboot的启动类中的run方法入参是什么呢?其实也是一个配置类,那么springboot是怎么用这个配置类的呢?

首先是将这个配置类放在SpringApplication的成员变量里,然后在run方法中的上下文应用准备的时候对配置类进行了处理。

// Load the sourcesSet<Object> sources = getAllSources();Assert.notEmpty(sources, "Sources must not be empty");load(context, sources.toArray(new Object[0]));listeners.contextLoaded(context); public Set<Object> getAllSources() {Set<Object> allSources = new LinkedHashSet<>();if (!CollectionUtils.isEmpty(this.primarySources)) {allSources.addAll(this.primarySources);}if (!CollectionUtils.isEmpty(this.sources)) {allSources.addAll(this.sources);}return Collections.unmodifiableSet(allSources);}

往下一步就是在load()方法中加载


这里因为我们看的配置类,所以进入第一个if中,再往里走就到了我们前面spring处理时的类似代码了

圈上的这行代码和前面提示注意的那行代码就是一个意思了,到目前为止说清楚了,这个配置类被注册到容器的过程,那么和我们启动类的位置有什么关系呢?

三、ComponentScan的扫描范围

细心的朋友可能已经发现,我们几次修改的时候配置类的ComponentScan的value值是有所不同的,@SpringBootApplication的value值是默认空,而自己写的配置类上的ComponentScan注解是加了路径值的。两者的区别在于,默认空的话,扫描路径是按配置类所在的位置扫描同级及下级;有值的话就按填写的值进行扫描同级及下级。这个操作在ConfigurationClassPostProcessor类处理配置类信息时处理的。而配置类的信息在前面已经说了是怎么注册到容器中的,所以spring能处理到我们的启动配置类,也顺其自然的能处理到配置类上的扫描范围。所以虽然我们修改了main方法文件所在的位置,修改了配置类的位置服务依然能正常启用,接口也正常调用。

总结

唉,前面屁话了一堆,第三点就这么点东西说明了原因。最后再多一嘴,
既然启动类的位置可以不在最外层,那springboot为什么要放在最外层呢?因为springboot不知道我们会写些什么包路径,所以放最外层从最外层往下扫描,将对象是否注入容器交给开发者(需要注入就加注解)。以上就是我的一点个人理解,欢迎大家斧正。大家一起加油!!!

总结

以上是生活随笔为你收集整理的springboot启动类的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。