Spring 源码解析五:Bean 的配置、定义、注册

x33g5p2x  于2022-02-11 发布在 Spring  
字(33.7k)|赞(0)|评价(0)|浏览(322)

在 Spring 源码解析二:上下文组件(WebApplicationContext) 中,留有一些点待解析:

  • ConfigurableListableBeanFactory如何加载、实例化 bean
  • ResourceEditorRegistrar如何注册属性编辑器、属性编辑器如何解析为对象
  • PathMatchingResourcePatternResolver如何解析、加载 locationPattern 指定的资源
  • PropertySourcesPropertyResolver如何是解析路径的
  • XmlBeanDefinitionReader如何是解析 bean 定义的
  • AnnotatedBeanDefinitionReader是如何注册 bean 的
  • ClassPathBeanDefinitionScanner是如何扫描包的

其中第一条已在Spring 源码解析三:Bean 的注册、解析、实例化机制中解析了,这一节来看看后面几条

1. ResourceEditorRegistrar

ResourceEditorRegistrar
的主要功能是在 bean 实例化的时候,在 beanDefinition 转换为 BeanWrapper 后用于对属性的填充

比如说,xml 中这样定义了一个 bean

<bean id="demoBean" class="com.example.DemoBean">
  <property name="date" value="2021-10-15" />
</bean>

com.example.DemoBean类中定义了一个属性dateDate类型的,但 Spring 从 xml 中读出来的是字符串,这就需要给 Spring 配置属性编辑器,把字符串转化成对象。

public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
    // 注册自定义编辑器
    @Override
    public void registerCustomEditors(PropertyEditorRegistry registry) {
        // 注册实体,暂时省略,后面再解析
        // 这里先解析PropertyEditorRegistry
    }
}

先来看看PropertyEditorRegistrySupport
是如何处理各种类型的属性编辑器的(PropertyEditorRegistry只是接口,PropertyEditorRegistrySupport是其默认实现)

1.1. PropertyEditorRegistrySupport

public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
    // 默认编辑器
    private Map<Class<?>, PropertyEditor> defaultEditors;
    // 覆盖默认编辑器
    private Map<Class<?>, PropertyEditor> overriddenDefaultEditors;
    // 自定义编辑器
    private Map<Class<?>, PropertyEditor> customEditors;
    // Path自定义编辑器
    private Map<String, CustomEditorHolder> customEditorsForPath;
    // 自定义编辑器缓存
    private Map<Class<?>, PropertyEditor> customEditorCache;
}

1.1.1. PropertyEditorRegistrySupport.getDefaultEditor

public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
    // 获取针对requiredType的默认编辑器
    public PropertyEditor getDefaultEditor(Class<?> requiredType) {
        // ... 代码省略

        if (this.overriddenDefaultEditors != null) {
            // 如果有自定义覆盖默认编辑器的,返回自定义默认编辑器
            PropertyEditor editor = this.overriddenDefaultEditors.get(requiredType);
            if (editor != null) {
                return editor;
            }
        }
        // 如果defaultEditors还没创建过,则创建
        if (this.defaultEditors == null) {
            createDefaultEditors();
        }
        return this.defaultEditors.get(requiredType);
    }

    // 创建默认编辑器,所有的基本、常用类型都囊括了
    private void createDefaultEditors() {
        this.defaultEditors = new HashMap<>(64);

        this.defaultEditors.put(Charset.class, new CharsetEditor());
        this.defaultEditors.put(Class.class, new ClassEditor());
        this.defaultEditors.put(Class[].class, new ClassArrayEditor());
        this.defaultEditors.put(Currency.class, new CurrencyEditor());
        this.defaultEditors.put(File.class, new FileEditor());
        this.defaultEditors.put(InputStream.class, new InputStreamEditor());

        this.defaultEditors.put(InputSource.class, new InputSourceEditor());

        this.defaultEditors.put(Locale.class, new LocaleEditor());
        this.defaultEditors.put(Path.class, new PathEditor());
        this.defaultEditors.put(Pattern.class, new PatternEditor());
        this.defaultEditors.put(Properties.class, new PropertiesEditor());
        this.defaultEditors.put(Reader.class, new ReaderEditor());
        this.defaultEditors.put(Resource[].class, new ResourceArrayPropertyEditor());
        this.defaultEditors.put(TimeZone.class, new TimeZoneEditor());
        this.defaultEditors.put(URI.class, new URIEditor());
        this.defaultEditors.put(URL.class, new URLEditor());
        this.defaultEditors.put(UUID.class, new UUIDEditor());
        this.defaultEditors.put(ZoneId.class, new ZoneIdEditor());

        this.defaultEditors.put(Collection.class, new CustomCollectionEditor(Collection.class));
        this.defaultEditors.put(Set.class, new CustomCollectionEditor(Set.class));
        this.defaultEditors.put(SortedSet.class, new CustomCollectionEditor(SortedSet.class));
        this.defaultEditors.put(List.class, new CustomCollectionEditor(List.class));
        this.defaultEditors.put(SortedMap.class, new CustomMapEditor(SortedMap.class));

        this.defaultEditors.put(byte[].class, new ByteArrayPropertyEditor());
        this.defaultEditors.put(char[].class, new CharArrayPropertyEditor());

        this.defaultEditors.put(char.class, new CharacterEditor(false));
        this.defaultEditors.put(Character.class, new CharacterEditor(true));

        this.defaultEditors.put(boolean.class, new CustomBooleanEditor(false));
        this.defaultEditors.put(Boolean.class, new CustomBooleanEditor(true));

        this.defaultEditors.put(byte.class, new CustomNumberEditor(Byte.class, false));
        this.defaultEditors.put(Byte.class, new CustomNumberEditor(Byte.class, true));
        this.defaultEditors.put(short.class, new CustomNumberEditor(Short.class, false));
        this.defaultEditors.put(Short.class, new CustomNumberEditor(Short.class, true));
        this.defaultEditors.put(int.class, new CustomNumberEditor(Integer.class, false));
        this.defaultEditors.put(Integer.class, new CustomNumberEditor(Integer.class, true));
        this.defaultEditors.put(long.class, new CustomNumberEditor(Long.class, false));
        this.defaultEditors.put(Long.class, new CustomNumberEditor(Long.class, true));
        this.defaultEditors.put(float.class, new CustomNumberEditor(Float.class, false));
        this.defaultEditors.put(Float.class, new CustomNumberEditor(Float.class, true));
        this.defaultEditors.put(double.class, new CustomNumberEditor(Double.class, false));
        this.defaultEditors.put(Double.class, new CustomNumberEditor(Double.class, true));
        this.defaultEditors.put(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, true));
        this.defaultEditors.put(BigInteger.class, new CustomNumberEditor(BigInteger.class, true));

        StringArrayPropertyEditor sae = new StringArrayPropertyEditor();
        this.defaultEditors.put(String[].class, sae);
        this.defaultEditors.put(short[].class, sae);
        this.defaultEditors.put(int[].class, sae);
        this.defaultEditors.put(long[].class, sae);
    }
}

这些默认的编辑器都比较简单,都在 beans/propertyeditors
这个包下,只有一个不在这个包下,也需要解析下:ResourceArrayPropertyEditor

ResourceArrayPropertyEditor 解析的是多个资源,如通配符*代表的多个资源

public class ResourceArrayPropertyEditor extends PropertyEditorSupport {
    // 转换String值为目标值
    @Override
    public void setAsText(String text) {
        // 解析path中的占位符${}
        String pattern = resolvePath(text).trim();
        try {
            // 使用ResourcePatternResolver.getResources解析
            setValue(this.resourcePatternResolver.getResources(pattern));
        }
        catch (IOException ex) {
            // ... 代码省略
        }
    }

    // 设置转换的值
    @Override
    public void setValue(Object value) throws IllegalArgumentException {
        // 如果是Collection,继续处理
        // 如果是数组,但还没有转化为Resource,继续处理
        if (value instanceof Collection || (value instanceof Object[] && !(value instanceof Resource[]))) {
            Collection<?> input = (value instanceof Collection ? (Collection<?>) value : Arrays.asList((Object[]) value));
            Set<Resource> merged = new LinkedHashSet<>();
            for (Object element : input) {
                if (element instanceof String) {
                    // 解析path中的占位符${}
                    String pattern = resolvePath((String) element).trim();
                    try {
                        // 转化为Resource,并添加
                        Resource[] resources = this.resourcePatternResolver.getResources(pattern);
                        Collections.addAll(merged, resources);
                    }
                    catch (IOException ex) {
                        // ... 代码省略
                    }
                }
                else if (element instanceof Resource) {
                    // 如果本来就是Resource,则添加
                    merged.add((Resource) element);
                }
                else {
                    // ... 代码省略
                }
            }
            super.setValue(merged.toArray(new Resource[0]));
        }
        else {
            super.setValue(value);
        }
    }
}

1.1.2. PropertyEditorRegistrySupport.registerCustomEditor

public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
    // 注册自定义编辑器
    @Override
    public void registerCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath, PropertyEditor propertyEditor) {
        // ... 代码省略

        // 如果有propertyPath,注册到customEditorsForPath中
        if (propertyPath != null) {
            if (this.customEditorsForPath == null) {
                this.customEditorsForPath = new LinkedHashMap<>(16);
            }
            this.customEditorsForPath.put(propertyPath, new CustomEditorHolder(propertyEditor, requiredType));
        }
        // 不然,注册到customEditors中
        else {
            if (this.customEditors == null) {
                this.customEditors = new LinkedHashMap<>(16);
            }
            this.customEditors.put(requiredType, propertyEditor);
            this.customEditorCache = null;
        }
    }

    // 添加针对requiredType的覆盖默认编辑器
    public void overrideDefaultEditor(Class<?> requiredType, PropertyEditor propertyEditor) {
        if (this.overriddenDefaultEditors == null) {
            this.overriddenDefaultEditors = new HashMap<>();
        }
        this.overriddenDefaultEditors.put(requiredType, propertyEditor);
    }
}

1.2. ResourceEditorRegistrar.registerCustomEditors

public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
    // 注册自定义编辑器
    @Override
    public void registerCustomEditors(PropertyEditorRegistry registry) {
        // 使用当前的resourceLoader,覆盖Resource、InputStream、File、Path等的默认资源加载器
        // 其他的处理方式不变
        ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
        doRegisterEditor(registry, Resource.class, baseEditor);
        doRegisterEditor(registry, ContextResource.class, baseEditor);
        doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
        doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
        doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
        doRegisterEditor(registry, Path.class, new PathEditor(baseEditor));
        doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
        doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));

        ClassLoader classLoader = this.resourceLoader.getClassLoader();
        doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
        doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
        doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader));

        if (this.resourceLoader instanceof ResourcePatternResolver) {
            doRegisterEditor(registry, Resource[].class,
                    new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver));
        }
    }

    // 如果可以,覆盖默认编辑器,不然注册自定义编辑器
    private void doRegisterEditor(PropertyEditorRegistry registry, Class<?> requiredType, PropertyEditor editor) {
        if (registry instanceof PropertyEditorRegistrySupport) {
            ((PropertyEditorRegistrySupport) registry).overrideDefaultEditor(requiredType, editor);
        }
        else {
            registry.registerCustomEditor(requiredType, editor);
        }
    }
}

2. PathMatchingResourcePatternResolver

PathMatchingResourcePatternResolver
是一个 Ant 模式通配符的 Resource 查找器,可以用来查找类路径下或者文件系统中的资源

Ant 模式匹配规则如下

  1. ? 匹配一个字符
  2. * 匹配 0 个或多个字符
  3. ** 匹配 0 个或多个目录

例如

  • /trip/api/*x 匹配 /trip/api/x/trip/api/ax/trip/api/abx,但不匹配 /trip/abc/x
  • /trip/a/a?x 匹配 /trip/a/abx,但不匹配 /trip/a/ax/trip/a/abcx
  • /**/api/alie 匹配 /trip/api/alie/trip/dax/api/alie,但不匹配 /trip/a/api
  • /**/*.htmlm 匹配所有以 .htmlm 结尾的路径
public class PathMatchingResourcePatternResolver implements ResourcePatternResolver {
    // 默认使用Ant模式通配符
    private PathMatcher pathMatcher = new AntPathMatcher();

    // 解析 locationPattern 指定的资源
    @Override
    public Resource[] getResources(String locationPattern) throws IOException {
        // 以"classpath*:"开头
        if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
            // 有*?{}符号的通配符
            if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
                // 找出含有*?{}符号路径涵盖的资源
                return findPathMatchingResources(locationPattern);
            }
            else {
                // 无通配符,当做纯字符对待
                return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
            }
        }
        else {
            // 以"war:"开头或其他有:的路径
            int prefixEnd = (locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 :
                    locationPattern.indexOf(':') + 1);
            if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
                // 找出含有*?{}符号路径涵盖的资源
                return findPathMatchingResources(locationPattern);
            }
            else {
                // 不然,当做单个名字资源
                return new Resource[] {getResourceLoader().getResource(locationPattern)};
            }
        }
    }

}

2.1. PathMatchingResourcePatternResolver.findPathMatchingResources

public class PathMatchingResourcePatternResolver implements ResourcePatternResolver {
    // 找出含有*?{}符号路径涵盖的资源
    protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
        // 返回根路径,如"/WEB-INF/*.xml"的根路径是"/WEB-INF/"
        String rootDirPath = determineRootDir(locationPattern);
        // 去除根路径的子路径
        String subPattern = locationPattern.substring(rootDirPath.length());
        // 获取根路径下的所有资源
        Resource[] rootDirResources = getResources(rootDirPath);
        // 结果集
        Set<Resource> result = new LinkedHashSet<>(16);
        for (Resource rootDirResource : rootDirResources) {
            // 解析有:的协议
            URL rootDirUrl = rootDirResource.getURL();
            // bundle协议
            if (rootDirUrl.getProtocol().startsWith("bundle")) {
                // 当做UrlResource
                rootDirResource = new UrlResource(rootDirUrl);
            }
            // vfs协议
            if (rootDirUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
                result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirUrl, subPattern, getPathMatcher()));
            }
            // jar,war,zip,wsjar,vfszip协议
            else if (ResourceUtils.isJarURL(rootDirUrl) || isJarResource(rootDirResource)) {
                // 从jar文件中载入资源
                result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirUrl, subPattern));
            }
            else {
                // 从系统文件中载入资源
                result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
            }
        }
        return result.toArray(new Resource[0]);
    }
}

2.2. PathMatchingResourcePatternResolver.findAllClassPathResources

public class PathMatchingResourcePatternResolver implements ResourcePatternResolver {
    // 找出无通配符路径涵盖的资源
    protected Resource[] findAllClassPathResources(String location) throws IOException {
        // 去掉开头的/
        String path = location;
        if (path.startsWith("/")) {
            path = path.substring(1);
        }
        Set<Resource> result = doFindAllClassPathResources(path);
        return result.toArray(new Resource[0]);
    }

    protected Set<Resource> doFindAllClassPathResources(String path) throws IOException {
        Set<Resource> result = new LinkedHashSet<>(16);
        ClassLoader cl = getClassLoader();
        // 通过classloader加载资源
        Enumeration<URL> resourceUrls = (cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path));
        while (resourceUrls.hasMoreElements()) {
            URL url = resourceUrls.nextElement();
            // url转换为UrlResource,再添加
            result.add(convertClassLoaderURL(url));
        }
        if (!StringUtils.hasLength(path)) {
            // 处理jar资源,系统文件资源
            addAllClassLoaderJarRoots(cl, result);
        }
        return result;
    }
}

3. PropertySourcesPropertyResolver

PropertySourcesPropertyResolver
的主要功能是通过@PropertySource注解将属性来源注入到有如@Configuration, @Component, ...注解的类中

public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
    // 字符值到对象的转换器,默认使用DefaultConversionService
    private volatile ConfigurableConversionService conversionService;
    // 占位符的前缀,默认是 ${
    private String placeholderPrefix = SystemPropertyUtils.PLACEHOLDER_PREFIX;
    // 占位符的后缀,默认是 }
    private String placeholderSuffix = SystemPropertyUtils.PLACEHOLDER_SUFFIX;
    // 多个值的分隔符,默认 :
    private String valueSeparator = SystemPropertyUtils.VALUE_SEPARATOR;
}
public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
    // 获取一个属性值
    protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
        if (this.propertySources != null) {
            // 从来源中遍历
            for (PropertySource<?> propertySource : this.propertySources) {
                // 来源中获取值
                Object value = propertySource.getProperty(key);
                if (value != null) {
                    if (resolveNestedPlaceholders && value instanceof String) {
                        // 解析占位符
                        value = resolveNestedPlaceholders((String) value);
                    }

                    // 转换当前值到其他类型对象,如果需要的话
                    return convertValueIfNecessary(value, targetValueType);
                }
            }
        }
        // 没有就返回null
        return null;
    }

    // 解析占位符
    protected String resolveNestedPlaceholders(String value) {
        // ... 代码省略

        return resolvePlaceholders(value);
    }

    // 解析占位符
    public String resolvePlaceholders(String text) {
        if (this.nonStrictHelper == null) {
            this.nonStrictHelper = createPlaceholderHelper(true);
        }
        // 替换占位符
        return doResolvePlaceholders(text, this.nonStrictHelper);
    }

    // 转换当前值到其他类型对象,如果需要的话
    protected <T> T convertValueIfNecessary(Object value, Class<T> targetType) {
        // ... 代码省略

        ConversionService conversionServiceToUse = this.conversionService;
        if (conversionServiceToUse == null) {
            // ... 代码省略

            // 获取默认的转换器DefaultConversionService
            conversionServiceToUse = DefaultConversionService.getSharedInstance();
        }
        // 转换值
        return conversionServiceToUse.convert(value, targetType);
    }
}

来看看 DefaultConversionService
是如何转换对象的

public class DefaultConversionService extends GenericConversionService {
    public DefaultConversionService() {
        // 初始化的时候就添加默认转换器
        addDefaultConverters(this);
    }

    // 添加默认转换器
    public static void addDefaultConverters(ConverterRegistry converterRegistry) {
        // 添加标量类转换器
        addScalarConverters(converterRegistry);
        // 添加集合类转换器
        addCollectionConverters(converterRegistry);

        // 转换ByteBuffer或字节数组到其他任意类型
        converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));
        converterRegistry.addConverter(new StringToTimeZoneConverter());
        converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());
        converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter());

        converterRegistry.addConverter(new ObjectToObjectConverter());
        converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));
        converterRegistry.addConverter(new FallbackObjectToStringConverter());
        converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry));
    }

    // 添加集合类转换器
    public static void addCollectionConverters(ConverterRegistry converterRegistry) {
        ConversionService conversionService = (ConversionService) converterRegistry;

        // 数组转集合
        converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService));
        // 集合转数组
        converterRegistry.addConverter(new CollectionToArrayConverter(conversionService));

        // 数组转另一种数组
        converterRegistry.addConverter(new ArrayToArrayConverter(conversionService));
        // 集合转另一种集合
        converterRegistry.addConverter(new CollectionToCollectionConverter(conversionService));
        // Map转另一种Map
        converterRegistry.addConverter(new MapToMapConverter(conversionService));

        converterRegistry.addConverter(new ArrayToStringConverter(conversionService));
        converterRegistry.addConverter(new StringToArrayConverter(conversionService));

        converterRegistry.addConverter(new ArrayToObjectConverter(conversionService));
        converterRegistry.addConverter(new ObjectToArrayConverter(conversionService));

        converterRegistry.addConverter(new CollectionToStringConverter(conversionService));
        converterRegistry.addConverter(new StringToCollectionConverter(conversionService));

        converterRegistry.addConverter(new CollectionToObjectConverter(conversionService));
        converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService));

        // 转换Stream到数组或集合
        converterRegistry.addConverter(new StreamConverter(conversionService));
    }

    // 添加标量类转换器
    private static void addScalarConverters(ConverterRegistry converterRegistry) {
        // 一个jdk版本的数字转换到其他jdk版本的数字
        converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());

        converterRegistry.addConverterFactory(new StringToNumberConverterFactory());
        converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter());

        converterRegistry.addConverter(new StringToCharacterConverter());
        converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter());

        converterRegistry.addConverter(new NumberToCharacterConverter());
        converterRegistry.addConverterFactory(new CharacterToNumberFactory());

        converterRegistry.addConverter(new StringToBooleanConverter());
        converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());

        converterRegistry.addConverterFactory(new StringToEnumConverterFactory());
        converterRegistry.addConverter(new EnumToStringConverter((ConversionService) converterRegistry));

        converterRegistry.addConverterFactory(new IntegerToEnumConverterFactory());
        converterRegistry.addConverter(new EnumToIntegerConverter((ConversionService) converterRegistry));

        converterRegistry.addConverter(new StringToLocaleConverter());
        converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter());

        converterRegistry.addConverter(new StringToCharsetConverter());
        converterRegistry.addConverter(Charset.class, String.class, new ObjectToStringConverter());

        converterRegistry.addConverter(new StringToCurrencyConverter());
        converterRegistry.addConverter(Currency.class, String.class, new ObjectToStringConverter());

        // String转Properties对象
        converterRegistry.addConverter(new StringToPropertiesConverter());
        // Properties对象转String
        converterRegistry.addConverter(new PropertiesToStringConverter());

        converterRegistry.addConverter(new StringToUUIDConverter());
        converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter());
    }
}

这些默认的编辑器都在 convert/support
包下,都不难,举个较复杂一点的例子 ArrayToCollectionConverter

final class ArrayToCollectionConverter implements ConditionalGenericConverter {
    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
        // ... 代码省略

        // 先获取数组长度
        int length = Array.getLength(source);
        TypeDescriptor elementDesc = targetType.getElementTypeDescriptor();
        // 创建集合
        Collection<Object> target = CollectionFactory.createCollection(targetType.getType(),
                (elementDesc != null ? elementDesc.getType() : null), length);

        // 元素不需要转换
        if (elementDesc == null) {
            for (int i = 0; i < length; i++) {
                Object sourceElement = Array.get(source, i);
                target.add(sourceElement);
            }
        }
        // 元素需要转换
        else {
            for (int i = 0; i < length; i++) {
                Object sourceElement = Array.get(source, i);
                // 调用注入的conversionService转换元素后,再添加
                Object targetElement = this.conversionService.convert(sourceElement,
                        sourceType.elementTypeDescriptor(sourceElement), elementDesc);
                target.add(targetElement);
            }
        }
        return target;
    }
}

4. XmlBeanDefinitionReader

XmlBeanDefinitionReader
的主要功能是从xml中解析 bean 定义

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
    // 从一个来源处加载bean定义
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        // 获取线程池来装载来源
        Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();

        if (!currentResources.add(encodedResource)) {
            // 如果添加失败,报错
        }

        try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            // 通过资源流来加载bean定义
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        }
        catch (IOException ex) {
            // ... 代码省略
        }
        finally {
            // ... 代码省略
        }
    }

    // 通过资源流来加载bean定义
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {

        try {
            // 获取xml文件的Document对象
            Document doc = doLoadDocument(inputSource, resource);
            int count = registerBeanDefinitions(doc, resource);

            // ... 代码省略

            return count;
        }
        catch (BeanDefinitionStoreException ex) {
            // ... 代码省略
        }
        // ... 代码省略
    }

    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        // 实例化一个BeanDefinitionDocumentReader对象,默认使用DefaultBeanDefinitionDocumentReader
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();

        // ... 代码省略

        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));

        // ... 代码省略
    }
}

本质上还是调用的 DefaultBeanDefinitionDocumentReader.registerBeanDefinitions

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    // 注册bean定义
    @Override
    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
        this.readerContext = readerContext;
        doRegisterBeanDefinitions(doc.getDocumentElement());
    }

    // 从doc根元素开始寻找并注册bean定义
    protected void doRegisterBeanDefinitions(Element root) {
        BeanDefinitionParserDelegate parent = this.delegate;
        // 实例化一个新的bean定义解析器
        this.delegate = createDelegate(getReaderContext(), root, parent);

        // ... 代码省略

        // 解析bean定义
        parseBeanDefinitions(root, this.delegate);

        // ... 代码省略
    }

    // 解析bean定义
    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        // 如果bean定义的xmlns命名空间为空,或者为http://www.springframework.org/schema/beans
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();
            // 遍历子节点
            for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);
                if (node instanceof Element) {
                    Element ele = (Element) node;
                    // 如果bean定义的xmlns命名空间为空,或者为http://www.springframework.org/schema/beans
                    // 做默认解析
                    if (delegate.isDefaultNamespace(ele)) {
                        parseDefaultElement(ele, delegate);
                    }
                    // 不然做自定义解析
                    else {
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            // 解析自定义的元素
            delegate.parseCustomElement(root);
        }
    }
}
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    // 做默认解析
    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        // 如果是<import>元素,导入其他资源
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }
        // 如果是<alias>元素,注册别名
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }
        // 如果是<bean>元素,注册bean定义
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
            processBeanDefinition(ele, delegate);
        }
        // 如果是<beans>元素,解析子元素
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            doRegisterBeanDefinitions(ele);
        }
    }

    // 如果是<bean>元素,注册bean定义
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        // 解析bean的名字、别名、定义,包裹为BeanDefinitionHolder
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {

            // ... 代码省略

            try {
                // 调用getReaderContext().getRegistry()注册bean定义
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
            }
            catch (BeanDefinitionStoreException ex) {
                // ... 代码省略
            }
            // ... 代码省略
        }
    }
}

再进一层,还是调用的 BeanDefinitionParserDelegate

public class BeanDefinitionParserDelegate {
    // 解析自定义的元素
    public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
        // 获取xmlns命名空间
        String namespaceUri = getNamespaceURI(ele);
        // 没有xmlns命名空间,返回null
        if (namespaceUri == null) {
            return null;
        }
        // 获取命名空间处理器,默认使用DefaultNamespaceHandlerResolver
        // DefaultNamespaceHandlerResolver中,默认加载META-INF/spring.handlers指定的处理器
        // 核心的处理器是下面这些
        // http\://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler
        // http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
        // http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler
        // http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
        // http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
        // http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
        // http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
        // http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler
        // http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
        // http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
        // http\://www.springframework.org/schema/jdbc=org.springframework.jdbc.config.JdbcNamespaceHandler
        // http\://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler
        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);

        // ... 代码省略

        // 调用处理器解析
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }
}

列举一下这些处理器,后面再解析:

public class BeanDefinitionParserDelegate {
    // 解析有bean定义的元素
    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
        // 获取id属性
        String id = ele.getAttribute(ID_ATTRIBUTE);
        // 获取name属性
        String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

        List<String> aliases = new ArrayList<>();
        if (StringUtils.hasLength(nameAttr)) {
            // 用,;分隔为多个别名
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            aliases.addAll(Arrays.asList(nameArr));
        }

        // 默认以id属性作为beanName
        String beanName = id;
        // 如果没有id属性,但有name属性,取第一个name作为beanName
        if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
            beanName = aliases.remove(0);
        }

        // ... 代码省略

        // 真正解析bean定义
        AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
        if (beanDefinition != null) {
            if (!StringUtils.hasText(beanName)) {
                // 如果没有beanName,生成默认的beanName
                try {
                    if (containingBean != null) {
                        beanName = BeanDefinitionReaderUtils.generateBeanName(
                                beanDefinition, this.readerContext.getRegistry(), true);
                    }
                    else {
                        beanName = this.readerContext.generateBeanName(beanDefinition);

                        // ... 代码省略
                    }

                }
                catch (Exception ex) {
                    // ... 代码省略

                    return null;
                }
            }
            String[] aliasesArray = StringUtils.toStringArray(aliases);
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        }

        return null;
    }

    // 深层解析bean定义
    public AbstractBeanDefinition parseBeanDefinitionElement(
            Element ele, String beanName, @Nullable BeanDefinition containingBean) {

        // class属性
        String className = null;
        if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
            className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
        }

        // parent属性
        String parent = null;
        if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
        }

        try {
            // 以class、parent创建一个基础的定义对象
            AbstractBeanDefinition bd = createBeanDefinition(className, parent);
            // 把其他属性应用到定义对象上,如singleton、abstract、lazy-init、autowire、depends-on等
            parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
            // 设置description属性
            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

            // 解析meta元素
            parseMetaElements(ele, bd);
            // 解析lookup-method元素
            parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
            // 解析replaced-method元素
            parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

            // 解析constructor-arg元素
            parseConstructorArgElements(ele, bd);
            // 解析property元素
            parsePropertyElements(ele, bd);
            // 解析qualifier元素
            parseQualifierElements(ele, bd);

            // ... 代码省略

            return bd;
        }
        catch (ClassNotFoundException ex) {
            // ... 代码省略
        }
        // ... 代码省略

        return null;
    }
}

5. AnnotatedBeanDefinitionReader

AnnotatedBeanDefinitionReader
的主要功能是通过注解注册 bean

public class AnnotatedBeanDefinitionReader {
    public void registerBean(Class<?> beanClass) {
        doRegisterBean(beanClass, null, null, null, null);
    }

    public void registerBean(Class<?> beanClass, @Nullable String name) {
        doRegisterBean(beanClass, name, null, null, null);
    }

    public void registerBean(Class<?> beanClass, Class<? extends Annotation>... qualifiers) {
        doRegisterBean(beanClass, null, qualifiers, null, null);
    }

    public void registerBean(Class<?> beanClass, @Nullable String name,
            Class<? extends Annotation>... qualifiers) {

        doRegisterBean(beanClass, name, qualifiers, null, null);
    }

    public <T> void registerBean(Class<T> beanClass, @Nullable Supplier<T> supplier) {
        doRegisterBean(beanClass, null, null, supplier, null);
    }

    public <T> void registerBean(Class<T> beanClass, @Nullable String name, @Nullable Supplier<T> supplier) {
        doRegisterBean(beanClass, name, null, supplier, null);
    }

    public <T> void registerBean(Class<T> beanClass, @Nullable String name, @Nullable Supplier<T> supplier,
            BeanDefinitionCustomizer... customizers) {

        doRegisterBean(beanClass, name, null, supplier, customizers);
    }

    // 注册bean
    private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
            @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
            @Nullable BeanDefinitionCustomizer[] customizers) {

        // 创建一个基础的注解bean定义
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);

        // ... 代码省略

        // 确保beanName
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

        // 处理元信息通用的注解,如Lazy、Primary、DependsOn、Role、Description
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        // qualifier注解的处理
        if (qualifiers != null) {
            for (Class<? extends Annotation> qualifier : qualifiers) {
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                }
                else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                }
                else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }

        // 自定义处理器
        if (customizers != null) {
            for (BeanDefinitionCustomizer customizer : customizers) {
                customizer.customize(abd);
            }
        }

        // 封装为Holder
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

        // ... 代码省略

        // 注册到registry中
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }
}

6. ClassPathBeanDefinitionScanner

ClassPathBeanDefinitionScanner
的主要功能是扫描指定包来获取 bean

public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
    // 扫描包
    public int scan(String... basePackages) {
        // ... 代码省略

        // 扫描
        doScan(basePackages);

        // 注册注解解析处理器
        if (this.includeAnnotationConfig) {
            // 主要是下面的bean
            // org.springframework.context.annotation.internalConfigurationAnnotationProcessor => ConfigurationClassPostProcessor
            // org.springframework.context.annotation.internalAutowiredAnnotationProcessor => AutowiredAnnotationBeanPostProcessor
            // org.springframework.context.annotation.internalCommonAnnotationProcessor => CommonAnnotationBeanPostProcessor
            // org.springframework.context.annotation.internalPersistenceAnnotationProcessor => PersistenceAnnotationBeanPostProcessor
            // org.springframework.context.event.internalEventListenerProcessor => EventListenerMethodProcessor
            // org.springframework.context.event.internalEventListenerFactory => DefaultEventListenerFactory
            AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
        }

        // ... 代码省略
    }

    // 扫描
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        // 初始化容器
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();

        // 遍历包
        for (String basePackage : basePackages) {
            // 获取包中可以处理的组件
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);

            // 遍历组件
            for (BeanDefinition candidate : candidates) {
                // 生成bean名字
                String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                if (candidate instanceof AbstractBeanDefinition) {
                    // 注入一些默认值,并确定是否需要自动装配其他的bean
                    postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
                }
                if (candidate instanceof AnnotatedBeanDefinition) {
                    // 处理元信息通用的注解,如Lazy、Primary、DependsOn、Role、Description
                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
                }
                // 如果不存在,可添加
                if (checkCandidate(beanName, candidate)) {
                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);

                    // ... 代码省略

                    beanDefinitions.add(definitionHolder);
                    // 注册到registry中
                    registerBeanDefinition(definitionHolder, this.registry);
                }
            }
        }
        return beanDefinitions;
    }

    // 获取包中可以处理的组件
    public Set<BeanDefinition> findCandidateComponents(String basePackage) {
        // ... 代码省略

        return scanCandidateComponents(basePackage);
    }

    // 获取包中可以处理的组件
    private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
        Set<BeanDefinition> candidates = new LinkedHashSet<>();
        try {
            // 加上"classpath*:"前缀,"**/*.class"后缀
            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                    basePackage + '/' + this.resourcePattern;
            // 获取包下的全部类
            Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
            // 遍历资源
            for (Resource resource : resources) {
                // 如果资源可读,继续进行
                if (resource.isReadable()) {
                    try {
                        // 获取元信息读取器
                        MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                        // 初始化一个基础的bean定义
                        ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                        sbd.setSource(resource);

                        // 添加
                        candidates.add(sbd);
                    }
                    catch (Throwable ex) {
                        // ... 代码省略
                    }
                }
                else {
                    // ... 代码省略
                }
            }
        }
        catch (IOException ex) {
            // ... 代码省略
        }
        return candidates;
    }
}

列举一下这些处理器,后面再解析:

后续

更多博客,查看 https://github.com/senntyou/blogs

作者:深予之 (@senntyou)

版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证

相关文章