java|Spring-IoC注入过程

本文基于spring5.1.6 一、大体流程

  1. 使用ResourceLoader加载资源
  2. 创建Bean工厂
  3. 获得BeanDefinition
  4. 装载资源
    资源定位、装载、注册
    装载。装载就是 BeanDefinition 的载入
//加载资源 ClassPathResource resource = new ClassPathResource("bean.xml"); //创建bean工厂 DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); //xml解析器 XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); //装载资源 reader.loadBeanDefinitions(resource);

不理解资源解析的请参考Spring-Resource源码解析
1.1 new XmlBeanDefinitionReader(factory)其实是调用的父类的构造方法
关系 public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader,EnvironmentCapable
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader
java|Spring-IoC注入过程
文章图片

1.2AbstractBeanDefinitionReader
  1. 创建对象就是初始化资源加载器和环境的过程
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); this.registry = registry; // 确定加载器如果BeanDefinitionRegistry是一个资源加载器,那么就使用它作为加载器,否则使用路径匹配加载器 if (this.registry instanceof ResourceLoader) { this.resourceLoader = (ResourceLoader) this.registry; } else { this.resourceLoader = new PathMatchingResourcePatternResolver(); } //EnvironmentCapable:Spring中所有的应用上下文类都实现了此接口。这个接口的主要作用是用于类型检查的 if (this.registry instanceof EnvironmentCapable) { this.environment = ((EnvironmentCapable) this.registry).getEnvironment(); } else { this.environment = new StandardEnvironment(); } }

环境类Environment
/** * 环境的一些参数 */ public interface Environment extends PropertyResolver { //获取激活的配置 String[] getActiveProfiles(); //默认的配置 String[] getDefaultProfiles(); //废弃的方法通过字符串的配置判断是否可以使用该配置 @Deprecated boolean acceptsProfiles(String... profiles); //通过Profiles对象判断是否可以使用该配置 boolean acceptsProfiles(Profiles profiles); }public interface PropertyResolver { boolean containsProperty(String key); //获取参数 @Nullable String getProperty(String key); //获取参数,如果为空,返回默认值 String getProperty(String key, String defaultValue); //返回指定的对象的字节码对象 @Nullable T getProperty(String key, Class targetType); //返回指定的对象的字节码类,如果为空返回默认值 T getProperty(String key, Class targetType, T defaultValue); //获取要求的参数 String getRequiredProperty(String key) throws IllegalStateException; //获取要求的参数的对象的字节码对象 T getRequiredProperty(String key, Class targetType) throws IllegalStateException; //解析占位符 String resolvePlaceholders(String text); //解析要求的占位符 String resolveRequiredPlaceholders(String text) throws IllegalArgumentException; }

1.3加载过程
loadBeanDefinitions会将资源进行编码,然后执行的是下面的代码
将encodedResource放入Set,去重
将encodedResource转成流并且将Resource对象传入doLoadBeanDefinitions,详见1.4源码
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null"); if (logger.isTraceEnabled()) { logger.trace("Loading XML bean definitions from " + encodedResource); } //resourcesCurrentlyBeingLoaded是一个ThreadLocal对象 Set currentResources = this.resourcesCurrentlyBeingLoaded.get(); //如果是空的,那么就初始化一个set if (currentResources == null) { currentResources = new HashSet<>(4); this.resourcesCurrentlyBeingLoaded.set(currentResources); } //如果set集合添加不进去,那么抛出异常,说明已经加载过了,防止重复加载 if (!currentResources.add(encodedResource)) { throw new BeanDefinitionStoreException( "Detected cyclic loading of " + encodedResource + " - check your import definitions!"); } try { //转换成流 InputStream inputStream = encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { //设置编码 inputSource.setEncoding(encodedResource.getEncoding()); } //见下方源码1.4 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()) { //ThreadLocal必须要remove掉,防止线程池下的线程复用 this.resourcesCurrentlyBeingLoaded.remove(); } } }

1.4doLoadBeanDefinitions方法
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { //获取Document 实例 Document doc = doLoadDocument(inputSource, resource); //注册到ioc容器中详见1.5 int count = registerBeanDefinitions(doc, resource); if (logger.isDebugEnabled()) { logger.debug("Loaded " + count + " bean definitions from " + resource); } return count; } catch (BeanDefinitionStoreException ex) { throw ex; } catch (SAXParseException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex); } catch (SAXException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", ex); } catch (ParserConfigurationException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, ex); } catch (IOException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, ex); } catch (Throwable ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, ex); } }

1.5 registerBeanDefinitions
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { //利用反射创建对象详见1。6 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); //registry是不是有点眼熟XmlBeanDefinitionReader extends AbstractBeanDefinitionReader //在创建XmlBeanDefinitionReader的时候初始化了registry和environment //也就是DefaultListableBeanFactory //获取容器总数量 int countBefore = getRegistry().getBeanDefinitionCount(); //将Resource包装成XmlReaderContext详见1.7 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); //返回成功的个数beanDefinitionMap新增的数量 return getRegistry().getBeanDefinitionCount() - countBefore; }

1.6 instantiateClass
public static T instantiateClass(Class clazz) throws BeanInstantiationException { Assert.notNull(clazz, "Class must not be null"); //如果是接口,抛出异常 if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { //如果不是接口,根据反射实例化对象 return instantiateClass(clazz.getDeclaredConstructor()); } catch (NoSuchMethodException ex) { Constructor ctor = findPrimaryConstructor(clazz); if (ctor != null) { return instantiateClass(ctor); } throw new BeanInstantiationException(clazz, "No default constructor found", ex); } catch (LinkageError err) { throw new BeanInstantiationException(clazz, "Unresolvable class definition", err); } }

1.7registerBeanDefinitions
@Override public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; //详见1.8 doRegisterBeanDefinitions(doc.getDocumentElement()); }

1.8doRegisterBeanDefinitions
@SuppressWarnings("deprecation")// for Environment.acceptsProfiles(String...) protected void doRegisterBeanDefinitions(Element root) { //解析器 BeanDefinitionParserDelegate parent = this.delegate; //this.delegate重新指向新的delegate this.delegate = createDelegate(getReaderContext(), root, parent); //根节点是否为默认的命名空间,node.getNamespaceURI()为空 //或者为BeanDefinitionParserDelegate.BEANS_NAMESPACE_URI //"http://www.springframework.org/schema/beans" 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.isDebugEnabled()) { logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + getReaderContext().getResource()); } return; } } } //什么都没做,需要子类来实现 preProcessXml(root); //解析BeanDefinitions,详见1.9parseBeanDefinitions parseBeanDefinitions(root, this.delegate); //什么都没做,需要子类来实现 postProcessXml(root); this.delegate = parent; }

1.9parseBeanDefinitions
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) { Element ele = (Element) node; if (delegate.isDefaultNamespace(ele)) { //处理默认的元素 parseDefaultElement(ele, delegate); } else { //处理自定义的元素 delegate.parseCustomElement(ele); } } } } else { //处理自定义的元素 delegate.parseCustomElement(root); } }

2.0 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)) { //2.2processBeanDefinition processBeanDefinition(ele, delegate); } //beans标签 else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { //调用1.9的方法继续往下解析即解析bean doRegisterBeanDefinitions(ele); } }

2.1parseCustomElement处理客户自定义的元素
@Nullable public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); if (namespaceUri == null) { return null; } NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }

2.2 processBeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { //解析ele并且将bean封装到BeanDefinitionHolder BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); //如果不为空 if (bdHolder != null) { //获取属性 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // 注册到IOC容器 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }

2.3parseBeanDefinitionElement 从xml中解析bean
@Nullable 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)) { //将name属性值进行分割放入aliases中 String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } //将id作为beanName,也就是说,id优先级最高 String beanName = id; //id不存在的时候 if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { //是否真的有值,把aliases的第一个元素放进来,那么把name作为beanname beanName = aliases.remove(0); if (logger.isTraceEnabled()) { logger.trace("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } if (containingBean == null) { //检查是否唯一如果存在抛出异常,如果不存在那么缓存起来 checkNameUniqueness(beanName, aliases, ele); } //获取beanDefinition AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { //如果别名和id都为空的情况 if (!StringUtils.hasText(beanName)) { try { //如果不为空的情况下获取beanName if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { //根据上下文生成beanName beanName = this.readerContext.generateBeanName(beanDefinition); // 获取真正的java类名 String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } if (logger.isTraceEnabled()) { logger.trace("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName + "]"); } } catch (Exception ex) { error(ex.getMessage(), ele); return null; } } String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }

2.4registerBeanDefinition
public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // 获取bean名称 String beanName = definitionHolder.getBeanName(); //注册到IOC容器中 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); //注册别名 String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } }

【java|Spring-IoC注入过程】2.5 registerBeanDefinition
@Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { //校验 Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } //通过Map查询是否存在BeanDefinition BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); //如果存在 if (existingDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } else if (existingDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (logger.isInfoEnabled()) { logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else if (!beanDefinition.equals(existingDefinition)) { if (logger.isDebugEnabled()) { logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } //如果不存在BeanDefinition else { if (logger.isTraceEnabled()) { logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } //注册进去IOC容器 this.beanDefinitionMap.put(beanName, beanDefinition); } else { if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); List> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; if (this.manualSingletonNames.contains(beanName)) { Set> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames); updatedSingletons.remove(beanName); this.manualSingletonNames = updatedSingletons; } } } else { // Still in startup registration phase this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); this.manualSingletonNames.remove(beanName); } this.frozenBeanDefinitionNames = null; } if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }

小结
1. 将Resource转成EncodedResource设置编码 2. 通过Resource和Resource的流获取Document 3. 通过命名空间(BEANS_NAMESPACE_URI = “http://www.springframework.org/schema/beans”; )判断是否是用户自定义的xml,然后解析不同的xml(我们这里只分析默认的) 4. 根据标签解析xml,spring解析import、alias、bean、beans 5. 解析bean标签、将Element对象封装成BeanDefinitionHolder 6. 将beanName作为key,BeanDefinition作为value保存到beanDefinitionMap中

    推荐阅读