Spring FactoriesLoader机制实例详解
一、SpringFactoriesLoader介绍
1.1SpringFactoriesLoader简介
SpringFactoriesLoader工厂加载机制是Spring内部提供的一个约定俗成的加载方式,与javaspi类似,只需要在模块的META-INF/spring.factories文件中,以Properties类型(即key-value形式)配置,就可以将相应的实现类注入Spirng容器中。
Properties类型格式:
key:是全限定名(抽象类|接口)
value:是实现,多个实现通过**逗号**进行分隔
1.2SpringFactoriesLoader常用方法
loadFactoryNames
读取classpath上所有的jar包中的所有META-INF/spring.factories属性文件,找出其中定义的匹配类型factoryClass的工厂类,然后并返回这些工厂类的名字列表,注意是包含包名的全限定名。
loadFactories
读取classpath上所有的jar包中的所有META-INF/spring.factories属性文件,找出其中定义的匹配类型factoryClass的工厂类,然后创建每个工厂类的对象/实例,并返回这些工厂类对象/实例的列表。
1.3loadFactories流程图
二、SpringFactoriesLoader源码解析
2.1loadFactoryNames解析
publicstaticListloadFactoryNames(Class>factoryType,@NullableClassLoaderclassLoader){ //获取包含包名的工厂类名称 StringfactoryTypeName=factoryType.getName(); //获取所有配置在META-INF/spring.factories文件的值 //然后获取指定类的实现类名列表 returnloadSpringFactories(classLoader).getOrDefault(factoryTypeName,Collections.emptyList()); }
//默认的工厂配置路径地址,可以存放在多个JAR包下 publicstaticfinalStringFACTORIES_RESOURCE_LOCATION="META-INF/spring.factories"; privatestaticMap>loadSpringFactories(@NullableClassLoaderclassLoader){ //判断是否有缓存结果,如果有直接返回 MultiValueMap result=cache.get(classLoader); if(result!=null){ returnresult; } try{ //扫描classpath上所有JAR中的文件META-INF/spring.factories Enumeration urls=(classLoader!=null? classLoader.getResources(FACTORIES_RESOURCE_LOCATION): ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); result=newLinkedMultiValueMap<>(); while(urls.hasMoreElements()){ //找到的每个META-INF/spring.factories文件都是一个Properties文件,将其内容加载到一个Properties对象然后处理其中的每个属性 URLurl=urls.nextElement(); UrlResourceresource=newUrlResource(url); Propertiesproperties=PropertiesLoaderUtils.loadProperties(resource); for(Map.Entry,?>entry:properties.entrySet()){ //获取工厂类名称(接口或者抽象类的全限定名) StringfactoryTypeName=((String)entry.getKey()).trim(); //将逗号分割的属性值逐个取出,然后放到结果result中去 for(StringfactoryImplementationName:StringUtils.commaDelimitedListToStringArray((String)entry.getValue())){ result.add(factoryTypeName,factoryImplementationName.trim()); } } } //将结果存放到缓存中 cache.put(classLoader,result); returnresult; } catch(IOExceptionex){ thrownewIllegalArgumentException("Unabletoloadfactoriesfromlocation["+ FACTORIES_RESOURCE_LOCATION+"]",ex); } }
defaultVgetOrDefault(Objectkey,VdefaultValue){ Vv; return(((v=get(key))!=null)||containsKey(key)) ?v :defaultValue; }
2.2loadFactories解析
publicstaticList loadFactories(Class factoryType,@NullableClassLoaderclassLoader){ Assert.notNull(factoryType,"'factoryType'mustnotbenull"); //如果未指定类加载器,则使用默认的 ClassLoaderclassLoaderToUse=classLoader; if(classLoaderToUse==null){ classLoaderToUse=SpringFactoriesLoader.class.getClassLoader(); } //获取指定工厂名称列表 List factoryImplementationNames=loadFactoryNames(factoryType,classLoaderToUse); //如果记录器Trace跟踪激活的话,将工厂名称列表输出 if(logger.isTraceEnabled()){ logger.trace("Loaded["+factoryType.getName()+"]names:"+factoryImplementationNames); } //创建结果集 List result=newArrayList<>(factoryImplementationNames.size()); for(StringfactoryImplementationName:factoryImplementationNames){ //实例化工厂类,并添加到结果集中 result.add(instantiateFactory(factoryImplementationName,factoryType,classLoaderToUse)); } //对结果集列表进行排序 AnnotationAwareOrderComparator.sort(result); returnresult; }
privatestaticTinstantiateFactory(StringfactoryImplementationName,Class factoryType,ClassLoaderclassLoader){ try{ Class>factoryImplementationClass=ClassUtils.forName(factoryImplementationName,classLoader); if(!factoryType.isAssignableFrom(factoryImplementationClass)){ thrownewIllegalArgumentException( "Class["+factoryImplementationName+"]isnotassignabletofactorytype["+factoryType.getName()+"]"); } return(T)ReflectionUtils.accessibleConstructor(factoryImplementationClass).newInstance(); } catch(Throwableex){ thrownewIllegalArgumentException( "Unabletoinstantiatefactoryclass["+factoryImplementationName+"]forfactorytype["+factoryType.getName()+"]", ex); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。