Spring源码分析十一:Spring的扩展加载机制Spring的扩展加载机制主要有两个:自动加载第三方包中的类,扩展xml配置文件中的bean命名空间1.自动加载第三方包中的类spring-core提供了类似于JavaSPI的扩展机制。在META-INF/spring.factories文件中定义需要自动加载的类,然后自动实例化其他包指定的类。spring-boot和spring-cloud都是依赖这种机制自动加载资源的。比如spring-boot的扩展(部分)#LoggingSystemsorg.springframework.boot.logging.LoggingSystemFactory=\org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory,\org.springframework.boot.logging.log4j2。Log4J2LoggingSystem.Factory,\org.springframework.boot.logging.java.JavaLoggingSystem.Factory#PropertySourceLoadersLocationResolversorg.springframework.boot.context.config.ConfigDataLocationResolver=\org.springframework.boot.context.config.ConfigTreeConfigDataLocationResolver,\org.springframework.boot.context.config.StandardConfigDataLocationResolver#ConfigDataLoadersorg.springframework.boot.context.config.ConfigDataLoader=\org.springframework.boot.context.config.ConfigTreeConfigDataLoader,\org.springframework.boot.context.config.StandardConfigDataLoader#运行监听器org.springframework.boot.SpringApplicationRunListener=\org.springframework.boot.context.event.EventPublishingRunListener实际发现这个功能的类是SpringFactoriesLoaderpublicfinalclassSpringFactoriesLoader{//自动加载文件地址publicstaticfinalStringFACTORIES_RESOURCE_LOCATION="META-INF/spring.factories";//加载spring.factoriespublicstaticListloadFactories(ClassfactoryType,@NullableClassLoaderclassLoader){ClassLoaderclassLoaderToUse=classLoader;如果(classLoaderToUse==null){classLoaderToUse=SpringFactoriesLoader.class.getClassLoader();}//加载spring.factories中的bean名称ListfactoryImplementationNames=loadFactoryNames(工厂类型,classLoaderToUse);//结果集Listresult=newArrayList<>(factoryImplementationNames.size());for(StringfactoryImplementationName:factoryImplementationNames){//初始化bean并将其添加到结果集中result.add(instantiateFactory(factoryImplementationName,factoryType,classLoaderToUse));}返回结果;}//加载spring.factories中的bean名称publicstaticListloadFactoryNames(Class>factoryType,@NullableClassLoaderclassLoader){ClassLoaderclassLoaderToUse=classLoader;如果(classLoaderToUse==null){classLoaderToUse=SpringFactoriesLoader.class.getClassLoader();}StringfactoryTypeName=factoryType.getName();//加载spring.factories中的bean定义并提取名称returnloadSpringFactories(classLoaderToUse)。getOrDefault(factoryTypeName,Collections.emptyList());}//加载spring.factories中的bean定义privatestaticMap>loadSpringFactories(ClassLoaderclassLoader){//如果有缓存,直接返回缓存Map>result=cache.get(classLoader);如果(结果!=null){返回结果;}//结果集result=newHashMap<>();try{//加载所有包下的spring.factories,不仅是主包,还有各种依赖包Enumerationurls=classLoader.getResources(FACTORIES_RESOURCE_LOCATION);//遍历并读取while(urls.hasMoreElements()){URLurl=urls.nextElement();UrlResource资源=newUrlResource(url);//加载属性并将属性视为属性文件properties=PropertiesLoaderUtils.loadProperties(resource);for(Map.Entry,?>entry:properties.entrySet()){//bean名称StringfactoryTypeName=((String)entry.getKey()).trim();//bean类型,多个String可以用逗号分隔factoryImplementationNames=StringUtils.commaDelimitedListToStringArray((String)entry.getValue());//遍历bean类型for(StringfactoryImplementationName:factoryImplementationNames){//添加到结果集result.computeIfAbsent(factoryTypeName,key->newArrayList<>()).add(factoryImplementationName.trim());}}}//去重result.replaceAll((factoryType,implementations)->implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(),Collections::unmodifiableList)));//添加缓存cache.put(classLoader,result);}catch(IOExceptionex){//...省略代码}returnresult;}//初始化beanprivatestaticTinstantiateFactory(StringfactoryImplementationName,ClassfactoryType,ClassLoaderclassLoader){try{//取出classClass>factoryImplementationClass=ClassUtils.forName(factoryImplementationName,classLoader);//factoryImplementationClass不是factoryType的子类if(!factoryType.isAssignableFrom(factoryImplementationClass)){//错误}//调用newInstance实例化return(T)ReflectionUtils.accessibleConstructor(factoryImplementationClass).newInstance();}catch(Throwableex){//...代码省略}}}然后在CachedIntrospectionResults静态加载publicfinalclassCachedIntrospectionResults{privatestaticfinalListbeanInfoFactories=SpringFactoriesLoader.loadFactories(BeanInfoFactory.class,CachedIntrospectionResults.class.getClassLoader());}2.xml扩展配置文件中的bean命名空间spring-beans为bean命令空间提供了基于XML配置的第三方扩展机制,主要定义在META-INF/spring.handlers、META-INF/spring.schemas文件中需要待扩展的命令空间,如,如spring-beans下的extensionshttp\://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandlerhttp\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandlerhttp\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler实际上发现这个功能的类是DefaultNamespaceHandlerResolverpublicclassDefaultNamespaceHandlerResolverimplementsNamespaceHandlerResolver{//自动加载文件地址publicstaticfinalStringDEFAULT_HANDLER_MAPPINGS_LOCATION="spring.//默认加载DEFAULT_HANDLER_MAPPINGS_LOCATIONpublicDefaultNamespaceHandlerResolver(){this(null,DEFAULT_HANDLER_MAPPINGS_LOCATION);}//默认加载DEFAULT_HANDLER_MAPPINGS_LOCATIONpublicDefaultNamespaceHandlerResolver(@NullableClassLoaderclassLoader){this(classLoader,DEFAULT_HANDLER_MAPPINGS_LOCATION);}publicDefaultNamespaceHandlerResolver(@NullableClassLoaderclassLoader,StringhandlerMappingsLocation){this.classLoader=(classLoader!=null?classLoader:ClassUtils.getDefaultClassLoader());this.handlerMappingsLocation=handlerMappingsLocation;}//解析命空间@OverridepublicNamespaceHandlerresolve(StringnamespaceUri){//获取命空间映射MaphandlerMappings=getHandlerMappings();//获取处理器ObjecthandlerOrClassName=handlerMappings.get(namespaceUri);//没有,返回nullif(handlerOrClassName==null){returnnull;}//NamespaceHandler,返回NamespaceHandlerelseif(handlerOrClassNameinstanceofNamespaceHandler){return(NamespaceHandler)handler或类名;}else{StringclassName=(String)handlerOrClassName;try{//作为类加载Class>handlerClass=ClassUtils.forName(className,this.classLoader);//初始化类并调用init方法NamespaceHandlernamespaceHandler=(NamespaceHandler)BeanUtils.instantiateClass(handlerClass);namespaceHandler.init();//加载缓存handlerMappings.put(namespaceUri,namespaceHandler);返回命名空间处理程序;}catch(ClassNotFoundExceptionex){//...省略代码}//...省略代码}}//获取命令空间映射privateMapgetHandlerMappings(){MaphandlerMappings=this.handlerMappings;//如果已经加载过,则不加载if(handlerMappings==null){synchronized(this){handlerMappings=这个.handlerMappings;if(handlerMappings==null){try{//加载所有包下的spring.handlers,不仅是主包,还有各种依赖包//加载属性并将属性映射视为属性文件=PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation,这个.classLoader);handlerMappings=newConcurrentHashMap<>(mappings.size());CollectionUtils.mergePropertiesIntoMap(映射,handlerMappings);//为handlerMappings赋值this.handlerMappings=handlerMappings(}IOExceptionex){//...省略代码}}}}returnhandlerMappings;}}因为DefaultNamespaceHandlerResolver是默认的namespaceresolver,所以一开始就会初始化,所以会自动加载spring.handlers用于后续的更新多博客,查看https://github.com/senntyou/blogs作者:沈玉之(@senntyou)版权声明:免费转载-非商业-非衍生-保留署名(CreativeCommons3.0许可)