SpringBoot的自动装配机制

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介:

前言

image.png

SpringBoot主启动类被@SpringBootApplication所修饰,点击进去该注解,出现上图,会发现其为组合注解,本章节将会基于注解进行解释其自动装配在源码层面是怎么实现的,完整的注解调用链路如下图所示:

1597476479704-a5227212-d027-43a7-a721-eb6cdc730a61.png

1.元注解

@Target注解


  • 注解的作用目标
  • @Target(ElementType.TYPE)                                           //接口、类、枚举、注解
  • @Target(ElementType.FIELD)                                         //字段、枚举的常量
  • @Target(ElementType.METHOD)                                   //方法
  • @Target(ElementType.PARAMETER)                              //方法参数
  • @Target(ElementType.CONSTRUCTOR)                        //构造函数
  • @Target(ElementType.LOCAL_VARIABLE)                     //局部变量
  • @Target(ElementType.ANNOTATION_TYPE)                //注解
  • @Target(ElementType.PACKAGE)                                 //包    

@Retention注解


  • 修饰注解,是注解的注解,称为元注解
  • SOURCE,     // 编译器处理完Annotation后不存储在class中  
  • CLASS,       // 编译器把Annotation存储在class中,这是默认值  
  • RUNTIME  // 编译器把Annotation存储在class中,可以由虚拟机读取,反射需要

@Documented注解


  • 这个Annotation可以被写入javadoc


上述三个元注解也是实现自定义注解的基础,不是很清楚的可以先看这篇:自定义注解

@Inherited 注解


@SpringBootApplication注解被@Inherited修饰,则SpringBoot主启动类也就具备了@SpringBootApplication注解的:

@SpringBootConfiguration

@EnableAutoConfiguration

@ComponentScan

2.@ComponentScan注解


这个注解原来在SpringFramework中比较常见,而且其出现位置为配置文件:spring配置文件的applicationContext.xml或者springmvc的配置文件中,用来标识:扫描的包路径,这样就可以将我们定义的注解扫描进去。

在SpringBoot中,其关键作用是:默认扫描当前配置类所在包及子包下的所有组件, exclude 属性会将主启动类、自动配置类屏蔽掉

2.1 TypeExcludeFilter注解

image.png

其核心代码简单PO出,依赖BeanFactory,这个BeanFactory就是SpringFramework接口体系中的顶层,定义了基本的方法,如:getBean,containsBean,isSingleton,getType,isTypeMatch等。如下图(体系要比这个更丰富,推荐大家自己在Idea中生成查看,看SpringBoot源码的前提,建议先看Spring源码):

1.png

TypeExcludeFilter核心方法为match(),其关键作用在于:拓展组件的过滤提供一种扩展机制,能让我们向IOC容器中注册一些自定义的组件过滤器,以在包扫描的过程中过滤它们会从 BeanFactory 中获取所有类型为 TypeExcludeFilter 的组件,去执行自定义的过滤方法。

2.2 AutoConfigurationExcludeFilter注解

image.png

其核心方法和TypeExcludeFilter一样,match()方法,但是实现有所区别,AutoConfigurationExcludeFilter的核心是:判断是否是一个配置类,且同时是否是一个自动配置的配置类

2.3 问题:SpringBoot怎么过滤不需要的组件


面试题】:Spring IOC容器在boot中也是存在的对吧,那有一些Bean我不想在启动时就注入IOC容器,这种情况有遇到过吗?

【个人理解】:目前还没遇到,不过要是实现的话,在启动类上加上@ComponentScan注解,在value中写上指定的:*.class是可以实现的【参见2.4小结】,或继承TypeExcludeFilter ,重写match方法,如默认会加载com.test.TestService这个bean,则重写的方法中,

public class MyTypeExcludeFilter extends TypeExcludeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
            throws IOException {
        if("com.test.TestService".equals(metadataReader.getClassMetadata().getClassName())){
            return false;
        }
        return true;
    }
}

或者直接在boot配置文件中添加,其是支持的【但是我没细究如何配置,这个百度下应该就有】,如下:

2.png

2.4 小结

上述之后我们都能知道两个Exclude都有match方法,但是匹配什么?过滤什么?至少我在第一次看的时候还是很懵的,目前我的认知总结如下,可能不是很准确,提供出来给大家参考一下:

@ComponentScan注解会扫描Bean完成IOC注入,但是有一部分我们是不需要注入进IOC容器的,那么这种场景下我们就可以借助于我们这一小章节的注解进行实现,其实现方法就是:

image.png

import org.springframework.context.annotation.FilterType;

import org.springframework.context.annotation.ComponentScan;

@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {TestBean.class})})

这种方式是官方给的一个参考方式,但是我们也可以清楚的看到弊端:仅适用于少量的,如果需要规避的扫描类很多,这个classes将会变的非常冗杂,当然也有很多解决方案,如继承TypeExcludeFilter ,重写match方法,更多方式自行百度下就行。

关于@AutoConfigurationExcludeFilter,能搜到的资料很少,区别就在于多了一部分AutoConfiguration,所以我目前的认知是:二者都能用来处理组件过滤,但是是TypeFilter接口的两种实现,一种主要服务于主启动类组件,一种服务于自动配置的组件,二者结合实现一个完整的组件过滤

6.png

图的BeanFactoryAware,BeanClassLoaderAware在Spring IOC容器中比较常见,也是Spring的Bean生命周期中会遇到的组件,这里就不再赘述,有需要的百度学习下即可


3.@SpringBootConfiguration注解

image.png

官方给的解释也是:@SpringBootConfiguration 是对 @Configuration注解(这个我们可能就比较熟悉了,不了解的参考:@Configuration)的一种封装,在上图我们也可看出,其核心作用是:标注在配置类上,且是主启动类(如果@Configuration标注就不必强调是主启动类),基于这个注解,其所在的包路径位置获取之后EnableAutoConfiguration(第4节详细论述)注解扫描的依据,进而扫描出配置文件。

这里也说明了为什么SpringBoot的主启动类,我们是放在包的最外层,因为只有这样,我们的basePackage才能够获取到全部组件。

4.@EnableAutoConfiguration注解


我们简单了解下SpringFramework的装配吧:

其中:@Repository,@Service,@Controller为Component的衍生注解,后面配置实现可以参考这里:链接

【SpringFramework总结】

基于以上三种任意一种方式(我们常用的还是第一种注解模式),就可以实现对应的装配机制,所谓的装配就是告诉我们的Spring我们要用哪些Bean,顶层的BeanFactory的子类ApplicationContext帮我们实现底层细节【IOC接口体系2.3小结有简略版】,IOC容器帮我们完成Bean的注入实现,其缓存机制帮我们规避循环依赖,以实现一个装配体系。


【SpringBoot自动装配开始】


这里我觉得还是直接拷贝其官方解释更好,也顺便翻译一下(个人理解可能会有偏差)

Enable auto-configuration of the Spring Application Context, attempting to guess and
configure beans that you are likely to need. Auto-configuration classes are usually
applied based on your classpath and what beans you have defined. For example, if you
have {@code tomcat-embedded.jar} on your classpath you are likely to want a
{@link TomcatServletWebServerFactory} (unless you have defined your own
{@link ServletWebServerFactory} bean).
-- Spring的自动配置上下文,会大致预估你需要使用的Bean,其依据就是项目中classpath中的jar、配置文件+我们自己定义的Bean(借助于上面SpringFramework的方式之一),举例:比如引入了tomcat-embedded.jar,那么自动配置认为你大概率会使用TomcatServletWebServerFactory,于是就帮你初始化,除非你自己定义了一个自定义Bean:ServletWebServerFactory,即:自定义的优先级>系统默认配置,同级覆盖
    
When using {@link SpringBootApplication @SpringBootApplication}, the auto-configuration
of the context is automatically enabled and adding this annotation has therefore no
additional effect.
-- 当使用@SpringBootApplication注解时,自动配置注解再加到主启动类上不会有什么用,也是因为@SpringBootApplication注解是组合注解,其内部已经包含了自动配置的注解
    
Auto-configuration tries to be as intelligent as possible and will back-away as you
define more of your own configuration. You can always manually {@link #exclude()} any
configuration that you never want to apply (use {@link #excludeName()} if you don't
have access to them). You can also exclude them via the
{@code spring.autoconfigure.exclude} property. Auto-configuration is always applied
after user-defined beans have been registered.
 -- 自动化配置会尽可能地智能化,当你的配置和自动化配置一致时,自动化配置自动就会失效。即用户配置>自动化配置权限。对于你不需要自动化配置的,可以通过exclude进行手动排除(就像上面2.3小结我们举例的
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {TestBean.class})})),当然你也可以在配置文件中进行排除:spring.autoconfigure.exclude。
  最后说了下,自动化配置的永远在用户定义的Bean注册之后进行。
    
The package of the class that is annotated with {@code @EnableAutoConfiguration},
usually via {@code @SpringBootApplication}, has specific significance and is often used
as a 'default'. For example, it will be used when scanning for {@code @Entity} classes.
It is generally recommended that you place {@code @EnableAutoConfiguration} (if you're
not using {@code @SpringBootApplication}) in a root package so that all sub-packages
and classes can be searched.
-- 就是说@SpringBootApplication,@EnableAutoConfiguration标注的类是具备意义的,一般会被系统认作默认配置启动类,因此建议标注有 @SpringBootApplication注解的文件最好放在根包中,这样所有的子包才能被扫描到。
    
Auto-configuration classes are regular Spring {@link Configuration @Configuration}
beans. They are located using the {@link SpringFactoriesLoader} mechanism (keyed
against this class). Generally auto-configuration beans are
{@link Conditional @Conditional} beans (most often using
{@link ConditionalOnClass @ConditionalOnClass} and
{@link ConditionalOnMissingBean @ConditionalOnMissingBean} annotations).
    
-- 被@Configuration标注的Spring的Bean就被认为是一个配置类,等同于ApplicationContext.xml,采用SpringFactoriesLoader机制,自动装配Bean常用以下注解实现:@Conditional,@ConditionalOnClass,@ConditionalOnMissingBean

其完整代码如下所示,可看到它也是一个组合注解,主要包括4个元注解+2个自定义注解,所以这两个注解应该就是帮我们实现自动化配置的核心所在了。

image.png

4.1 @AutoConfigurationPackage注解概述

image.png

这个注解看起来就比较简单了,没有特别的代码,也只有4个元注解+1个自定义注解,但是可以看到这个注解@Import和上面的@EnableAutoConfiguration内部的value还是不一样的,区别在4.2讲解。

  • @EnableAutoConfiguration:AutoConfigurationImportSelector.class
  • @AutoConfigurationPackage:AutoConfigurationPackages.Registrar.class

前面我们也有提到,主启动类必须放在所有自定义组件的包的最外层,以保证Spring能扫描到它们,就是@AutoConfigurationPackage发挥的作用,【作用小结】:保证Spring扫描到所有子包,完成资源的加载.

其实现原理如下4.1.1:


4.2 AutoConfigurationPackage实现原理


在4.1的图可看到,他引入了一个@Import注解,这个注解引入了AutoConfigurationPackages.Registrar

image.png

Register 实现了 ImportBeanDefinitionRegister 接口,通过它实现向IOC容器手动注册组件,在重写的 registerBeanDefinitions 方法中,调用外部类的 AutoConfigurationPackages 的 register 方法,其中传参为:new PackageImport(metadata).getPackageName(),而实例化PackageImport的有参构造方法:

PackageImport(AnnotationMetadata metadata) {
    this.packageName = ClassUtils.getPackageName(metadata.getClassName());
}

可看到是通过metadata的类名来获取所在的包名,所以需要明确下metadata是什么?怎么获取的?为什么通过这个就可以获取到对应根包路径?

/**
 * Register bean definitions as necessary based on the given annotation metadata of
 * the importing {@code @Configuration} class.
 * <p>Note that {@link BeanDefinitionRegistryPostProcessor} types may <em>not</em> be
 * registered here, due to lifecycle constraints related to {@code @Configuration}
 * class processing.
 * <p>The default implementation is empty.
 * @param importingClassMetadata annotation metadata of the importing class
 * @param registry current bean definition registry
 */
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
}

4.2.1.metadata是什么及获取方式?

这个是官方提供的registerBeanDefinitions方法的释义,重点就在:

@param importingClassMetadata annotation metadata of the importing class,即:传参是导入类的原信息,实际就是被@Import标注的class信息,实际就是我们每个SpringBoot启动类的类信息【这里我们能知道,他通过Register类重写的registerBeanDefinitions方法获取被@Import标注的类信息,即SpringBoot启动类的类信息,而启动类我们都是放在根包下面的,所以大概知道个端倪了】

4.2.2.metadata能做什么?

拿到了metadata这个形参,具体做什么就是这个方法要做的了,所以我们再回头看下这个4.1.1中的register方法。

image.png

大致思路是:首先会判断当前IOC容器中,是否已经有这个AutoConfigurationPackages,其中的BEAN是这个类的静态变量:private static final String BEAN = AutoConfigurationPackages.class.getName();

如果已经有了,则将其添加到basePackage【这个我们前面也有提到,实际就是一个去重之后是String数组,存储根包及所有子包组件,包含系统默认组件+用户自定义组件】中

如果没有,会创建一个新的Bean【存放在一个ConcurrentHashMap中维护,初始化size=256,在else逻辑第三行会发现调用了一样方法:addIndexedArgumentValue,不同之处在于这里的第二个参数是直接传入的packageNames,即直接将主启动类的包名添加到basePackage中.即该注解还会帮我们完成Bean的注册与缓存。


4.2.3.问题:basePackages去重?为什么if-else两套?


面试题】:register方法能获取所有的basePackage你刚讲到了,但是他怎么做到去重的呢?为什么这里需要有if-else两套逻辑,而且两套逻辑里的packageNames一个是直接添加,一个是调用方法呢?

【个人理解】:去重就是借助于一个Set做到的,如下源码:

private static String[] addBasePackages(ConstructorArgumentValues constructorArguments, String[] packageNames) {
    String[] existing = (String[]) constructorArguments.getIndexedArgumentValue(0, String[].class).getValue();
    Set<String> merged = new LinkedHashSet<>();
    // 添加现有全部
    merged.addAll(Arrays.asList(existing));
    // 添加此次
    merged.addAll(Arrays.asList(packageNames));
    // 返回全部
    return StringUtils.toStringArray(merged);
}

之所以就if-else两套逻辑,也是和Spring的Bean的IOC工厂一样,Bean是有缓存的,Bean的创建是单例+缓存进行存储的,底层是借助于一个size=256的ConcurrentHashMap【可能会问你Map体系了,顺便转移话题深度】进行存储,可以规避一些性能损耗,也可以快速响应,第一次那就先创建再添加,第一次创建的肯定没有添加到basePackage中,之后可能就已经添加过了,就需要进行去重了。一句带过就是:首次创建的Bean不会存在packageNames重复问题,而已存在的Bean可能已经添加过,需要借助于Set进行去重,保证最后的basePackages都是唯一的。


4.2.4.小结

结合以上,我们能知道SpringBoot的自动配置,重要的一环就是获取全部的basePackage,而获取的方式是借助于@AutoConfigurationPackage 注解所引入的AutoConfigurationPackages.Register,对应的就是AutoConfigurationPackages下面的Register方法,该方法重写的registerBeanDefinitions方法帮我们获取全部的basePackages,同时帮我们做Bean注入,缓存,packageNames去重处理,以保证获取的name均为唯一。

4.3 AutoConfigurationImportSelector[核心]

注意每一层调用关系不要混乱,4.1-4.2平级,4.1.1是4.1的调用,4.1主要作用是获取basePackage,4.1.1是它的实现细节。

下面是AutoConfigurationImportSelector的继承关系视图,可以看到他继承了一系列的Aware接口,这也就保证了Bean在被初始化之后,能够获取对应的Aware资源【Aware系列在Spring的Bean声明周期中有强烈存在感,不是很清楚的可以百度下】

5.png

4.3.1 @DeferredImportSelector

DeferredImportSelector继承自ImportSelector,DeferredImportSelector 的执行时机,是@Configuration 注解中的其他逻辑被处理完毕之后(包括对 @ImportResource@Bean 这些注解的处理)再执行 ,即DeferredImportSelector 的执行时机比 ImportSelector 更晚。

4.3.2 实现原理[核心]

image.png

【步骤1】:判断系统配置项是否开启了自动配置,也就是  isEnabled 方法,该方法默认true,未开启直接结束。

protected boolean isEnabled(AnnotationMetadata metadata) {
    if (getClass() == AutoConfigurationImportSelector.class) {
        return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
    }
    return true;
}

getProperty方法三个参数

  • 第一个:当前环境变量配置的key,会通过这个key查找配置文件配置的value
  • 第二个:返回类型,转义成Boolean
  • 第三个:默认值true


【步骤2】:获取元数据,入参path:META-INF/spring-autoconfigure-metadata.properties

static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {
    try {
        Enumeration<URL> urls = (classLoader != null) ? classLoader.getResources(path)
            : ClassLoader.getSystemResources(path);
        Properties properties = new Properties();
        while (urls.hasMoreElements()) {
            properties.putAll(PropertiesLoaderUtils.loadProperties(new UrlResource(urls.nextElement())));
        }
        return loadMetadata(properties);
    }
    catch (IOException ex) {
        throw new IllegalArgumentException("Unable to load @ConditionalOnClass location [" + path + "]", ex);
    }
}

可以看到在三目运算符中,用户配置>系统配置,AutoConfigurationMetadata是借助于属性文件实现的内部类进行返回的。

【步骤3】:核心是加载自动配置类,上来还是判断是否开启了自动配置,没则直接结束

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
      AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    }
    // 1.获取所有的attributes
    AnnotationAttributes attributes = getAttributes(annotationMetadata);
    
    // 2.SPI机制加载自动配置类configurations
    List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
   
    // 3.步骤2结果去重
    configurations = removeDuplicates(configurations);
    
     // 4.基于1获取全部去重的Exclusion【过滤限制的配置项】
    Set<String> exclusions = getExclusions(annotationMetadata, attributes);
    
    /**
     * 5.检查是否有无效Exclusion,有则抛出IllegalStateException
     * The following classes could not be excluded because they are not auto-configuration classes
   * 不能排除下列类,因为它们不是自动配置类
     */
    checkExcludedClasses(configurations, exclusions);
    
    // 6.清空configurations中的exclusions
    configurations.removeAll(exclusions);
   
     // 7.重新生成configurations,前面4.2的继承体系在这里发挥作用
    configurations = filter(configurations, autoConfigurationMetadata);
    fireAutoConfigurationImportEvents(configurations, exclusions);
    return new AutoConfigurationEntry(configurations, exclusions);
}

其中方法调用链路粗略绘制,如下所示:

关于SpringFactoriesLoader.loadFactoryNames方法,这里还是需要说明一下,关键就在于这个方法,帮我们实现的全局自动配置

image.png

所以自动装配最后还是会回到配置文件,基于配置文件spring.factories的:   org.springframework.boot.autoconfigure.EnableAutoConfiguration=\,去加载自动配置类的全限定类名,这个结果会是一个很长的字符串,如下:

4.png

之后装配到IOC容器中,之后的自动配置类就可以通过 ImportSelector 和 @Import 的机制被创建出,开始生效。

【SpringBoot自动装配结束】


4.3.3 自动装配做了什么

自动装配的最大好处,我觉得以下面这个例子说明应该就比较直观了。在传统的SSM框架中,我们使用Redis时候,需要在xml中定义Bean才可以使用,如:

<!-- redis template definition -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
  <property name="connectionFactory" ref="jedisConnectionFactory" />
  <property name="keySerializer">
    <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
  </property>
  <property name="valueSerializer">
    <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
  </property>
  <property name="hashKeySerializer">
    <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
  </property>
  <property name="hashValueSerializer">
    <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
  </property>
  <!--开启事务  -->  
  <property name="enableTransactionSupport" value="true"></property>  
</bean>

用的时候就这样声明式调用:

@Autowired 
public RedisTemplate redisTemplate;

但是在SpringBoot框架中,我们引入jar包之后,只需要下面这样就可以直接使用,仔细看下你的SpringBoot项目是不是直接使用的,原因就在于自动化配置帮我们实现了。这应该就是最直观的感受了。

3.png

5.总结

@SpringBootApplication这个组合注解,主要分4个元注解+3个自定义注解:

@ComponentScan告诉去哪里扫描,如果遇到不想在启动初期加载进IOC容器的,主启动类组件通过TypeExcludeFilter,自动配置组件通过AutoConfigurationExcludeFilter进行过滤。

@SpringBootConfiguration标注主启动类,声明为一个配置类,@EnableAutoConfiguration服务。

@EnableAutoConfiguration是自动化配置的核心,标识开启自动配置,是一个派生注解,其两个核心:@AutoConfigurationPackage帮助完成Bean注册,获取全部去重的packageNames;@AutoConfigurationImportSelector核心是借助于ImportSelector接口的selectImport方法实现,层层调用之后,最终会获取spring.factories文件下的配置信息,取到EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作。以前我们需要自己配置的东西,自动配置类都帮我们完成了。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
1月前
|
架构师 Java 开发者
得物面试:Springboot自动装配机制是什么?如何控制一个bean 是否加载,使用什么注解?
在40岁老架构师尼恩的读者交流群中,近期多位读者成功获得了知名互联网企业的面试机会,如得物、阿里、滴滴等。然而,面对“Spring Boot自动装配机制”等核心面试题,部分读者因准备不足而未能顺利通过。为此,尼恩团队将系统化梳理和总结这一主题,帮助大家全面提升技术水平,让面试官“爱到不能自已”。
得物面试:Springboot自动装配机制是什么?如何控制一个bean 是否加载,使用什么注解?
|
1月前
|
Java 数据库连接 mybatis
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
该文档详细介绍了如何在Springboot Web项目中整合Mybatis,包括添加依赖、使用`@MapperScan`注解配置包扫描路径等步骤。若未使用`@MapperScan`,系统会自动扫描加了`@Mapper`注解的接口;若使用了`@MapperScan`,则按指定路径扫描。文档还深入分析了相关源码,解释了不同情况下的扫描逻辑与优先级,帮助理解Mybatis在Springboot项目中的自动配置机制。
129 0
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
|
3月前
|
Java 数据库 开发者
深入剖析 SpringBoot 的 SPI 机制
【8月更文挑战第10天】在软件开发中,SPI(Service Provider Interface)机制是一种重要的服务发现和加载机制,尤其在构建模块化、可扩展的系统时尤为重要。SpringBoot作为Spring家族的一员,其内置的SPI机制不仅继承了Java SPI的设计思想,还进行了优化和扩展,以适应Spring Boot特有的需求。本文将深入剖析SpringBoot中的SPI机制,揭示其背后的原理与应用。
87 7
|
3月前
|
Java 开发者 Spring
"揭秘SpringBoot魔法SPI机制:一键解锁服务扩展新姿势,让你的应用灵活飞天!"
【8月更文挑战第11天】SPI(Service Provider Interface)是Java的服务提供发现机制,用于运行时动态查找和加载服务实现。SpringBoot在其基础上进行了封装和优化,通过`spring.factories`文件提供更集中的配置方式,便于框架扩展和组件替换。本文通过定义接口`HelloService`及其实现类`HelloServiceImpl`,并在`spring.factories`中配置,结合`SpringFactoriesLoader`加载服务,展示了SpringBoot SPI机制的工作流程和优势。
57 5
|
3月前
|
安全 Java UED
掌握SpringBoot单点登录精髓,单点登录是一种身份认证机制
【8月更文挑战第31天】单点登录(Single Sign-On,简称SSO)是一种身份认证机制,它允许用户只需在多个相互信任的应用系统中登录一次,即可访问所有系统,而无需重复输入用户名和密码。在微服务架构日益盛行的今天,SSO成为提升用户体验和系统安全性的重要手段。本文将详细介绍如何在SpringBoot中实现SSO,并附上示例代码。
75 0
|
3月前
|
消息中间件 Java Kafka
深入SpringBoot的心脏地带:掌握其核心机制的全方位指南
【8月更文挑战第29天】这段内容介绍了在分布式系统中起到异步通信与解耦作用的消息队列,并详细探讨了三种流行的消息队列产品:RabbitMQ、RocketMQ 和 Kafka。RabbitMQ 是一个基于 AMQP 协议的开源消息队列系统,支持多种消息模型,具有高可靠性及稳定性;RocketMQ 则是由阿里巴巴开源的高性能分布式消息队列,支持事务消息等多种特性;而 Kafka 是 LinkedIn 开源的分布式流处理平台,以其高吞吐量和良好的可扩展性著称。文中还提供了使用这三种消息队列产品的示例代码。总之,这三款产品各有优势,适用于不同场景。
16 0
|
3月前
|
消息中间件 Java Kafka
SpringBoot大揭秘:如何轻松掌握其核心机制?
【8月更文挑战第29天】这段内容介绍了在分布式系统中起到异步通信与解耦作用的消息队列,并详细探讨了三种流行的消息队列产品:RabbitMQ、RocketMQ 和 Kafka。RabbitMQ 是一个基于 AMQP 协议的开源消息队列系统,支持多种消息模型,具有高可靠性及稳定性;RocketMQ 则是由阿里巴巴开源的高性能分布式消息队列,支持事务消息等多种特性;而 Kafka 是 LinkedIn 开源的分布式流处理平台,以其高吞吐量和良好的可扩展性著称。文中还提供了使用这三种消息队列产品的示例代码。
16 0
|
3月前
|
消息中间件 Java Kafka
SpringBoot Kafka SSL接入点PLAIN机制收发消息
SpringBoot Kafka SSL接入点PLAIN机制收发消息
38 0
|
4月前
|
安全 Java API
构建基于Spring Boot的REST API安全机制
构建基于Spring Boot的REST API安全机制
|
5月前
|
安全 Java 应用服务中间件
优雅的理解SpringBoot的核心机制
【6月更文挑战第21天】理解 Spring Boot 的核心机制可以帮助开发者更好地利用这个框架来构建现代化的企业级应用。
178 9