Spring——O3. Bean 注册

  1. 默认标签解析
parseDefaultElement

// 如果在默认标签中有自定义标签属性,还需要进行自定义标签解析
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);			// 装饰者模式 + SPI

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

  1. 自定义标签解析:详细见下面分析。以 context:component-sacn 为例,在 ClassPathBeanDefinitionScanner 中,创建 BeanDefinition,ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);,然后对属性或注解进行解析,setXxx

两种标签都是先封装成 BeanDefinitionHolder,BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);beanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);,再从 BeanDefinitionHolder 中拿出 beanDefinition、beanName,注册到 DefaultListableBeanFactory 中的 beanDefinitionMap、beanDefinitionNames 中,从 BeanDefinitionHolder 中拿出 alias,注册到 SimpleAliasRegistry 中的 aliasMap 中。

3. 自定义标签解析

3.1 自定义标签创建步骤

  1. 创建一个需要扩展的组件
  2. 定义一个 XSD 文件描述组件内容
  3. 创建一个类,实现 BeanDefinitionParser 接口,用来解析 XSD 文件中的定义、组件定义
  4. 创建一个 Handler 类,继承自 NamespaceHandlerSupport
  5. 编写 .handlers、.schemas

3.2 自定义标签创建举例

  1. 创建一个需要扩展的组件
public class Contact {
    private String id;
    private String userName;
    private String email;
	// getter、setter
}
  1. 定义一个XSD文件描述组件内容

META-INF/user.xsd

<?xml version="1.0" encoding="UTF-8" ?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://www.mustang.com/schema/user"
        elementFormDefault="qualified">
    <element name="contact">
        <complexType>
            <attribute name="id" type="string"/>
            <attribute name="userName" type="string"/>
            <attribute name="email" type="string"/>
        </complexType>
    </element>
</schema>
  1. 创建一个类,实现 BeanDefinitionParser 接口,用来解析 XSD 文件中的定义、组件定义
public class ContactBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    /**
     * Element 对应的类
     */
    @Override
    protected Class<?> getBeanClass(Element element) {
        return Contact.class;
    }

    /**
     * 从 element 中解析并提取对应的元素
     */
    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        String userName = element.getAttribute("userName");
        String email = element.getAttribute("email");
        // 将提取的数据放入到 BeanDefinitionBuilder 中,待到完成所有 bean 的解析后统一注册到 beanFactory 中
        if (StringUtils.hasText(userName)) {
            builder.addPropertyValue("userName", userName);
        }
        if (StringUtils.hasText(email)) {
            builder.addPropertyValue("email", email);
        }
    }
}
  1. 创建一个 Handler 类,继承自 NamespaceHandlerSupport
public class UserNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        registerBeanDefinitionParser("contact", new ContactBeanDefinitionParser());
    }
}
  1. 编写 .handlers、.schemas

META-INF/spring.schemas

http\://www.mustang.com/schema/user.xsd=META-INF/user.xsd

META-INF/spring.handlers

http\://www.mustang.com/schema/user=com.mustang.custom.UserNamespaceHandler
  1. xml 配置自定义标签的 bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:user="http://www.mustang.com/schema/user"
       xsi:schemaLocation=
               http://www.mustang.com/schema/user http://www.mustang.com/schema/user.xsd">

    <user:contact id="userId" email="userEmail" userName="userName"/>
</beans>
  1. 测试
public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
    Contact bean = (Contact)context.getBean("userId");
    System.out.println(bean);
}

3.3 自定义标签解析流程

  1. 根据当前解析标签的头信息找到对应的 namespaceUri
  2. 加载 spring 所有 jar 中的 META-INF/spring.handlers 文件,并建立映射关系
  3. 根据 namespaceUri 从映射关系中找到对应的实现了 NamespaceHandler 接口的类
  4. 调用类的 init 方法完成标签解析类的注册
  5. 根据 namespaceUri 找到对应的解析类,然后调用 parser 方法完成标签解析

3.4 自定义标签解析源码

BeanDefinitionParserDelegate # parseCustomElement

public BeanDefinition parseCustomElement(Element ele) {
	// containingBd 为父类 Bean,对顶层元素的解析应设置为 null
	return parseCustomElement(ele, null);
}
BeanDefinitionParserDelegate # parseCustomElement

/**
 * 对非默认命名空间的元素节点的解析,过程为:
 * 1. 获取标签的 namespaceUri
 * 2. 加载 META-INF/spring.handlers 配置文件,建立映射关系
 * 3. 根据 namespaceUri 从映射关系中获取NamespaceHandler 处理类
 * 4. 调用 NamespaceHandler 的 init 方法完成标签解析类的注册
 * 5. 调用 NamespaceHandler 的 parse 方法开始真正标签解析过程
 */
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
	// 1. 获取对应的命名空间
	String namespaceUri = getNamespaceURI(ele);
	if (namespaceUri == null) {
		return null;
	}
	// 2. 根据命名空间找到对应的 NamespaceHandler
	// 在 readerContext 初始化时其属性 namespaceHandlerResolver 已经被初始化为 DefaultNamespaceHandlerResolver 的实例,所以,
	// 这里调用的 resolve 方法其实调用的是 DefaultNamespaceHandlerResolver 类中的方法
	NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
	if (handler == null) {
		error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
		return null;
	}
	// 3. 调用自定义的 NamespaceHandler 进行解析
	/**
	 * public class UserNamespaceHandler extends NamespaceHandlerSupport {
	 *     @Override
	 *     public void init() {
	 *         registerBeanDefinitionParser("contact", new ContactBeanDefinitionParser());
	 *     }
	 * }
	 */
	// 以上面为例,此时的 handler 已经被实例化为我们自定义的 UserNamespaceHandler,UserNamespaceHandler 也完成了初始化
	// 调用 NamespaceHandlerSupport.parse
	return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
DefaultNamespaceHandlerResolver # resolve

public NamespaceHandler resolve(String namespaceUri) {
	// 读取 spring.handlers 配置文件并将配置文件缓存到 map 中
	Map<String, Object> handlerMappings = getHandlerMappings();
	// 根据命名空间找到对应的信息
	Object handlerOrClassName = handlerMappings.get(namespaceUri);
	if (handlerOrClassName == null) {
		return null;
	}
	else if (handlerOrClassName instanceof NamespaceHandler) {
		// 已经做过解析的情况,直接从缓存中读取
		return (NamespaceHandler) handlerOrClassName;
	}
	else {
		// 没有做过解析,则返回的是类路径
		String className = (String) handlerOrClassName;
		try {
			// 使用反射,将类路径转化为类
			Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
			if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
				throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
						"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
			}
			// 初始化类
			NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
			// 调用自定义的 NamespaceHandler 的初始化方法
			/**
			 * public class UserNamespaceHandler extends NamespaceHandlerSupport {
			 *     @Override
			 *     public void init() {
			 *         registerBeanDefinitionParser("contact", new ContactBeanDefinitionParser());
			 *     }
			 * }
			 */
			namespaceHandler.init();
			// 记录在缓存
			handlerMappings.put(namespaceUri, namespaceHandler);
			return namespaceHandler;
		}
		catch (ClassNotFoundException ex) {
			throw new FatalBeanException("Could not find NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", ex);
		}
		catch (LinkageError err) {
			throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +	className + "] for namespace [" + namespaceUri + "]", err);
		}
	}
}
DefaultNamespaceHandlerResolver # getHandlerMappings

private Map<String, Object> getHandlerMappings() {
	Map<String, Object> handlerMappings = this.handlerMappings;
	// 如果没有被缓存则开始进行缓存
	if (handlerMappings == null) {
		synchronized (this) {
			handlerMappings = this.handlerMappings;
			if (handlerMappings == null) {
				if (logger.isTraceEnabled()) {
					logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]");
				}
				try {
					// this.handlerMappingsLocation 在构造函数中已经被初始化为:META-INF/spring.handlers
					// DEFAULT_HANDLER_MAPPINGS_LOCATION
					/**
					 * public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) {
					 * 		this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION);
					 * }
					 */
					Properties mappings =
							PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
					if (logger.isTraceEnabled()) {
						logger.trace("Loaded NamespaceHandler mappings: " + mappings);
					}
					handlerMappings = new ConcurrentHashMap<>(mappings.size());
					// 将 Properties 格式文件合并到 Map 格式的 handlerMappings 中
					CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
					this.handlerMappings = handlerMappings;
				}
				catch (IOException ex) {
					throw new IllegalStateException("Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
				}
			}
		}
	}
	return handlerMappings;
}
NamespaceHandlerSupport # parse

public BeanDefinition parse(Element element, ParserContext parserContext) {
	// 寻找解析器并进行解析操作
	// 结合示例,首先获取在 UserNamespaceHandler 类中的 init 方法中注册的对应的 UserBeanDefinitionParser 实例,并调用其 parse 进行进一步解析
	BeanDefinitionParser parser = findParserForElement(element, parserContext);
	return (parser != null ? parser.parse(element, parserContext) : null);
}

我们自定义的 UserBeanDefinitionParser 继承 AbstractSingleBeanDefinitionParser,因此调用到 AbstractBeanDefinitionParser # parse

AbstractBeanDefinitionParser # parse

public final BeanDefinition parse(Element element, ParserContext parserContext) {
	// 真正做解析的事情委托给 parseInternal,正是这句代码调用了我们自定义的解析函数
	AbstractBeanDefinition definition = parseInternal(element, parserContext);
	if (definition != null && !parserContext.isNested()) {
		try {
			String id = resolveId(element, definition, parserContext);
			if (!StringUtils.hasText(id)) {
				parserContext.getReaderContext().error("Id is required for element '" + parserContext.getDelegate().getLocalName(element) + "' when used as a top-level tag", element);
			}
			String[] aliases = null;
			if (shouldParseNameAsAliases()) {
				String name = element.getAttribute(NAME_ATTRIBUTE);
				if (StringUtils.hasLength(name)) {
					aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
				}
			}
			// 将 AbstractBeanDefinition 转化为 BeanDefinitionHolder 并注册
			BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
			registerBeanDefinition(holder, parserContext.getRegistry());
			if (shouldFireEvents()) {
				// 需要通知监听器进行处理
				BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
				postProcessComponentDefinition(componentDefinition);
				parserContext.registerComponent(componentDefinition);
			}
		}
		catch (BeanDefinitionStoreException ex) {
			String msg = ex.getMessage();
			parserContext.getReaderContext().error((msg != null ? msg : ex.toString()), element);
			return null;
		}
	}
	return definition;
}
AbstractSingleBeanDefinitionParser # parseInternal

// 并不是直接调用自定义的 doParse 函数,而是进行了一系列的数据准备,包括对 beanClass、scope、lazyInit 等属性的准备
protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
	BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
	String parentName = getParentName(element);
	if (parentName != null) {
		builder.getRawBeanDefinition().setParentName(parentName);
	}
	// 获取自定义标签中的 class,此时会调用自定义解析器如 ContactBeanDefinitionParser 中的 getBeanClass 方法
	Class<?> beanClass = getBeanClass(element);
	if (beanClass != null) {
		builder.getRawBeanDefinition().setBeanClass(beanClass);
	}
	else {
		// 若子类没有重写 getBeanClass 方法,则尝试检查子类是否重写 getBeanClassName 方法
		String beanClassName = getBeanClassName(element);
		if (beanClassName != null) {
			builder.getRawBeanDefinition().setBeanClassName(beanClassName);
		}
	}
	builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
	BeanDefinition containingBd = parserContext.getContainingBeanDefinition();
	if (containingBd != null) {
		// Inner bean definition must receive same scope as containing bean.
		// 若存在父类,则使用父类的 scope 属性
		builder.setScope(containingBd.getScope());
	}
	if (parserContext.isDefaultLazyInit()) {
		// Default-lazy-init applies to custom bean definitions as well.
		// 配置延迟加载
		builder.setLazyInit(true);
	}
	// 调用子类重写的 doParse 方法进行解析
	doParse(element, parserContext, builder);
	return builder.getBeanDefinition();
}
AbstractSingleBeanDefinitionParser # doParse

protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
	doParse(element, builder);
}

protected void doParse(Element element, BeanDefinitionBuilder builder) {
}
public class ContactBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    /**
     * Element 对应的类
     */
    @Override
    protected Class<?> getBeanClass(Element element) {
        return Contact.class;
    }

    /**
     * 从 element 中解析并提取对应的元素
     */
    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        String userName = element.getAttribute("userName");
        String email = element.getAttribute("email");
        // 将提取的数据放入到 BeanDefinitionBuilder 中,待到完成所有 bean 的解析后统一注册到 beanFactory 中
        if (StringUtils.hasText(userName)) {
            builder.addPropertyValue("userName", userName);
        }
        if (StringUtils.hasText(email)) {
            builder.addPropertyValue("email", email);
        }
    }
}

3.5 context:component-scan自定义标签解析源码

以 <context:component-scan /> 为例

  1. 解析当前自定义标签的 namespaceUri
String namespaceUri = getNamespaceURI(ele);
  1. 加载所有 jar 中的 META-INF/spring.handlers
Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
  1. 根据 namespaceUri 从映射关系中找到对应的实现了 NamespaceHandler 接口的类
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
  1. 调用类的 init 方法
namespaceHandler.init();
  1. 调用 parser 方法完成标签解析
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));

return (parser != null ? parser.parse(element, parserContext) : null);

继续调用 ComponentScanBeanDefinitionParser # parse

/**
 * 完成对 <context:component-scan base-package="com.mustang.service"/> 的解析
 * component-scan 中还有其他属性如:scoped-proxy、use-default-filters
 * 见下面 ###1 的分析
 */
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
// 扫描指定包中的 bean,见下面 ###2 的分析
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
// 注册 ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor,见 ###3
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

###1
ComponentScanBeanDefinitionParser # configureScanner
ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);

ComponentScanBeanDefinitionParser # createScanner
return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters, readerContext.getEnvironment(), readerContext.getResourceLoader());

###2
ClassPathBeanDefinitionScanner # doScan
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);

ClassPathScanningCandidateComponentProvider # findCandidateComponents
return scanCandidateComponents(basePackage);

ClassPathScanningCandidateComponentProvider # scanCandidateComponents
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);

ClassPathBeanDefinitionScanner # doScan
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
registerBeanDefinition(definitionHolder, this.registry);

ClassPathBeanDefinitionScanner # registerBeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);

BeanDefinitionReaderUtils # registerBeanDefinition
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
registry.registerAlias(beanName, alias);

DefaultListableBeanFactory # registerBeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);

SimpleAliasRegistry # registerAlias
this.aliasMap.put(alias, name);

###3
ComponentScanBeanDefinitionParser # registerComponents

Set<BeanDefinitionHolder> processorDefinitions = AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);

AnnotationConfigUtils # registerAnnotationConfigProcessors
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值