SpingBoot原理

2024-06-24 09:36
文章标签 原理 spingboot

本文主要是介绍SpingBoot原理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

配置优先级

SpringBoot配置的优先级从高到低依次为命令行参数、JNDI属性、Java系统属性、操作系统环境变量、外部配置文件、内部配置文件、注解指定的配置文件和编码中直接指定的默认属性。具体如下:

  1. 命令行参数:启动应用时,通过命令行指定的参数拥有最高优先级。例如,使用--server.port=8081会直接改变应用程序的端口,无论在什么配置文件中定义过该值。
  2. JNDI属性:这些属性由当前J2EE应用的环境提供,并具有第二优先级。
  3. Java系统属性:这些属性通过-D参数设置,并优先于操作系统环境变量。
  4. 操作系统环境变量:设置在操作系统级别的环境变量也具有较高的优先级。
  5. 外部配置文件:位于JAR包外部的配置文件(如application.propertiesapplication.yml)优先于内部的配置文件。特定环境的配置文件(如application-dev.properties)会覆盖通用配置文件(即application.properties)中的相应属性。
  6. 内部配置文件:在同一级目录下,不同后缀配置文件的优先级为:.properties最高,其次是.yml.yaml最低。相同后缀配置文件的优先级中,带环境名的配置文件(如application-dev.yml)高于不带环境名的(如application.yml)。
  7. 注解指定的配置文件:通过@PropertySource注解指定的配置文件优先级较低。
  8. 默认属性:通过SpringApplication.setDefaultProperties指定的默认属性拥有最低优先级。

下面是一个SpringBoot配置优先级的示例:

假设有以下配置文件:

  • application.properties(通用配置文件)
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=123456
  • application-dev.properties(开发环境配置文件)
server.port=8081
spring.datasource.url=jdbc:mysql://localhost:3306/dev_test
  • application-prod.properties(生产环境配置文件)
server.port=8082
spring.datasource.url=jdbc:mysql://localhost:3306/prod_test
  • 命令行参数:--server.port=9090

在启动应用时,会按照以下顺序加载配置:

  1. 命令行参数:--server.port=9090
  2. JNDI属性、Java系统属性、操作系统环境变量等其他来源的配置选项。
  3. 外部配置文件:application.propertiesapplication-dev.propertiesapplication-prod.properties
  4. 内部配置文件:application.propertiesapplication-dev.propertiesapplication-prod.properties
  5. 注解指定的配置文件。
  6. 编码中直接指定的默认属性。

最终,应用程序的端口号为9090,数据源URL为jdbc:mysql://localhost:3306/dev_test

Bean管理

获取Bean

在Spring框架中,获取Bean的方法有多种,包括通过ApplicationContext、实现ApplicationContextAware接口、继承抽象类等方法。具体如下:

通过ApplicationContext获取Bean

  • 可以在初始化时保存ApplicationContext对象,然后通过这个对象获取Bean。例如,使用ClassPathXmlApplicationContext加载配置文件并获取Bean:
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    MyBean myBean = (MyBean) applicationContext.getBean("myBean");
    
  • 适用于独立应用程序和基于Web的应用程序,这种方法简单直接,但需要显式加载配置文件。

通过实现ApplicationContextAware接口获取Bean

  • 可以实现ApplicationContextAware接口并将ApplicationContext对象注入到实现类中,从而随时获取Bean。例如:
    public class SpringUtils implements ApplicationContextAware {private static ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {SpringUtils.applicationContext = applicationContext;}public static <T> T getBean(String beanName) {return (T) applicationContext.getBean(beanName);}
    }
    
  • 这种方法的优点是不需要显式加载配置文件,Spring会自动注入ApplicationContext。

通过继承抽象类获取Bean

  • 可以继承ApplicationObjectSupportWebApplicationObjectSupport抽象类,调用父类的getApplicationContext()方法获取Spring容器对象。例如:
    @Service
    public class SpringContextHelper extends ApplicationObjectSupport {public Object getBean(String beanName) {return getApplicationContext().getBean(beanName);}
    }
    
  • 这种方法适用于需要在Spring容器管理的对象内部获取其他Bean的场景。

通过BeanFactory获取Bean

  • 虽然不推荐,但可以通过BeanFactory来获取Bean。例如,使用已废弃的XmlBeanFactory类:
    BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
    MyBean myBean = (MyBean) beanFactory.getBean("myBean");
    
  • 由于XmlBeanFactory已被废弃,这种方法不推荐使用,且存在潜在的维护问题。

通过Spring提供的工具类获取ApplicationContext对象

  • 在基于Web的应用程序中,可以通过WebApplicationContextUtils工具类从ServletContext对象获取ApplicationContext对象,再通过它获取需要的类实例。例如:
    ApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
    MyBean myBean = (MyBean) ac.getBean("myBean");
    
  • 这种方法适用于在Web应用程序中使用Spring框架的场景。

Bean作用域

Spring Bean的作用域定义了Bean在Spring容器中的生命周期和可见性,主要分为五种:singleton、prototype、request、session和application

作用域说明
singleton容器内同名称的bean只有一个实例(单例)(默认)
prototype每次使用该bean时会创建新的实例(非单例)
request每个请求范围内会创建新的实例(web环境中,了解)
session每个会话范围内会创建新的实例(web环境中,了解)
application每个应用范围内会创建新的实例(web环境中,了解)

 单例作用域(Singleton Scope)

  • 单例作用域是Spring的默认设置,在整个Spring IoC容器中只存在一个Bean实例。这意味着所有对该Bean的请求都会返回同一个实例。例如,在Spring配置文件中可以这样配置:
    <bean id="singletonBean" class="com.example.MySingletonBean" scope="singleton"/>
    
  • 适用于无状态的服务,如数据访问对象(DAO)、业务服务(Service)等,因为这些组件不需要存储特定于用户的信息,可以在多线程之间安全共享。

原型作用域(Prototype Scope)

  • 每次注入或通过getBean()方法调用时,都会创建一个新的Bean实例。这意味着每个请求得到的都是一个全新的对象。例如,在Spring配置文件中可以这样配置:
    <bean id="prototypeBean" class="com.example.MyPrototypeBean" scope="prototype"/>
    
  • 适用于需要频繁创建新对象的场景,如每次使用时需要新的状态或配置的Bean。

请求作用域(Request Scope)

  • 每个HTTP请求都会创建一个新的Bean实例,该实例仅在当前请求中有效,请求结束后即被销毁。这适用于需要在单个HTTP请求中保持状态的Bean。例如,在类上添加注解:
    @Component
    @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public class MyRequestBean {// ...
    }
    
  • 适用于处理表单提交或执行某个请求特定操作的组件。

会话作用域(Session Scope)

  • 每个HTTP会话都会创建一个新的Bean实例,该实例在会话结束前一直有效。这适用于需要在多个HTTP请求之间保持状态的Bean。例如,在类上添加注解:
    @Component
    @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public class MySessionBean {// ...
    }
    
  • 适用于需要跟踪用户会话信息的场景,如购物车或用户登录信息。

应用程序作用域(Application Scope)

  • 在ServletContext范围内,整个Web应用程序共享同一个Bean实例。该实例在应用程序启动时创建,应用程序关闭时销毁。例如,在类上添加注解:
    @Component
    @Scope(value = WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public class MyApplicationBean {// ...
    }
    
  • 适用于需要在整个Web应用程序中共享的状态或资源,如全局缓存或配置信息。

第三方Bean

在Spring框架中,第三方Bean的管理是通过配置类和注解来实现的,使得开发者可以在不修改原始代码的情况下定义和管理这些Bean。具体如下:

使用@Bean注解管理第三方Bean

  • 环境准备:需要创建一个Spring项目,并添加对应的依赖。例如,要管理Druid数据源,需要在pom.xml中添加Druid的依赖:
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.16</version>
</dependency>
  • 配置类和@Bean注解:在配置类中使用@Bean注解标注的方法来创建和管理第三方Bean。比如,为Druid数据源创建一个DataSource Bean:
@Configuration
public class SpringConfig {@Beanpublic DataSource dataSource() {DruidDataSource ds = new DruidDataSource();ds.setDriverClassName("com.mysql.jdbc.Driver");ds.setUrl("jdbc:mysql://localhost:3306/spring_db");ds.setUsername("root");ds.setPassword("root");return ds;}
}

使用独立的配置类

  • 导入式管理:通过在核心配置类中使用@Import注解,手动添加其他配置类。例如,可以将JdbcConfig导入到SpringConfig中:
@Configuration
public class JdbcConfig {@Beanpublic DataSource dataSource() {DruidDataSource ds = new DruidDataSource();// 相关配置return ds;}
}@Configuration
public class SpringConfig {@Import(JdbcConfig.class)// 其他配置...
}
  • 扫描式管理:使用@ComponentScan注解自动加载对应包中的配置类。这种方法虽然简便,但可能隐藏性太强,不推荐使用。
@Configuration
@ComponentScan("com.itheima.config")
public class SpringConfig {}

第三方Bean的依赖注入

  • 简单类型依赖注入:使用@Value注解可以注入简单类型的值,如字符串、整数等。例如,注入数据库URL和用户名:
public class JdbcConfig {@Value("jdbc:mysql://localhost:3306/spring_db")private String url;@Value("root")private String userName;@Beanpublic DataSource dataSource() {DruidDataSource ds = new DruidDataSource();ds.setUrl(url);ds.setUsername(userName);// 其他配置...return ds;}
}
  • 引用类型依赖注入:通过在Bean定义的方法中添加形参,Spring会自动装配同类型的Bean。例如,注入BookService:
@Bean
public DataSource dataSource(BookService bookService) {System.out.println(bookService);DruidDataSource ds = new DruidDataSource();// 属性设置return ds;
}

XML配置与注解配置的比对

  • 定义bean:XML配置使用标签;注解配置使用@Component及其衍生注解。
  • 依赖注入:XML配置通过标签设置属性;注解配置使用@Autowired、@Qualifier、@Value等。

SpringBoot原理

起步依赖

起步依赖是Spring Boot的核心特性之一,通过提供一系列预定义的依赖项集合来简化项目的搭建和依赖管理

起步依赖(Starter)在Spring Boot中起着至关重要的作用。它通过整合各种依赖库和自动配置,大大简化了开发者的工作。例如,当在项目中添加spring-boot-starter-web起步依赖时,会自动包含Spring MVC、Tomcat和其他Web开发所需的依赖,无需再手动逐个添加这些依赖。这样不仅提高了开发效率,还减少了因版本不兼容导致的问题。

起步依赖的原理是通过spring.factories文件和自动配置类来实现的。当项目引入某个Starter后,Spring Boot会在启动时读取META-INF/spring.factories文件中的配置,根据其中的自动配置类(如DataSourceAutoConfigurationWebMvcAutoConfiguration等)来自动配置相应的Bean。这些自动配置类通常包含一系列的条件注解(如@ConditionalOnClass@ConditionalOnMissingBean等),用于判断是否满足某些条件来决定配置哪些Bean。

除了使用官方提供的起步依赖外,Spring Boot还允许开发者自定义Starter。自定义Starter的命名通常遵循反向的格式,如官方的是spring-boot-starter-xxx,而自定义的则是xxx-spring-boot-starter。自定义Starter时,需要创建一个自动配置模块,并在其中定义相关的自动配置类和属性类,然后通过spring.factories文件将其与对应的Starter关联起来。

代码解释:

引入起步依赖:在项目的pom.xml文件中添加spring-boot-starter-web起步依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

自动配置类:当项目引入spring-boot-starter-web后,Spring Boot会在启动时读取META-INF/spring.factories文件,根据其中的自动配置类来自动配置相应的Bean。例如,WebMvcAutoConfiguration类会配置Spring MVC相关的Bean,如DispatcherServlet、ViewResolver等。

@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties(WebProperties.class)
@Import({ DispatcherServletAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class })
public class WebMvcAutoConfiguration {// ...
}

自定义属性类:除了自动配置类外,起步依赖还可能包含一些自定义的属性类,用于提供额外的配置选项。例如,WebProperties类提供了与Web相关的配置属性,如服务器端口号、上下文路径等。

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {private Integer port;private String contextPath;// ...
}

使用起步依赖:在项目中可以直接使用起步依赖提供的Bean,无需手动创建或注入。例如,通过@Autowired注解注入一个RestTemplate实例:

@RestController
public class MyController {@Autowiredprivate RestTemplate restTemplate;// ...
}

自定义Starter:除了官方提供的起步依赖外,开发者还可以自定义Starter。自定义Starter需要创建一个自动配置模块,并在其中定义相关的自动配置类和属性类,然后通过spring.factories文件将其与对应的Starter关联起来。

// 自动配置类
@Configuration
@ConditionalOnClass(MyService.class)
@Import(MyServiceAutoConfiguration.class)
public class MyServiceAutoConfiguration {// ...
}
// 属性类
@ConfigurationProperties(prefix = "myservice")
public class MyServiceProperties {private String url;// ...
}
// spring.factories文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.MyServiceAutoConfiguration

Conditional注解

@Conditional注解是Spring中的一个强大的条件化配置工具,它用于控制特定Bean或配置类在满足某些条件时才被加载到Spring容器中。@Conditional可以应用在@Bean注解的方法上,也可以应用在整个@Configuration类上。具体如下:

@Conditional注解的作用

  • @Conditional注解的主要作用是提供一种机制,允许根据是否满足特定的条件来决定是否创建某个Bean或者是否执行某个配置块。这种条件可以是类路径中是否存在某个类、属性文件中的某个属性值、环境变量的值等等。

@Conditional的常见使用方式

  • @ConditionalOnClass:当类路径中存在指定的类时,条件匹配成功。例如,当需要根据项目是否使用了某个特定的数据库驱动来调整数据源的配置时,可以使用这个注解。
  • @ConditionalOnMissingClass:与@ConditionalOnClass相反,当类路径中不存在指定的类时,条件匹配成功。
  • @ConditionalOnBean:当Spring容器中存在指定类型的Bean时,条件匹配成功。这常用于基于容器中是否有某个特定Bean来调整配置。
  • @ConditionalOnMissingBean:与@ConditionalOnBean相反,当Spring容器中不存在指定类型的Bean时,条件匹配成功。
  • @ConditionalOnProperty:当指定的属性值满足条件时(如属性存在且其值为true),条件匹配成功。这常用于根据配置文件中的设置来决定是否启用某个配置。
  • @ConditionalOnExpression:基于SpEL表达式的条件判断,当表达式结果为true时,条件匹配成功。这提供了更灵活的条件判断方式。

自定义条件化配置

  • 除了上述的常见@Conditional注解外,Spring还允许开发者通过实现Condition接口或继承AbstractCondition类来创建自定义的条件化配置。这允许开发者根据具体的应用场景和需求来编写自己的条件判断逻辑。

代码示例:

@Configuration
public class MyConfiguration {@Bean@ConditionalOnClass(name = "com.example.MyService")public MyService myService() {return new MyService();}@Bean@ConditionalOnProperty(name = "my.property", havingValue = "true")public MyComponent myComponent() {return new MyComponent();}@Bean@ConditionalOnExpression("${my.expression:false}")public MyOtherComponent myOtherComponent() {return new MyOtherComponent();}
}

这篇关于SpingBoot原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1089770

相关文章

MySQL中的MVCC底层原理解读

《MySQL中的MVCC底层原理解读》本文详细介绍了MySQL中的多版本并发控制(MVCC)机制,包括版本链、ReadView以及在不同事务隔离级别下MVCC的工作原理,通过一个具体的示例演示了在可重... 目录简介ReadView版本链演示过程总结简介MVCC(Multi-Version Concurr

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

Redis主从复制的原理分析

《Redis主从复制的原理分析》Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、... 目录Redis主从复制的原理主从复制概述配置主从复制数据同步过程复制一致性与延迟故障转移机制监控与维

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和

hdu4407容斥原理

题意: 有一个元素为 1~n 的数列{An},有2种操作(1000次): 1、求某段区间 [a,b] 中与 p 互质的数的和。 2、将数列中某个位置元素的值改变。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.Inpu

hdu4059容斥原理

求1-n中与n互质的数的4次方之和 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWrit

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类