美文网首页
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