环境
- Ubuntu 22.04
- IntelliJ IDEA 2022.1.3
- JDK 17.0.3
- SpringBoot 2.7.3
准备
创建SpringBoot项目 test0905 ,全部使用默认设置。
创建包 com.example.test0905.pojo ,并创建如下POJO:
Axe :Axe接口;StoneAxe :Axe实现类;SteelAxe :Axe实现类;Person :Person持有Axe
package com.example.test0905.pojo;
public interface Axe {
public void chop();
}
package com.example.test0905.pojo;
import org.springframework.stereotype.Component;
@Component
public class StoneAxe implements Axe{
public StoneAxe() {
System.out.println("StoneAxe constructor!");
}
@Override
public void chop() {
System.out.println("Stone axe!");
}
}
package com.example.test0905.pojo;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
@Component
@Primary
public class SteelAxe implements Axe{
public SteelAxe() {
System.out.println("SteelAxe constructor!");
}
@Override
public void chop() {
System.out.println("Steel axe!");
}
}
package com.example.test0905.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Person {
private String name;
private Axe axe;
public void useAxe() {
System.out.println("I am " + name);
axe.chop();
}
@Autowired
public Person(@Value("Tom") String name, Axe axe) {
System.out.println("Person constructor!");
this.name = name;
this.axe = axe;
}
}
默认生成的主程序代码如下:
package com.example.test0905;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Test0905Application {
public static void main(String[] args) {
SpringApplication.run(Test0905Application.class, args);
}
}
说明
SpringBoot程序的入口是 SpringApplication.run() 方法:
- 第一个参数是一个类,该类被
@SpringBootApplication 注解所修饰,也就是主配置类; - 第二个参数是命令行参数;
- 该方法返回
ConfigurableApplicationContext 对象,即Spring容器;
SpringApplication.run()方法
修改代码如下:
public static void main(String[] args) {
var ctx = SpringApplication.run(Test0905Application.class, args);
System.out.println("=====================================");
var person = ctx.getBean("person", Person.class);
person.useAxe();
}
运行程序,结果如下:
SteelAxe constructor!
Person constructor!
StoneAxe constructor!
......
=====================================
I am Tom
Steel axe!
可见,默认情况下,在初始化Spring时,会初始化所有singleton的bean。
SpringApplication对象
public static void main(String[] args) {
var application = new SpringApplication(Test0905Application.class);
application.setLazyInitialization(true);
application.setBannerMode(Banner.Mode.OFF);
var ctx = application.run(args);
System.out.println("=====================================");
var person = ctx.getBean("person", Person.class);
person.useAxe();
}
运行程序,结果如下:
=====================================
SteelAxe constructor!
Person constructor!
I am Tom
Steel axe!
本例中,显式的实例化了一个 SpringApplication 对象,然后调用其 run() 方法运行,和前面的方式很类似。在运行之前,可以配置该实例对象。本例中,配置了懒加载,并且设置为不显示banner。
懒加载的效果:在初始化Spring容器时,并没有实例化任何bean,而是在 getBean() 的时候才实例化 Person ,因为把 SteelAxe 注入了 Person ,所以 SteelAxe 会在 Person 前实例化。 StoneAxe 没有被实例化。
SpringApplicationBuilder对象
public static void main(String[] args) {
var ctx = new SpringApplicationBuilder().sources(Test0905Application.class)
.bannerMode(Banner.Mode.OFF)
.lazyInitialization(true)
.run(args);
System.out.println("=====================================");
var person = ctx.getBean("person", Person.class);
person.useAxe();
}
运行程序,结果如下:
=====================================
SteelAxe constructor!
Person constructor!
I am Tom
Steel axe!
本例和前面的例子类似,只不过是显式的实例化了一个 SpringApplicationBuilder 对象,然后通过流式API的方式来配置,最后调用其 run() 方法运行。本例中,配置了懒加载,并且设置为不显示banner。
注: new 的优先级比 . 高,所以 new SpringApplicationBuilder().sources(Test0905Application.class) 等同于 (new SpringApplicationBuilder()).sources(Test0905Application.class) ,括号可以省略。
|