亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringFactoriesLoader類作用詳解

 更新時間:2022年10月26日 14:45:22   作者:沫洺  
SpringFactoriesLoader可以加載jar包下META-INF下的spring.factories,把相關接口的實現按照key,value的形式加載到內存,一個接口的多個實現可以按照","進行分割

SpringFactoriesLoader類

介紹

SpringFactoriesLoader類的主要作用是通過類路徑下的META-INF/spring.factories文件獲取工廠類接口的實現類,初始化并保存在緩存中,以供Springboot啟動過程中各個階段的調用。Spring的自動化配置功能,也與此息息相關。

SpringFactoriesLoader 工廠加載機制是 Spring 內部提供的一個約定俗成的加載方式,只需要在模塊的 META-INF/spring.factories 文件中,以 Properties 類型(即 key-value 形式)配置,就可以將相應的實現類注入 Spirng 容器中。

Properties類型格式:

key:value

  • key:是全限定名(抽象類|接口)
  • value:是實現類,多個實現類通過逗號進行分割

spring boot類路徑下: META-INFO/spring.factories

方法

返回值方法描述
<T>List<T>loadFactories(Class<T> factoryType,@Nullable ClassLoader classLoader)靜態(tài)方法 根據接口獲取其實現類的實例 該方法返回的是實現類對象列表
List<String>loadFactoryNames(Class<?>) factoryType,@Nullable ClassLoader classLoader)公共靜態(tài)方法 根據接口獲取其實現類的名稱 該方法返回的是實現類的類名的列表
public final class SpringFactoriesLoader {
    //文件位置,可以存在多個JAR文件中
    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
    //用來緩存MultiValueMap對象
    private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap<>();
    private SpringFactoriesLoader() {
    }
    /**
     * 根據給定的類型加載并實例化工廠的實現類
     */
    public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
        Assert.notNull(factoryType, "'factoryType' must not be null");
        //獲取類加載器
        ClassLoader classLoaderToUse = classLoader;
        if (classLoaderToUse == null) {
            classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
        }
        //加載類的全限定名
        List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse);
        if (logger.isTraceEnabled()) {
            logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames);
        }
        //創(chuàng)建一個存放對象的List
        List<T> result = new ArrayList<>(factoryImplementationNames.size());
        for (String factoryImplementationName : factoryImplementationNames) {
            //實例化Bean,并將Bean放入到List集合中
            result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
        }
        //對List中的Bean進行排序
        AnnotationAwareOrderComparator.sort(result);
        return result;
    }
    /**
     * 根據給定的類型加載類路徑的全限定名
     */
    public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
        //獲取名稱
        String factoryTypeName = factoryType.getName();
        //加載并獲取所有META-INF/spring.factories中的value
        return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
    }
    private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
        //根據類加載器從緩存中獲取,如果緩存中存在,就直接返回,如果不存在就去加載
        MultiValueMap<String, String> result = cache.get(classLoader);
        if (result != null) {
            return result;
        }
        try {
            //獲取所有JAR及classpath路徑下的META-INF/spring.factories的路徑
            Enumeration<URL> urls = (classLoader != null ?
                    classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                    ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
            result = new LinkedMultiValueMap<>();
            //遍歷所有的META-INF/spring.factories的路徑
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                UrlResource resource = new UrlResource(url);
                //將META-INF/spring.factories中的key value加載為Prpperties對象
                Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                for (Map.Entry<?, ?> entry : properties.entrySet()) {
                    //key名稱
                    String factoryTypeName = ((String) entry.getKey()).trim();
                    for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
                        //以factoryTypeName為key,value為值放入map集合中
                        result.add(factoryTypeName, factoryImplementationName.trim());
                    }
                }
            }
            //放入到緩存中 
            cache.put(classLoader, result);
            return result;
        }
        catch (IOException ex) {
            throw new IllegalArgumentException("Unable to load factories from location [" +
                    FACTORIES_RESOURCE_LOCATION + "]", ex);
        }
    }
    //實例化Bean對象
    @SuppressWarnings("unchecked")
    private static <T> T instantiateFactory(String factoryImplementationName, Class<T> factoryType, ClassLoader classLoader) {
        try {
            Class<?> factoryImplementationClass = ClassUtils.forName(factoryImplementationName, classLoader);
            if (!factoryType.isAssignableFrom(factoryImplementationClass)) {
                throw new IllegalArgumentException(
                        "Class [" + factoryImplementationName + "] is not assignable to factory type [" + factoryType.getName() + "]");
            }
            return (T) ReflectionUtils.accessibleConstructor(factoryImplementationClass).newInstance();
        }
        catch (Throwable ex) {
            throw new IllegalArgumentException(
                "Unable to instantiate factory class [" + factoryImplementationName + "] for factory type [" + factoryType.getName() + "]",
                ex);
        }
    }
}

測試

resources下新建META-INF/spring.factories

com.moming.service.IStudentService=\
com.moming.service.impl.StudentServiceImpl1,\
com.moming.service.impl.StudentServiceImpl2

創(chuàng)建業(yè)務層接口及實現類

service/IStudentService

service/impl/StudentServiceImpl1

service/impl/StudentServiceImpl2

測試

@SpringBootApplication
public class App{
    public static void main(String[] args) {
        //SpringApplication.run(App.class, args);
        List<String> names = SpringFactoriesLoader.loadFactoryNames(IStudentService.class, ClassUtils.getDefaultClassLoader());
        for (String name : names) {
            System.out.println(name);
        }
        System.out.println("===================================");
        List<IStudentService> iStudentServices = SpringFactoriesLoader.loadFactories(IStudentService.class, ClassUtils.getDefaultClassLoader());
        for (IStudentService iStudentService : iStudentServices) {
            System.out.println(iStudentService);
            System.out.println(iStudentService.game());
        }
    }
}

通過以上可以證明,SpringFactoriesLoader會尋找jar包中配置META-INF下的spring.factories配置文件相應Key的value,并根據需要實例化

到此這篇關于SpringFactoriesLoader類作用詳解的文章就介紹到這了,更多相關SpringFactoriesLoader內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關文章

  • Java開發(fā)如何把數據庫里的未付款訂單改成已付款

    Java開發(fā)如何把數據庫里的未付款訂單改成已付款

    這篇文章主要介紹了Java開發(fā)如何把數據庫里的未付款訂單改成已付款,先介紹MD5算法,簡單的來說,MD5能把任意大小、長度的數據轉換成固定長度的一串字符,實現思路非常簡單需要的朋友可以參考下
    2022-11-11
  • Java集合之Map接口與實現類詳解

    Java集合之Map接口與實現類詳解

    這篇文章主要為大家詳細介紹了Java集合中的Map接口與實現類,文中的示例代碼講解詳細,對我們學習Java有一定的幫助,感興趣的可以了解一下
    2022-12-12
  • Java實現MD5加密及解密的代碼實例分享

    Java實現MD5加密及解密的代碼實例分享

    如果對安全性的需求不是太高,MD5仍是使用非常方便和普及的加密方式,比如Java中自帶的MessageDigest類就提供了支持,這里就為大家?guī)鞪ava實現MD5加密及解密的代碼實例分享:
    2016-06-06
  • 使用Idea或Datagrip導入excel數據的方法

    使用Idea或Datagrip導入excel數據的方法

    這篇文章主要介紹了使用Idea或Datagrip導入excel數據的方法,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • SpringBoot實現圖片識別文字的四種方式小結

    SpringBoot實現圖片識別文字的四種方式小結

    本文主要介紹了SpringBoot實現圖片識別文字的四種方式,包括Tess4J,百度智能云,阿里云,騰訊云這四種,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • java文件下載設置中文名稱的實例(response.addHeader)

    java文件下載設置中文名稱的實例(response.addHeader)

    下面小編就為大家分享一篇java文件下載設置中文名稱的實例(response.addHeader),具有很好的參考價值,希望對大家有所幫助
    2017-12-12
  • java實現事件委托模式的實例詳解

    java實現事件委托模式的實例詳解

    這篇文章主要介紹了java實現事件委托模式的實例詳解的相關資料,這里提供實例來說明如何實現改功能,希望能幫助到大家理解這樣的模式,需要的朋友可以參考下
    2017-08-08
  • Maven熱部署devtools的實現示例

    Maven熱部署devtools的實現示例

    本文主要介紹了Maven熱部署devtools的實現示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-07-07
  • 如何通過Java監(jiān)聽MySQL數據的變化

    如何通過Java監(jiān)聽MySQL數據的變化

    對于二次開發(fā)來說,很大一部分就找找文件和找數據庫的變化情況,下面這篇文章主要給大家介紹了關于如何通過Java監(jiān)聽MySQL數據的變化的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-03-03
  • 在Spring中基于Java類進行配置的完整步驟

    在Spring中基于Java類進行配置的完整步驟

    基于Java配置選項,可以編寫大多數的Spring不用配置XML,下面這篇文章主要給大家介紹了關于在Spring中基于Java類進行配置的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2018-05-05

最新評論