Spring如何将xml配置映射为BeanDefinition
Spring的常用配置文件是applicationContext.xml文件,最简单的,一般我们都会添加这样的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.harvey.demo.*"></context:component-scan>
</beans>
Spring是根据BeanDefinition来创建Bean对象,BeanDefinition就是Spring中表示Bean定义。BeanDefinition用来存储Bean的相关信息,主要包括:Bean的属性、是否单例、延迟加载、Bean的名称、构造方法等。
那Spring是如何找到所有的目标类创建对象的BeanDefinition的呢?
///////////////////////////////////////////////////////////////////////////
// 入口:AbstractApplicationContext >>>> refresh方法
///////////////////////////////////////////////////////////////////////////
/**
* 【步骤1:刷新前准备工作】
**/
prepareRefresh();
/**
* 【步骤2:获取刷新的BeanFactory】
* 获取(或创建) BeanFactory(DefaultListableBeanFactory),它也是作为 ApplicationContext 的一个成员变量
* BeanFactory 的作用是负责 bean 的创建、依赖注入和初始化,bean 的各项特征由 BeanDefinition 定义
* BeanDefinition 的来源有多种多样,可以是通过 xml 获得、配置类获得、组件扫描获得,也可以是编程添加
* 该方法获取所有的 BeanDefinition 会存入 BeanFactory 中的 beanDefinitionMap 集合(包括Spring内置的,以及我们自定义的)
*
* 另外,此处会加载Spring内置的一些BeanDefinition
* - ConfigurationClassPostProcessor 很重要的一个类,后续用于解析注解配置类
* - AutowiredAnnotationBeanPostProcessor
* - RequiredAnnotationBeanPostProcessor
* - CommonAnnotationBeanPostProcessor
* - EventListenerMethodProcessor
* - DefaultEventListenerFactory
* - 等等
**/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
/**
* 【步骤3:进一步完善 BeanFactory,为它的各项成员变量赋值】
**/
prepareBeanFactory(beanFactory);
/**
* 【步骤4:空实现,留给子类扩展】
**/
postProcessBeanFactory(beanFactory);
/**
* 【步骤5:调用 beanFactory 后处理器】
**/
invokeBeanFactoryPostProcessors(beanFactory);
/**
* 【步骤6:实例化bean后处理器】
*
**/
registerBeanPostProcessors(beanFactory);
/**
* 【步骤7:为 ApplicationContext 添加 messageSource 成员,实现国际化功能】
**/
initMessageSource();
/**
* 【步骤8:为ApplicationContext 添加事件广播器成员,即 applicationContextEventMulticaster】
**/
initApplicationEventMulticaster();
/**
* 【步骤9:空实现,留给子类扩展】
**/
onRefresh();
/**
* 【步骤10:从多种途径找到事件监听器,并添加至 applicationEventMulticaster】
*
**/
registerListeners();
/**
* 【步骤11:将beanFactory的成员补充完毕,并初始化所有非延迟单例 bean】
**/
finishBeanFactoryInitialization(beanFactory);
/**
* 【步骤12:为 ApplicationContext 添加 lifecycleProcessor 成员,用来控制容器内需要生命周期管理的 bean】
**/
finishRefresh();
在obtainFreshBeanFactory方法中一共是两个方法
- refreshBeanFactory:初始化BeanFactory
- getBeanFactory:返回实例化的BeanFactory
///////////////////////////////////////////////////////////////////////////
// AbstractApplicationContext >>>> obtainFreshBeanFactory方法
///////////////////////////////////////////////////////////////////////////
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
走到refreshBeanFactory()方法内部,核心方法loadBeanDefinitions(),这个方法是读取xml文件读取bean的定义。最后赋值到该类的BeanFactory中。
///////////////////////////////////////////////////////////////////////////
// AbstractRefreshableApplicationContext >>>> refreshBeanFactory
///////////////////////////////////////////////////////////////////////////
//如果已经存在BeanFactory,则先销毁先前的BeanFactory,关闭连接以释放资源
if (hasBeanFactory()) {
//销毁先前的BeanFactory
destroyBeans();
//关闭连接
closeBeanFactory();
}
try {
//创建一个新的BeanFactory,在这里使用DefaultListableBeanFactory作为BeanFactory的默认实现类
DefaultListableBeanFactory beanFactory = createBeanFactory();
//设置从ID,用于 BeanFactory 的序列化和反序列化
beanFactory.setSerializationId(getId());
//调用子类的customizeBeanFactory方法,用于在创建新的BeanFactony后,对BeanFactory进行附加的自定义设置
customizeBeanFactory(beanFactory);
/**
* 【重点】加载Bean定义,这个bean definition 是通过XmlBeanDefinitionReader来读取Spring的配置文件(通常为XL格式的〉,得到Bean定义实现类AbstractXmlApplicationContext
*/
loadBeanDefinitions(beanFactory);
//将当前BeanFactory实例赋值给该类实例的beanFactory变量中
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
//如果在解析Bean定义源时遇到I/0错误,则抛出ApplicationContextException异常
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
点击查看这个类下的实现方法。
///////////////////////////////////////////////////////////////////////////
// AbstractXmlApplicationContext >>>> loadBeanDefinitions
///////////////////////////////////////////////////////////////////////////
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 为beanFactory创建XmlBeanDefinitionReader对象
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//用当前 ApplicationContext的环境来配置 BeanDefinition读取器
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//初始化 BeanDefinition 读取器,让子类可以对其进行自定义初始化(留一个可扩展的接口)
initBeanDefinitionReader(beanDefinitionReader);
/**关键方法:读取 BeanDefinition并向 BeanFactory注册*/
loadBeanDefinitions(beanDefinitionReader);
}
然后走到loadBeanDefinitions(),还是调用loadBeanDefinitions()方法。
///////////////////////////////////////////////////////////////////////////
// AbstractXmlApplicationContext >>>> loadBeanDefinitions
///////////////////////////////////////////////////////////////////////////
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
//将每一个Resource的 BeanDefinition 读取并注册到BeanDefinitionRegistry 中
reader.loadBeanDefinitions(configResources);
}
//获取要加载的配置文件路径,即ClassPath下的XML配置
String[] configLocations = getConfigLocations();
if (configLocations != null) {
/**
* 关键方法:根据路径加载配置文件中的 BeanDefinition并注册到 BeanFactory 中
*/
reader.loadBeanDefinitions(configLocations);
}
}
///////////////////////////////////////////////////////////////////////////
// AbstractBeanDefinitionReader >>>> loadBeanDefinitions
///////////////////////////////////////////////////////////////////////////
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
for (Resource resource : resources) {
/**入口,实现类XmlBeanDefinitionReader.loadBeanDefinitions*/
counter += loadBeanDefinitions(resource);
}
return counter;
}
///////////////////////////////////////////////////////////////////////////
// XmlBeanDefinitionReader >>>> loadBeanDefinitions
///////////////////////////////////////////////////////////////////////////
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
//把XML读取的文件流,解析成InputSource对象
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
/**入口,spring框架里面真正干活的方法名 doXXX*/
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
到了这个方法,才开始执行真正的逻辑,通过读取资源载入Bean定义信息。
///////////////////////////////////////////////////////////////////////////
// XmlBeanDefinitionReader >>>> doLoadBeanDefinitions
///////////////////////////////////////////////////////////////////////////
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//读取XML配置,把配置文件转成Document对象
Document doc = doLoadDocument(inputSource, resource);
/**根据解析得到的Document对象,将其中的 Bean配置信息注册到BeanFactory 中*/
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
}
///////////////////////////////////////////////////////////////////////////
// XmlBeanDefinitionReader >>>> registerBeanDefinitions
///////////////////////////////////////////////////////////////////////////
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//创建 BeanDefinitionDocumentReader对象,用于读取文档转化成的 Element
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//记录当前注册的 Bean数量
int countBefore = getRegistry().getBeanDefinitionCount();
/**
* 通过BeanDefinitionDocumentReader的实现来对所提供的Document的BeanDefinition进行解析
* 关键方法:registerBeanDefinitions
*/
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//计算当前实际注册的Bean数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
///////////////////////////////////////////////////////////////////////////
// DefaultBeanDefinitionDocumentReader >>>> registerBeanDefinitions
///////////////////////////////////////////////////////////////////////////
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
///////////////////////////////////////////////////////////////////////////
// DefaultBeanDefinitionDocumentReader >>>> doRegisterBeanDefinitions
///////////////////////////////////////////////////////////////////////////
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
//预处理XNL元素,例如在XML解析之前可以修改XML DOM树,空实现,给子类定义
preProcessXml(root);
/**关键入口:解析Bean定义并注册 Bean 到 BeanFactory 容器中*/
parseBeanDefinitions(root, this.delegate);
//后处理XML元素,例如解析后的 Bean定义可能需要改变XNL DOM树等,空实现,给子类定义
postProcessXml(root);
// 恢复到原先的的 BeanDefinitionParserDelegate 委托对象
this.delegate = parent;
}
///////////////////////////////////////////////////////////////////////////
// DefaultBeanDefinitionDocumentReader >>>> parseBeanDefinitions
///////////////////////////////////////////////////////////////////////////
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
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) {
//如果子节点也是元素节点,并且也使用了默认命名空间,则通过默认方式解析元素
//默认的命名空间是:http://www.springframework.org/schema/beans
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
//解析bean元素信息
parseDefaultElement(ele, delegate);
}
else {
//如果没有指定默认命名空间,也通过自定义方式解析元素
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
解析xml节点分为两种情况:
- 解析默认命名空间下的元素,即http://www.springframework.org/schema/beans
- 解析非默认命名空间下的元素
首先我们来看看如何解析默认命名空间下的元素
///////////////////////////////////////////////////////////////////////////
// DefaultBeanDefinitionDocumentReader >>>> parseDefaultElement
///////////////////////////////////////////////////////////////////////////
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>元素
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
//关键方法:bean元素处理
processBeanDefinition(ele, delegate);
}
//解析<beans>元素
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
//递归调用doRegisterBeanDefinitions()方法解析并注册嵌套的<beans>元素
doRegisterBeanDefinitions(ele);
}
}
回到前面代码,我们再看看是如何解析非默认命名空间下的元素的
///////////////////////////////////////////////////////////////////////////
// BeanDefinitionParserDelegate >>>> parseCustomElement
///////////////////////////////////////////////////////////////////////////
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
//第一步:获取元素的namespaceUri
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
//第二步:通过namespaceUri获取对应的NamespaceHandler,
//例如<context>的命名空间处理器就是ContextNamespaceHandler
//在这里会实例化NamespaceHandler,并调用其init方法,创建诸多解析器,其中就有component-scan对应的解析器ComponentScanBeanDefinitionParser
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
//第三步:调用NamespaceHandler的parse方法准备开始解析
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
///////////////////////////////////////////////////////////////////////////
// NamespaceHandlerSupport >>>> parse
///////////////////////////////////////////////////////////////////////////
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
//根据元素拿到对应的解析器,比如component-scan对应的解析器ComponentScanBeanDefinitionParser
BeanDefinitionParser parser = findParserForElement(element, parserContext);
//调用对应解析器的parse方法解析
return (parser != null ? parser.parse(element, parserContext) : null);
}
///////////////////////////////////////////////////////////////////////////
// ComponentScanBeanDefinitionParser >>>> parse
///////////////////////////////////////////////////////////////////////////
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
//获取元素的base-package属性值
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
//处理占位符
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// 根据一些自定义配置信息创建扫描器,扫描器默认会扫描@Component注解
// 这里要注意:@Service、@Repository、@Configuration的父注解都是@Component
// 只有添加了这些注解的组件才会创建BeanDefinitionHolder
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
//找到声明包路径下的组件,并将类信息封装,实例化为BeanDefinitionHolder,并注册到beanDefinitionMap中
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
//加载其他BeanDefinitio,比如一些依赖bean、内部bean
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
protected void registerComponents(
XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {
Object source = readerContext.extractSource(element);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);
for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
}
// 加载一些注解配置类的后置器,其中就有我们比较重要的配置类解析器ConfigurationClassPostProcessor
boolean annotationConfig = true;
if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
}
if (annotationConfig) {
Set<BeanDefinitionHolder> processorDefinitions =
AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
}
}
readerContext.fireComponentRegistered(compositeDef);
}
///////////////////////////////////////////////////////////////////////////
// AnnotationConfigUtils.registerAnnotationConfigProcessors
///////////////////////////////////////////////////////////////////////////
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(4);
//注册ConfigurationClassPostProcessor的BeanDefinition,ConfigurationClassPostProcessor主要用于注解配置类的解析
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//注册AutowiredAnnotationBeanPostProcessor的BeanDefinition
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//注册RequiredAnnotationBeanPostProcessor的BeanDefinition
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 注册CommonAnnotationBeanPostProcessor的BeanDefinition
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//注册EventListenerMethodProcessor的BeanDefinition
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
//注册DefaultEventListenerFactory的BeanDefinition
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
从解析xml,到封装成BeanDefinition,最后放入map中的核心流程。