红茶的个人站点

  • 首页
  • 专栏
  • 开发工具
  • 其它
  • 隐私政策
Awalon
Talk is cheap,show me the code.
  1. 首页
  2. 专栏
  3. Spring Boot 学习笔记
  4. 正文

从零开始 Spring Boot 5:SpringApplication

2022年5月5日 893点热度 0人点赞 0条评论

spring boot

图源:简书 (jianshu.com)

我们的Spring Boot应用是通过SpringApplication.run启动的,启动后可以看到控制台输出欢迎信息以及一些日志信息,如果失败,也会显示相应的错误信息。

SpringApplication的主要工作是加载相关的配置,创建Web应用的上下文,以及启动应用等。

下面介绍和SpringApplication相关的Spring Boot特性。

本篇文章的演示代码基于learn_spring_boot (github.com)修改而来,你可以从相应的链接获取。

Lazy Initialization

Lazy Initialization也可以叫做“延迟初始化”或“懒加载”,这是一个常用的Web技术,比如大量图片的展示网页,就会在用户下滑需要展示相应图片时再真正加载图片资源,这可以节省一开始网页加载的时间和带宽。

在Sprint Boot中,这指的是可以将相关创建和注入bean的行为延后到真正需要这些bean的时候,这样做可以加快应用的启动速度。但缺点是如果bean的生成会产生bug,那么就无法在一开始应用启动时暴露,而是延后到使用bean时,这样就违背了“尽可能早地暴露bug”这条编程哲学。此外,延迟初始化还可能因为内存紧张的机器在一开始可以正常启动,而在需要并初始化某些bean后导致内存不够而崩溃,着同样会掩盖问题的发生。

因此,并不推荐积极地使用这项功能。

要开启延迟初始化,可以添加以下配置项:

spring.main.lazy-initialization=true

如果开启了延迟初始化,你希望某些自动注入的组件不被延迟初始化,可以使用@Lazy(false)注解:

@Service
@Lazy(false)
public class UserService implements UserServiceInterface {
    ...
}

Banner

在应用启动后,你会在控制台看到这个:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.7)

这个叫做Banner(横幅),你可以用在资源目录中添加banner.txt的方式添加“自定义banner”:

=====================================================
This is my exampled spring boot app.
name:${application.title}
version:${application.formatted-version}
spring boot version:${spring-boot.formatted-version}
=====================================================

再运行你就可以看到类似这样的输出:

=====================================================
This is my exampled spring boot app.
name:
version:
spring boot version: (v2.6.7)
=====================================================

这里的${application.title}等都是banner中可以设置的相关参数,完整列表见Core Features (spring.io)。

因为${application.title}这样的参数是从MANIFEST.MF获取的信息,所以直接从IDE运行是没法正常显示的,需要打包后运行jar包:

❯ java -jar .\target\my_first_app-0.0.1-SNAPSHOT.jar
=====================================================
This is my exampled spring boot app.
name:my_first_app
version: (v0.0.1-SNAPSHOT)
spring boot version: (v2.6.7)
=====================================================

你甚至可以通过添加banner.gif、banner.png等资源文件让应用打印一个图片作为banner,当然因为控制台的关系,这里打印的是转换为ASCII字符后的图片。

SpringApplication

可以通过SpringApplication以编程的方式修改某些配置,比如关闭banner:

package cn.icexmoon.my_first_app;
​
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
​
@SpringBootApplication
@MapperScan("cn.icexmoon.my_first_app.mapper")
public class MyFirstAppApplication {
​
    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(MyFirstAppApplication.class);
        application.setBannerMode(Banner.Mode.OFF);
        application.run(args);
    }
​
}

再启动应用就会发现不显示banner了。

要了解可以通过SpringApplication修改的全部配置列表,可以阅读SpringApplication (Spring Boot 2.6.7 API)。

命令行参数

可以通过注入ApplicationArguments对象的方式获取应用启动时的命令行参数:

package cn.icexmoon.my_first_app.component;
​
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.stereotype.Component;
​
@Component
public class ArgumentReader {
    @Autowired
    public ArgumentReader(ApplicationArguments args){
        if(args.containsOption("test")){
            System.out.println("test is find.");
            System.out.println(args.getNonOptionArgs());
        }
    }
}

打包后通过java -jar .\target\my_first_app-0.0.1-SNAPSHOT.jar --test hahaha.txt运行就会看到输出:

test is find.
[hahaha.txt]

要注意的是,为了让新添加的ArgumentReader组件被框架加载,需要关闭延迟初始化功能:

spring.main.lazy-initialization=false
  • 当然你可以可以使用@Lazy注解,不过为了方便后续代码演示,这里直接关闭延迟加载功能。

  • ArgumentReader构造器的@Autowired注解其实可以省略,因为在仅有一个构造器的情况下,框架会自动通过该构造器进行注入。

ApplicationRunner or CommandLineRunner

如果你有一些特殊代码需要在应用启动后执行,可以通过ApplicationRunner或CommandLineRunner接口实现,它们都有一个简单的run方法可以被覆盖,前者使用ApplicationArguments作为参数传递命令行参数,后者直接通过String[]传递。覆盖的run方法会在SpringApplication.run调用完成前被调用。

package cn.icexmoon.my_first_app.component;
​
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
​
@Component
public class CommnadLineProcessor implements ApplicationRunner{
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("CommnadLineProcessor is triggered.");
        System.out.println(args.getSourceArgs());
    }
}

运行应用后会看到类似这样的输出:

CommnadLineProcessor is triggered.
[Ljava.lang.String;@559cf27

参考资料

  • Core Features (spring.io)

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: 暂无
最后更新:2022年8月29日

魔芋红茶

加一点PHP,加一点Go,加一点Python......

点赞
< 上一篇
下一篇 >

文章评论

取消回复

*

code

COPYRIGHT © 2021 icexmoon.cn. ALL RIGHTS RESERVED.
本网站由提供CDN加速/云存储服务

Theme Kratos Made By Seaton Jiang

宁ICP备2021001508号

宁公网安备64040202000141号