springboot框架工作原理是怎样的?原理详解

XIAO 2020-06-03 14:02:14 java常见问答 5378

springboot作为java软件开发行业的比较流行的开发框架,其诸多优点在这暂时也不多提,今天我们主要来看看,springboot框架工作原理是什么样的呢?

在SpringBootApplication类上有一个十分重要的注解:@EnableAutoConfiguration,它其实就是实现所谓自动化配置的一个核心所在了。

当我们启动wmspringboot项目的时候,框架就去会调用@EnableAutoConfiguration注解,用来进一步去加载系统所需的一些配置信息,从而去完成自动化的一些配置。

@EnableAutoConfiguration的源码如下所示:

@Target(
{
    ElementType.TYPE
})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(
{
    AutoConfigurationImportSelector.class
})
public @interface EnableAutoConfiguration
{
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    Class[] exclude() default
    {};
    String[] excludeName() default
    {};
}

SpringFactoriesLoader类,其实是spring框架自己所使用的一个内部工具类,其本身就被声明为final,意思是不可以被其他类继承。

SpringFactoriesLoader类的源码如下所示:

/**
 * Source code recreated from a .class file by IntelliJ IDEA
 * (powered by Fernflower decompiler)
 */
package org.springframework.core.io.support;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.io.UrlResource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
/**
 * SpringFactoriesLoader#loadFactories设计用于加载和实例化指定类型的工厂,这些工厂类型的定义
 * 来自classpath中多个JAR包内常量FACTORIES_RESOURCE_LOCATION所指定的那些spring.factories文件。
 * spring.factories文件的格式必须是属性文件格式,每条属性的key必须是接口或者抽象类的全限定名,
 * 而属性值value是一个逗号分割的实现类的名称。
 */
public final class SpringFactoriesLoader
{
    /*
     * 要加载的资源路径,该常量定义了该工具类要从每个jar包中提取的工厂类定义属性文件的相对路径
     * 在classpath中的多个JAR中,要扫描的工厂配置文件的在本JAR包中的路径。
     * 实际上,Springboot的每个 autoconfigure包都包含spring.factories这个配置文件。
     */
    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
    //日志
    private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);
    private static final Map < classloader, string = ""
    multivaluemap > cache = new ConcurrentReferenceHashMap();
    private SpringFactoriesLoader()
    {}
    /**
     * @param factoryClass 工厂所属接口/抽象类全限定名称
     * @param classLoader 所要使用的类加载器
     *
     * 该方法会读取classpath上所有的jar包中的所有 META-INF/spring.factories 属性文件,找出其中定义的匹配类型 factoryClass 的工厂类,
     * 然后创建每个工厂类的对象/实例,并返回这些工厂类对象/实例的列表
     */
    public staticListloadFactories(ClassfactoryClass, @Nullable ClassLoader classLoader)
    {
        Assert.notNull(factoryClass, "'factoryClass' must not be null");
        ClassLoader classLoaderToUse = classLoader;
        if (classLoader == null)
        {
            classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
        }
        //加载类型为factoryClass的工厂的名称,其实是一个个的全限定类名,使用指定的classloader:classLoaderToUse
        ListfactoryNames = loadFactoryNames(factoryClass, classLoaderToUse);
        if (logger.isTraceEnabled())
        {
            logger.trace("Loaded [" + factoryClass.getName() + "] names: " + factoryNames);
        }
        Listresult = new ArrayList(factoryNames.size());
        Iterator var5 = factoryNames.iterator();
        // 实例化所加载的每个工厂类
        while (var5.hasNext())
        {
            String factoryName = (String) var5.next();
            result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));
        }
        //对工厂类进行排序
        AnnotationAwareOrderComparator.sort(result);
        return result;
    }
    /**
     *
     * @param factoryClass 工厂所属接口/抽象类全限定名称
     * @param classLoader 类加载器
     * @return
     *
     * 该方法会读取classpath上所有的jar包中的所有 META-INF/spring.factories 属性文件,找出其中定义的匹配类型 factoryClass 的工厂类,
     * 然后并返回这些工厂类的名字列表,注意是包含包名的全限定名。
     */
    public static ListloadFactoryNames(Class factoryClass, @Nullable ClassLoader classLoader)
    {
        String factoryClassName = factoryClass.getName();
        // 1. 使用指定的classloader扫描classpath上所有的JAR包中的文件META-INF/spring.factories,加载其中的多值工厂属性定义,使用多值Map的形式返回,
        // 2. 返回多值Map中key为factoryClassName的工厂名称列表,如果没有相应的entry,返回空列表而不是返回null
        return (List) loadSpringFactories(classLoader)
            .getOrDefault(factoryClassName, Collections.emptyList());
    }
    /**
     * @param classLoader 类加载器
     *
     * 使用指定的classloader扫描classpath上所有的JAR包中的文件META-INF/spring.factories,加载其中的多值
     * 工厂属性定义,使用多值Map的形式返回
     **/
    private static Map < string, list > loadSpringFactories(@Nullable ClassLoader classLoader)
    {
        MultiValueMapresult = (MultiValueMap) cache.get(classLoader);
        if (result != null)
        {
            return result;
        }
        else
        {
            try
            {
                // 扫描classpath上所有JAR中的文件META-INF/spring.factories
                Enumerationurls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
                LinkedMultiValueMap result = new LinkedMultiValueMap();
                while (urls.hasMoreElements())
                {
                    // 找到的每个META-INF/spring.factories文件都是一个Properties文件,将其内容
                    // 加载到一个 Properties 对象然后处理其中的每个属性
                    URL url = (URL) urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet()
                        .iterator();
                    while (var6.hasNext())
                    {
                        Entry entry = (Entry) var6.next();
                        // 获取工厂类名称(接口或者抽象类的全限定名)
                        String factoryClassName = ((String) entry.getKey())
                            .trim();
                        String[] var9 = StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
                        int var10 = var9.length;
                        for (int var11 = 0; var11 < var10; ++var11)
                        {
                            String factoryName = var9[var11];
                            result.add(factoryClassName, factoryName.trim());
                        }
                    }
                }
                cache.put(classLoader, result);
                return result;
            }
            catch (IOException var13)
            {
                throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
            }
        }
    }
    /**
     * @param instanceClassName 工厂实现类全限定名称
     * @param factoryClass 工厂所属接口/抽象类全限定名称
     * @param classLoader 所要使用的类加载器
     **/
    private staticT instantiateFactory(String instanceClassName, ClassfactoryClass, ClassLoader classLoader)
    {
        try
        {
            Class instanceClass = ClassUtils.forName(instanceClassName, classLoader);
            if (!factoryClass.isAssignableFrom(instanceClass))
            {
                throw new IllegalArgumentException("Class [" + instanceClassName + "] is not assignable to [" + factoryClass.getName() + "]");
            }
            else
            {
                return ReflectionUtils.accessibleConstructor(instanceClass, new Class[0])
                    .newInstance();
            }
        }
        catch (Throwable var4)
        {
            throw new IllegalArgumentException("Unable to instantiate factory class: " + factoryClass.getName(), var4);
        }
    }
}

好了,以上就是有关springboot框架工作原理的所有内容了,还想了解更多java架构师相关信息,记得关注本站消息获取。

推荐阅读:

springboot框架搭建如何实现?

springboot上传文件有何异同?

springboot框架的定义和特点介绍,java springboot详解