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架构师相关信息,记得关注本站消息获取。
推荐阅读: