栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springboot 自动配置原理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springboot 自动配置原理

springboot 自动配置原理 一、springboot自动配置

1、概述

自动配置的功能是其简化运用的关键技术,思想就是约定大于配置,意思就是一个工程约定必须要有事务功能,要有aop功能,要有mvc功能等,所以springboot在创建工程的时候自动把这些功能所需的类实例化并加入到spring容器了,这个就是约定大于配置,约定了必须要有这些功能。

2、springboot中的SPI机制

java原生的SPI,是一种服务发现机制( Service Provider Interface)。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。 这一机制为很多框架扩展提供了可能,比如在Dubbo、JDBC中都使用到了SPI。

2.1、JDK中的SPI机制

public interface Log {
 boolean support(String type); 
 void info(); 
 }

在resources/META-INF/services目录创建文件,文件名称必须跟接口的完整限定名相同。这个接口文件中配置了该接口的所有实现类的完整限定名。然后jdk api 加载配置文件

//jdk api 加载配置文件配置实例
 ServiceLoader all = ServiceLoader.load(Log.class);

2.2、springboot中的SPI机制
具体流程和上面差不多,在工程的resources下面创建META-INF文件夹,在文件夹下创建spring.factories文件,在文件配置内容如下:

com.ss.yc.spi.Log= 
com.ss.yc.spi.Log4j,
com.ss.yc.spi.Logback, 
com.ss.yc.spi.Slf4j

配置的key就是接口完整限定名,value就是接口的各个实现类,用","号隔开。

  • loadFactoryNames方法获取实现了接口的所有类的名称
@Test
public void test() {
List strings = SpringFactoriesLoader
.loadFactoryNames(Log.class, ClassUtils.getDefaultClassLoader());

for (String string : strings) { System.out.println(string); 
 }
}
  • loadFactories方法获取实现了接口的所有类的实例
@Test
public void test1() {
List strings = SpringFactoriesLoader
.loadFactories(Log.class, ClassUtils.getDefaultClassLoader());

for (String string : strings) { System.out.println(string); 
 }
}

2.3、我们以SpringFactoriesLoader.loadFactoryNames(Log.class, ClassUtils.getDefaultClassLoader());方法调用为例分析其源码

可以看到springboot spi是加载了整个工程的jar包和自己工程定义的spring.factories文件的。
其核心代码

Properties properties = PropertiesLoaderUtils.loadProperties(resource);
public static Properties loadProperties(Resource resource) 
throws IOException { 
Properties props = new Properties(); 
//核心代码,把文件包装成properties对象
 fillProperties(props, resource);
  return props;
 }

springboot中的SPI其实就是加载整个工程里面的spring.factories文件,然后把文件里面的内容建立一个key和value的映射关系,只是这个映射关系是一个类型和list的映射关系。

3、@EnableAutoConfiguration

@EnableAutoConfiguration注解是springboot自动配置的核心注解,就是因为有这个注解存在就会把例如事务,缓存,aop,mvc等功能自动导入到springboot工程中,Spring框架提供的各种名字为@Enable开头的Annotation定义,比如@EnableScheduling、@EnableMBeanExport等,@EnableAutoConfiguration的理念和做事方式其实一脉相承,简单概括一下就是,借助@Import的支持,收集和注册特定场景相关的bean定义。

@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    ...
}

@Import了一个类,这个AutoConfigurationImportSelector自动配置类

3.1、DeferredImportSelector

DeferredImportSelector该接口是ImportSelector接口的一个子接口,那么它是如何使用的呢?

//
public class DeferredImportSelectorDemo implements DeferredImportSelector{
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata)
{

System.out.println("=====DeferredImportSelectorDemo.selectImports");

return newString[]{DeferredBean.class.getName()};
}


//要返回一个实现了Group接口的类
@Override
public Class getImportGroup(){
return DeferredImportSelectorGroupDemo.class;
}


private static class DeferredImportSelectorGroupDemo implements Group{
List list=new ArrayList<>();

//收集需要实例化的类
@Override
public void process(AnnotationMetadata metadata,DeferredImportSelector selector){

System.out.println("=====DeferredImportSelectorGroupDemo.process");
String[] strings=selector.selectImports(metadata);
for(String string:strings){
list.add(newEntry(metadata,string));
}
}

//把收集到的类返回给spring容器
@Override
public Iterable selectImports(){
System.out.println("=====DeferredImportSelectorGroupDemo.selectImports");
return list;
}
}
}


//要实例的bean
public class DeferredBean{}

该类必须是@Import导入进来

@Component
//Import虽然是实例化一个类,Import进来的类可以实现一些接口@Import({DeferredImportSelectorDemo.class})
public class ImportBean{}

这样就实现了一个类的实例化。

3.2、EnableAutoConfigurationImportSelector

而AutoConfigurationImportSelector类,这个类就是@EnableAutoConfiguration注解中@Import进来的类,可以看到该类正是实现了DeferredImportSelector接口的。该类其实就是收集spring.factories文件中以@EnableAutoConfiguration类型为key的所有的类,然后把这些类交给spring去实例化,而这些类就是我们说的aop、事务、缓存、mvc等功能的支持类,这就是自动配置的加载原理。

4、@Configuration

就是JavaConfig形式的Spring Ioc容器的配置类使用的那个@Configuration,SpringBoot社区推荐使用基于JavaConfig的配置形式,所以,这里的启动类标注了@Configuration之后,本身其实也是一个IoC容器的配置类。

其中@Bean的方法,其返回值将作为一个bean定义注册到Spring的IoC容器,方法名将默认成该bean定义的id。

5、@ComponentScan

其实就是自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。可以通过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围,如果不指定,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/841360.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号