Spring 源码解析五:Bean 的配置、定义、注册
在 Spring 源码解析二:上下文组件(WebApplicationContext) 中,留有一些点待解析:
ConfigurableListableBeanFactory
如何加载、实例化 beanResourceEditorRegistrar
如何注册属性编辑器、属性编辑器如何解析为对象PathMatchingResourcePatternResolver
如何解析、加载 locationPattern 指定的资源PropertySourcesPropertyResolver
如何是解析路径的XmlBeanDefinitionReader
如何是解析 bean 定义的AnnotatedBeanDefinitionReader
是如何注册 bean 的ClassPathBeanDefinitionScanner
是如何扫描包的
其中第一条已在 Spring 源码解析三:Bean 的注册、解析、实例化机制 中解析了,这一节来看看后面几条
1. ResourceEditorRegistrar
ResourceEditorRegistrar
的主要功能是在 bean 实例化的时候,在 beanDefinition 转换为 BeanWrapper 后用于对属性的填充
比如说,xml 中这样定义了一个 bean
在com.example.DemoBean
类中定义了一个属性date
是Date
类型的,但 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, PropertyEditor> defaultEditors;
// 覆盖默认编辑器
private Map, PropertyEditor> overriddenDefaultEditors;
// 自定义编辑器
private Map, PropertyEditor> customEditors;
// Path自定义编辑器
private Map customEditorsForPath;
// 自定义编辑器缓存
private Map, 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 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 模式匹配规则如下
?
匹配一个字符*
匹配 0 个或多个字符**
匹配 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 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 result = doFindAllClassPathResources(path);
return result.toArray(new Resource[0]);
}
protected Set doFindAllClassPathResources(String path) throws IOException {
Set result = new LinkedHashSet<>(16);
ClassLoader cl = getClassLoader();
// 通过classloader加载资源
Enumeration 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 getProperty(String key, Class 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 convertValueIfNecessary(Object value, Class 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
4. XmlBeanDefinitionReader
XmlBeanDefinitionReader
的主要功能是从xml
中解析 bean 定义
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
// 从一个来源处加载bean定义
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
// 获取线程池来装载来源
Set 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) {
// 如果是元素,导入其他资源
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
// 如果是元素,注册别名
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// 如果是元素,注册bean定义
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
// 如果是元素,解析子元素
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
doRegisterBeanDefinitions(ele);
}
}
// 如果是元素,注册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));
}
}
列举一下这些处理器,后面再解析:
- SimpleConstructorNamespaceHandler
- SimplePropertyNamespaceHandler
- UtilNamespaceHandler
- ContextNamespaceHandler
- JeeNamespaceHandler
- LangNamespaceHandler
- TaskNamespaceHandler
- CacheNamespaceHandler
- MvcNamespaceHandler
- AopNamespaceHandler
- JdbcNamespaceHandler
- TxNamespaceHandler
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 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... qualifiers) {
doRegisterBean(beanClass, null, qualifiers, null, null);
}
public void registerBean(Class beanClass, @Nullable String name,
Class... qualifiers) {
doRegisterBean(beanClass, name, qualifiers, null, null);
}
public void registerBean(Class beanClass, @Nullable Supplier supplier) {
doRegisterBean(beanClass, null, null, supplier, null);
}
public void registerBean(Class beanClass, @Nullable String name, @Nullable Supplier supplier) {
doRegisterBean(beanClass, name, null, supplier, null);
}
public void registerBean(Class beanClass, @Nullable String name, @Nullable Supplier supplier,
BeanDefinitionCustomizer... customizers) {
doRegisterBean(beanClass, name, null, supplier, customizers);
}
// 注册bean
private void doRegisterBean(Class beanClass, @Nullable String name,
@Nullable Class[] qualifiers, @Nullable Supplier 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 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 doScan(String... basePackages) {
// 初始化容器
Set beanDefinitions = new LinkedHashSet<>();
// 遍历包
for (String basePackage : basePackages) {
// 获取包中可以处理的组件
Set 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 findCandidateComponents(String basePackage) {
// ... 代码省略
return scanCandidateComponents(basePackage);
}
// 获取包中可以处理的组件
private Set scanCandidateComponents(String basePackage) {
Set 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;
}
}
列举一下这些处理器,后面再解析:
- ConfigurationClassPostProcessor
- AutowiredAnnotationBeanPostProcessor
- CommonAnnotationBeanPostProcessor
- PersistenceAnnotationBeanPostProcessor
- EventListenerMethodProcessor
- DefaultEventListenerFactory
后续
更多博客,查看 https://github.com/senntyou/blogs
版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证)