千家信息网

Spring Boot底层原理实例分析

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,这篇"Spring Boot底层原理实例分析"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看
千家信息网最后更新 2026年10月31日Spring Boot底层原理实例分析

这篇"Spring Boot底层原理实例分析"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"Spring Boot底层原理实例分析"文章吧。

1. 底层注解@Configuration

@Configuration 注解主要用于给容器添加组件(Bean),下面实践其用法:

项目基本结构:

两个Bean组件:

User.java

package com.menergy.boot.bean; /** * 用户 */public class User {    private String name;    private Integer age;    public User() {    }    public User(String name, Integer age) {        this.name = name;        this.age = age;    public String getName() {        return name;    public void setName(String name) {    public Integer getAge() {        return age;    public void setAge(Integer age) {    @Override    public String toString() {        return "User{" +                "name='" + name + '\'' +                ", age=" + age +                '}';}

Pet.java

package com.menergy.boot.bean; /** * 宠物 */public class Pet {    private String name;    public Pet() {    }    public Pet(String name) {        this.name = name;    public String getName() {        return name;    public void setName(String name) {    @Override    public String toString() {        return "Pet{" +                "name='" + name + '\'' +                '}';}

以前Spring 配置文件方式是这样给容器添加组件的:

                                     

现在Spring Boot 已经不写上面的xml配置了,在Spring Boot 底层可以用@Configuration 注解给容器中添加组件。如下:

注解类MyConfig.java

package com.menergy.boot.config; import com.menergy.boot.bean.Pet;import com.menergy.boot.bean.User;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * 1. 配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的 * 2. 配置类本身也是组件 * 3. proxyBeanMethods: 代理Bean 方法: *      Full(proxyBeanMethods = true): 外部无论对配置类中的这个组件注册方法调用多少次,获取的都是之前注册容器中的单实例对象 *      Lite(proxyBeanMethods = false): 在容器中不会保留代理对象,外部多次调用这些组件时,每次调用都会产生一个新的对象 *      用于解决组件依赖场景 */@Configuration(proxyBeanMethods = true)  //告诉SpringBoot 这是一个配置类 == 以前的配置文件public class MyConfig {    /**     * 外部无论对配置类中的这个组件注册方法调用多少次,获取的都是之前注册容器中的单实例对象     * @return     */    @Bean   //给容器中添加组件,以方法名作为主键id,返回类型就是组件类型,返回值就是组件在容器中的实例    public User user01(){        return new User("dragon",18);    }    @Bean("tomcatPet")    public Pet pet01(){        return new Pet("dragonPet");}

主类MainApplication.java 中测试调用:

package com.menergy.boot; import com.menergy.boot.bean.Pet;import com.menergy.boot.bean.User;import com.menergy.boot.config.MyConfig;import org.springframework.boot.SpringApplication;import org.springframework.boot.SpringBootConfiguration;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.context.annotation.ComponentScan;import sun.awt.geom.AreaOp;/** * 主程序类 * 这个注解相当于告诉Spring Boot: 这是一个Spring boot 应用 *///@SpringBootApplication@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan("com.menergy.boot")public class MainApplication {    public static void main(String[] args) {//        SpringApplication.run(MainApplication.class, args);        // 1.返回IOC容器        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);        // 2.查看容器里面的容器        String[] names = run.getBeanDefinitionNames();        for (String name : names) {            System.out.println(name);        }        // 3. 从容器中获取组件        Pet pet1 = run.getBean("tomcatPet", Pet.class);        Pet pet2 = run.getBean("tomcatPet", Pet.class);        System.out.println("组件: " + (pet1 == pet2));        // 4. com.menergy.boot.config.MyConfig$$EnhancerBySpringCGLIB$$3779496a@67a056f1        MyConfig myConfig = run.getBean(MyConfig.class);        System.out.println(myConfig);        //如果@Configuration(proxyBeanMethods = true)代理对象调用方法, Spring Boot 总会检查这个组件是否在容器中有,如果有则不会新建,保持组件单实例。        User user01 = myConfig.user01();        User user02 = myConfig.user01();        System.out.println(user01 == user02);    }}

输出的部分结果:

上面的例子,重点落在@Configuration(proxyBeanMethods = true) 注解。 该注解告诉SpringBoot ,被注解的类是一个配置类, 相当于以前的配置文件xml中的"bean配置"。该注解有如下特性:

1. 该注解的配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的。

2. 被这个注解的配置类本身也是组件。

3. 该注解的属性proxyBeanMethods 可以通过"true" 和 "false" 配置值,来控制使用的模式:

(1)Full模式(proxyBeanMethods = true): 为true时,外部无论对配置类中的组件注册方法调用多少次,获取的都是之前注册容器中的单实例对象。

(2)Lite模式(proxyBeanMethods = false): 为false时,在容器中不会保留代理对象,外部多次调用这些组件时,每次调用都会产生一个新的对象。

这两种模式的存在主要用于解决组件依赖场景。

1和2 两点特性上面的例子中都有体现, 接下来重点实践第三点特性:

实践proxyBeanMethods:

基于上面的例子,首先修改User.java类,加上宠物Pet的依赖:

package com.menergy.boot.bean; /** * 用户 */public class User {    private String name;    private Integer age;    private Pet pet;    public User() {    }    public User(String name, Integer age) {        this.name = name;        this.age = age;    public User(String name, Integer age, Pet pet) {        this.pet = pet;    public String getName() {        return name;    public void setName(String name) {    public Integer getAge() {        return age;    public void setAge(Integer age) {    public Pet getPet() {        return pet;    public void setPet(Pet pet) {    @Override    public String toString() {        return "User{" +                "name='" + name + '\'' +                ", age=" + age +                ", pet=" + pet +                '}';}

在配置类MyConfig.java 中加入user01对象对用pet对象,同时使用Full模式(proxyBeanMethods = true):

package com.menergy.boot.config; import com.menergy.boot.bean.Pet;import com.menergy.boot.bean.User;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * 1. 配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的 * 2. 配置类本身也是组件 * 3. proxyBeanMethods: 代理Bean 方法: *      Full模式(proxyBeanMethods = true): 外部无论对配置类中的这个组件注册方法调用多少次,获取的都是之前注册容器中的单实例对象 *      Lite模式(proxyBeanMethods = false): 在容器中不会保留代理对象,外部多次调用这些组件时,每次调用都会产生一个新的对象 *      用于解决组件依赖场景 */@Configuration(proxyBeanMethods = true)  //告诉SpringBoot 这是一个配置类 == 以前的配置文件public class MyConfig {    /**     * 外部无论对配置类中的这个组件注册方法调用多少次,获取的都是之前注册容器中的单实例对象     * @return     */    @Bean   //给容器中添加组件,以方法名作为主键id,返回类型就是组件类型,返回值就是组件在容器中的实例    public User user01(){        User dragonUser = new User("dragon",18);        // User 组件依赖了Pet 组件,当proxyBeanMethods 为 true 时,这种依赖关系成立        dragonUser.setPet(pet01());        return dragonUser;    }    @Bean("tomcatPet")    public Pet pet01(){        return new Pet("dragonPet");}

主类MainApplication.java:

package com.menergy.boot; import com.menergy.boot.bean.Pet;import com.menergy.boot.bean.User;import com.menergy.boot.config.MyConfig;import org.springframework.boot.SpringApplication;import org.springframework.boot.SpringBootConfiguration;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.context.annotation.ComponentScan;import sun.awt.geom.AreaOp;/** * 主程序类 * 这个注解相当于告诉Spring Boot: 这是一个Spring boot 应用 *///@SpringBootApplication@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan("com.menergy.boot")public class MainApplication {    public static void main(String[] args) {//        SpringApplication.run(MainApplication.class, args);        // 1.返回IOC容器        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);        // 2.查看容器里面的容器        String[] names = run.getBeanDefinitionNames();        for (String name : names) {            System.out.println(name);        }        // 3. 从容器中获取组件        Pet pet1 = run.getBean("tomcatPet", Pet.class);        Pet pet2 = run.getBean("tomcatPet", Pet.class);        System.out.println("组件: " + (pet1 == pet2));        // 4. com.menergy.boot.config.MyConfig$$EnhancerBySpringCGLIB$$3779496a@67a056f1        MyConfig myConfig = run.getBean(MyConfig.class);        System.out.println(myConfig);        //如果@Configuration(proxyBeanMethods = true)代理对象调用方法, Spring Boot 总会检查这个组件是否在容器中有,如果有则不会新建,保持组件单实例。        User user01 = myConfig.user01();        User user02 = myConfig.user01();        System.out.println(user01 == user02);        //测试 @Configuration(proxyBeanMethods = true/false)        User user011 = run.getBean("user01", User.class);        Pet tomcatPet = run.getBean("tomcatPet", Pet.class);        System.out.println("用户的宠物:" + (user011.getPet() == tomcatPet));    }}

运行结果:

可以看出,Full模式(proxyBeanMethods = true)时,输出true,说明是从容器中获取的同一个组件(用户的宠物就是容器中的宠物)。

接下来,改用Lite模式(proxyBeanMethods = false):即基于上面实例,将配置类MyConfig.java 中的注解的属性proxyBeanMethods 改成false值,如下:

MyConfig.java:

package com.menergy.boot.config; import com.menergy.boot.bean.Pet;import com.menergy.boot.bean.User;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * 1. 配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的 * 2. 配置类本身也是组件 * 3. proxyBeanMethods: 代理Bean 方法: *      Full模式(proxyBeanMethods = true): 外部无论对配置类中的这个组件注册方法调用多少次,获取的都是之前注册容器中的单实例对象 *      Lite模式(proxyBeanMethods = false): 在容器中不会保留代理对象,外部多次调用这些组件时,每次调用都会产生一个新的对象 *      用于解决组件依赖场景 */@Configuration(proxyBeanMethods = false)  //告诉SpringBoot 这是一个配置类 == 以前的配置文件public class MyConfig {    /**     * 外部无论对配置类中的这个组件注册方法调用多少次,获取的都是之前注册容器中的单实例对象     * @return     */    @Bean   //给容器中添加组件,以方法名作为主键id,返回类型就是组件类型,返回值就是组件在容器中的实例    public User user01(){        User dragonUser = new User("dragon",18);        // User 组件依赖了Pet 组件,当proxyBeanMethods 为 true 时,这种依赖关系成立        dragonUser.setPet(pet01());        return dragonUser;    }    @Bean("tomcatPet")    public Pet pet01(){        return new Pet("dragonPet");}

运行结果:

可以看出,Lite模式(proxyBeanMethods = false)时,输出false,说明是从容器中获取的不是同一个组件(用户的宠物不是容器中的宠物, 相当于new 了另一个对象)。

总结:配置类包括了全模式(Full)和轻量级模式(Lite)两种。当proxyBeanMethods 是true时,Spring Boot 每次都会检查容器中是否有相应的组件,如果proxyBeanMethods 是false, 则不检查容器中是否有没有相应的组件,而是直接new一个。这也是Spring Boot 新增的一个很重要的特性。

最佳实战:如果只是向容器中增加组件,别的地方也不会调用这个组件,我们可以将其调为false 模式,这样Spring Boot 启动起来非常快,加载起来也非常快。 如果别的地方明显要用,要依赖,我们就把其调成true,保证依赖的组件就是容器中的组件。

注: 前面的例子中,在配置类中用到@Been 注解来指定组件, 其实Spring Boot 底层还用到了其他一些以前常用的注解来指定组件,包括@Component、@Controller、@Service、@Repository。这些类似于@Been 原理,也是用于向容器中注册组件。

除此之外,底层还用到@ComponentScan 注解来说明容器的包扫描,还有@Import 和@Conditional 来向容器添加组件。很多注解是以前常用的,接下来主要说明@Import 和@Conditional 注解。

2. 底层注解@Import

首先,从@Import 注解类中可以看到该注解的定义,以及知道其属性是一个Class类型的数组,说明这个注解的作用是向容器中导入一批组件:

接下来,实践一下:

首先在配置类上加入@Import 注解,并向容器中导入两个组件,一个是自己定义的类,一个是从第三方Jar 包中任意的一个类:

主类加入如下测试:

运行结果:

结果说明:

"com.menergy.boot.bean.User" 是通过@Import 导入的组件。(默认的组件名称是全类名)

"user01" 是之前用@Bean 方法添加进去的

"org.apache.logging.log4j.util.StringBuilders@4482469c" 也是通过@Import 导入的组件。

3. 底层注解@Conditional

@Conditional 是条件装配:当满足@Conditional指定的条件时, 才向容器中注入组件。

在全局Jar包中搜索@Conditional 类:双击Shift键,选择Classes,输入@Conditional搜索。

打开Conditional 类后,"Ctrl + H" 键调出这个类的继承树:

注:如果快捷键失效,请确定如下快捷键设置:

从前面的@Conditional 的继承树可以看出,@Conditional 有非常多的派生注解,每个注解都代表不同的功能,从派生注解的注解名称可以大概知道其功能用意,例如@ConditionalOnBean 注解代表当容器中存在某个Bean时才干某些事情, @ConditionalOnMissingBean 注解代表当容器中不存在某个Bean时才干某些事情。

以上就是关于"Spring Boot底层原理实例分析"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。

组件 容器 配置 注解 实例 对象 方法 模式 底层 就是 代理 宠物 类型 内容 文件 用户 结果 这是 面的 原理 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 广州紫鲸互联网科技有限公司 湖南永感互联网科技有限公司 互联网与科技发展 喔噻互联网科技 互联网科技论坛 卓越科技互联网 招聘 广州优美互联网科技 银川新华互联网科技职业技术培训学校图片 赶超互联网科技 微信多开 区块链结合互联网科技 南通创西澳互联网科技有限公司 四川互联网展示科技馆设计 互联网科技数字货币 互联网科技融合创新 普陀区互联网教育科技管理办法 互联网高科技行业有哪些企业 美国五大互联网科技公司市值多少 悟空问答互联网科技 安徽零酒互联网科技有限公司 数字科技和互联网金融哪个好 青岛互联网科技公司 互联网 卓越科技 互联网金融科技平台 无锡溥仪互联网科技有限公司 互联网和高科技公司 阿里互联网科技企业 互联网企业科技类企业如何做账 福州德业互联网科技 普陀区互联网教育科技管理办法 北京互联网科技类企业分布
0