iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Spring Boot底层原理实例分析
  • 129
分享到

Spring Boot底层原理实例分析

2023-06-29 20:06:08 129人浏览 薄情痞子
摘要

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

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

1. 底层注解@Configuration

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

项目基本结构:

Spring Boot底层原理实例分析

 两个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 配置文件方式是这样给容器添加组件的:

<beans>     <bean id="user01" class="com.menergy.boot.bean.User">        <property name="name" value="draGon"></property>        <property name="age" value="18"></property>    </bean>    <bean id="pet01" class="com.menergy.boot.bean.Pet">        <property name="name" value="dragonPet"></property></beans>

现在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;@Configuration(proxyBeanMethods = true)  //告诉SpringBoot 这是一个配置类 == 以前的配置文件public class MyConfig {        @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;//@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);    }}

输出的部分结果:

Spring Boot底层原理实例分析

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

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

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

该注解的属性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;@Configuration(proxyBeanMethods = true)  //告诉SpringBoot 这是一个配置类 == 以前的配置文件public class MyConfig {        @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;//@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));    }}

运行结果:

Spring Boot底层原理实例分析

可以看出,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;@Configuration(proxyBeanMethods = false)  //告诉SpringBoot 这是一个配置类 == 以前的配置文件public class MyConfig {        @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");}

运行结果:

Spring Boot底层原理实例分析

 可以看出,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类型的数组,说明这个注解的作用是向容器中导入一批组件

Spring Boot底层原理实例分析

接下来,实践一下:

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

Spring Boot底层原理实例分析

主类加入如下测试:

Spring Boot底层原理实例分析

 运行结果:

Spring Boot底层原理实例分析

 结果说明:

“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搜索。

Spring Boot底层原理实例分析

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

Spring Boot底层原理实例分析

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

Spring Boot底层原理实例分析

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

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

--结束END--

本文标题: Spring Boot底层原理实例分析

本文链接: https://www.lsjlt.com/news/326317.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Spring Boot底层原理实例分析
    这篇“Spring Boot底层原理实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Spring ...
    99+
    2023-06-29
  • Spring boot整合tomcat底层原理剖析
    目录本文结论spring-boot-starter-web内部有什么?TomcatServletWebServerFactory的作用:获取WebServer对象spring boo...
    99+
    2022-11-13
    Spring boot整合tomcat Spring boot 整合tomcat原理
  • Spring Boot 底层原理基础深度解析
    目录1. 底层注解@Configuration2. 底层注解@Import3. 底层注解@Conditional1. 底层注解@Configuration @Configuratio...
    99+
    2022-11-13
  • Spring AOP底层原理及代理模式实例分析
    这篇文章主要介绍“Spring AOP底层原理及代理模式实例分析”,在日常操作中,相信很多人在Spring AOP底层原理及代理模式实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”S...
    99+
    2023-06-30
  • Spring底层原理深入分析
    目录bean生命周期推断构造方法的底层原理1、使用哪个构造方法2、如果有参把哪个bean对象赋值给入参AOP实现原理spring事务@Configuration循环依赖为什么会出现循...
    99+
    2022-11-13
  • Spring Boot的底层原理是什么
    这篇文章主要讲解了“Spring Boot的底层原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring Boot的底层原理是什么”吧!1.基于你对springboot的理解描述...
    99+
    2023-06-27
  • HashMap底层原理分析
    小编给大家分享一下HashMap底层原理分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!众所周知,HashMap是一个用于存储Key-Value键值对的集合,每一个键值对也叫做Entry。这些个键值对(Entry)分散存...
    99+
    2023-06-27
  • Spring底层事务原理解析
    目录一、@EnableTransactionManagement工作原理二、Spring事务基本执行原理四、Spring事务传播机制五、Spring事务传播机制分类六、Spring事...
    99+
    2022-12-10
    Spring底层事务原理 Spring底层事务 Spring底层原理
  • spring boot集成kafka的spring-kafka底层原理是什么
    这篇“spring boot集成kafka的spring-kafka底层原理是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一...
    99+
    2023-06-29
  • Java LinkedHashMap 底层实现原理分析
    目录添加元素 删除元素 更新元素查找元素 其他方法 迭代器总结 在实现上,LinkedHashMap很多方法直接继承自HashMap,仅为维护双向链表覆写了部分方法。所以,要看懂 L...
    99+
    2022-11-12
  • 深度剖析Spring Cloud底层原理
    毫无疑问,Spring Cloud 是目前微服务架构领域的翘楚,无数的书籍博客都在讲解这个技术。不过大多数讲解还停留在对 Spring Cloud 功能使用的层面,其底层的很多原理,很多人可能并不知晓。实际上,Spring Cloud 是一...
    99+
    2023-06-05
  • C++中string底层原理的示例分析
    小编给大家分享一下C++中string底层原理的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、深浅拷贝浅拷贝:在实现string时要是不实先strin...
    99+
    2023-06-25
  • Golang底层原理解析String使用实例
    目录引言String底层stringStruct结构引言 本人因为种种原因(说来听听),放弃大学学的java,走上了golang这条路,本着干一行爱一行的情怀,做开发嘛,不能只会使用...
    99+
    2022-11-11
  • 微信小程序底层实现原理的示例分析
    这篇文章给大家分享的是有关微信小程序底层实现原理的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。  根据小程序开发文档-框架(https://mp.weixin.qq.com/debug/wxadoc/d...
    99+
    2023-06-26
  • Java中集合底层原理分析
    这篇文章将为大家详细讲解有关Java中集合底层原理分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、Collection集合Collection接口是单列集合类的父接口,这种集合可以将数据一个一个的存...
    99+
    2023-06-15
  • Docker基本概念和底层原理的示例分析
    这篇文章将为大家详细讲解有关Docker基本概念和底层原理的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Docker架构图:我们依照Docker架构图进行Docker基础概念的说明。1、Dock...
    99+
    2023-06-29
  • spring aop底层原理及如何实现
    目录前言 使用 源码分析 总结 前言 相信每天工作都要用spring框架的大家一定使用过spring aop,aop的概念是面向切面编程,相对与传统的面向对象编程oop,aop更关...
    99+
    2022-11-12
  • spring aop底层原理及实现方法
    这篇文章主要介绍spring aop底层原理及实现方法,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!使用要分析spring aop的底层原理,首先要会使用,先创建一个普通maven webapp项目,引入spring...
    99+
    2023-06-14
  • Spring Boot Starters使用实例分析
    本篇内容主要讲解“Spring Boot Starters使用实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring Boot Starters使用...
    99+
    2022-10-19
  • Go语言中并发goroutine底层原理的示例分析
    小编给大家分享一下Go语言中并发goroutine底层原理的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、基本概念①并发、并行区分1.概念并发:同一时间段内一个对象执行多个任务,充分利用时间并行:同一时刻,多个...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作