美文网首页
spring.factories

spring.factories

作者: 吃花生的小猴子 | 来源:发表于2017-12-13 15:32 被阅读0次
    image.png

    spring boot中的 spring.factories 定义了一系列的ApplicationListener和ApplicationContextInitializer等其他系统所要的类。spring-boot 项目一般是这样启动:

    SpringApplication application = new SpringApplication();
    application.run();
    

    new SpringApplication() 实例化SpringApplication时会进行一系统的初始化

        private void initialize(Object[] sources) {
            if (sources != null && sources.length > 0) {
                this.sources.addAll(Arrays.asList(sources));
            }
            //过程a
            this.webEnvironment = deduceWebEnvironment();
            //过程b
            setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
            setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
            this.mainApplicationClass = deduceMainApplicationClass();
        }
    

    过程a是判断是否是web应用
    过程b就是获取spring.factories文件中ApplicationListener和ApplicationContextInitializer的相应实现类,具体是通过SpringFactoriesLoader类来实现的。

    private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
                                                                        Class<?>[] parameterTypes, Object... args) {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            
            //SpringFactoriesLoader 获取type对应的实现类
            Set<String> names = new LinkedHashSet<String>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
            
            //实例化各个实现类
            List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
                    classLoader, args, names);
            AnnotationAwareOrderComparator.sort(instances);
            return instances;
        }
    
       @SuppressWarnings("unchecked")
        private <T> List<T> createSpringFactoriesInstances(Class<T> type,
                                                           Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args,
                                                           Set<String> names) {
            List<T> instances = new ArrayList<T>(names.size());
            
            for (String name : names) {
                try {
                    
                    Class<?> instanceClass = ClassUtils.forName(name, classLoader);
                    
                    Assert.isAssignable(type, instanceClass);
                    
                    Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
                    
                    //实例化
                    T instance = (T) BeanUtils.instantiateClass(constructor, args);
                    
                    instances.add(instance);
                }
                catch (Throwable ex) {
                    throw new IllegalArgumentException(
                            "Cannot instantiate " + type + " : " + name, ex);
                }
            }
            return instances;
        }
    

    具体的SpringFactoriesLoader.loadFactoryNames

    public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
            String factoryClassName = factoryClass.getName();
            try {
                Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                        ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
                List<String> result = new ArrayList<String>();
                
                while (urls.hasMoreElements()) {
                    URL url = urls.nextElement();
                    Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                    String factoryClassNames = properties.getProperty(factoryClassName);
                    result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
                }
                return result;
            }
            catch (IOException ex) {
                throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
                        "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
            }
        }
    

    相关文章

      网友评论

          本文标题:spring.factories

          本文链接:https://www.haomeiwen.com/subject/gpoaixtx.html