目录
系列文章目录
前言
IOC是什么?控制反转, 也称为依赖项注入(DI)。在此过程中,对象仅通过构造函数参数,工厂方法的参数或在构造或从工厂方法返回后在对象实例上设置的属性来定义其依赖项(即,与它们一起使用的其他对象) 。然后,容器在创建 bean 时注入那些依赖项。
通俗一点,对于控制反转的意思,可以通过比较法去理解。想想如果不用spring去开发项目,那么每当我们需要创建一个对象时,需要我们自己去创建,最简单的就是去new 一个新对象。而利用Spring创建对象,将所有对象的创建交给spring管理,只需提供相应的类信息(即配置文件)。需要对象时,只需要从spring容器中获取即可,控制权交给spring了。
而在spring创对象过程中,解决了依赖注入问题(即每个对象所拥有的属性如何设置进去)
一、IOC启动全局概览
这里以读取xml配置文件方式启动ioc容器(其他的还有以注解方式启动,自行了解)。重点关注ClassPathXmlApplicationContext
@Test public void testClassPathXml(){ ApplicationContext context = new ClassPathXmlApplicationContext("classpath:MyTestApplication.xml"); HelloService helloService = context.getBean("helloService",HelloService.class); helloService.sayHello(); System.out.println(helloService.getName()); }
看一下 new ClassPathXmlApplicationContext("classpath:MyTestApplication.xml")这个构造函数
public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this(new String[] {configLocation}, true, null); }
public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super(parent); // 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割) setConfigLocations(configLocations); if (refresh) { //启动容器,重点 refresh(); } }
再来看看ClassPathXmlApplicationContext的继承结构图
第一次看到这张图的时候,我晕了。不过慢慢来,接下关注 refresh()方法,这是在父类AbstractApplicationContext中的一个方法。在这个方法中,可以清晰的看见ioc启动的整个流程
/** * 模板方法,启动ioc容器主要核心方法 * @throws BeansException * @throws IllegalStateException */ @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. //记录启动时间,设置标志位 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. //这个方法负责了BeanFactory的初始化、Bean的加载和注册等事件 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. //Spring的一个扩展点 /** * 如果有Bean实现了BeanFactoryPostProcessor接口, * 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。 * 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事 */ postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //调用BeanFactoryPostProcessor各个实现类的postProcessBeanFactory(factory) 方法 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. //注册 BeanPostProcessor 的实现类,注意不是BeanFactoryPostProcessor //此接口有两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization // 分别会在Bean初始化之前和初始化之后得到执行 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. //初始化当前 ApplicationContext 的 MessageSource,有想了解国际化的相关知识可以深入研究一下 initMessageSource(); // Initialize event multicaster for this context. //这个方法主要为初始化当前 ApplicationContext 的事件广播器 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. //扩展点 onRefresh(); // Check for listener beans and register them. //注册事件监听器 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //负责初始化所有的没有设置懒加载的singleton bean finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. //初始化容器的生命周期事件处理器,并发布容器的生命周期事件 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. //销毁已创建的 Bean destroyBeans(); // Reset 'active' flag. //取消 refresh 操作,重置容器的同步标识. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... //重设公共缓存 resetCommonCaches(); } } }
obtainFreshBeanFactory()这个方法将创建一个BeanFactory,即bean工厂。BeanFactory的API 为 Spring 的 IoC 功能提供了基础,可以通过这个接口获取ioc容器的所有对象
public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&"; Object getBean(String name) throws BeansException; <T> T getBean(String name, Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType, Object... args) throws BeansException; <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType); <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType); boolean containsBean(String name); boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException; @Nullable Class<?> getType(String name) throws NoSuchBeanDefinitionException; String[] getAliases(String name); }
obtainFreshBeanFactory()这个方法负责了BeanFactory的初始化、Bean的加载和注册等事件,就是从各种渠道收集需要创建的对象的相关信息。
二、加载Bean信息到BeanFactory
1.创建BeanFactory并关联父容器
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { //创建beanFactory refreshBeanFactory(); return getBeanFactory(); }
AbstractRefreshableApplicationContext:
protected final void refreshBeanFactory() throws BeansException { // 判断当前ApplicationContext是否存在BeanFactory,如果存在的话就销毁所有 Bean,关闭 BeanFactory // 注意,一个应用可以存在多个BeanFactory,这里判断的是当前ApplicationContext是否存在BeanFactory if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { // 初始化DefaultListableBeanFactory,如果有父容器,则将父容器设置进去。 //springMvc 和 spring 容器关联 DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); // 设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用 customizeBeanFactory(beanFactory); // 加载 Bean 到 BeanFactory 中 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
protected DefaultListableBeanFactory createBeanFactory() { //创建BeanFactory,把父容器设置进去 return new DefaultListableBeanFactory(getInternalParentBeanFactory()); }
在创建BeanFactory步骤中,有一步获取父容器,如果单纯的研究spring框架,这一步获取的父容器是null,但是如果是研究springMvc框架时,这一步的父容器就有具体值,SpringMvc放后面研究。
2.解析Xml配置文件
关注 AbstractXmlApplicationContext.loadBeanDefinitions(beanFactory)这个方法
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. //创建XmlBeanDefinitionReader,即创建Bean读取器,并通过回调设置到容器中去,容器使用该读取器读取Bean定义资源 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment. beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); //为Bean读取器设置Dom xml解析器 beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. // 初始化 BeanDefinitionReader initBeanDefinitionReader(beanDefinitionReader); //开始解析 loadBeanDefinitions(beanDefinitionReader); }
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { //获取指定的配置文件,传入的classpath:application.xml Resource[] configResources = getConfigResources(); if (configResources != null) { //加载xml reader.loadBeanDefinitions(configResources); } //获取默认的配置文件 String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } }
AbstractBeanDefinitionReader.loadBeanDefinitions()
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException { Assert.notNull(locations, "Location array must not be null"); int count = 0; for (String location : locations) { count += loadBeanDefinitions(location); } return count; }
XmlBeanDefinitionReader.loadBeanDefinitions()
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); } //1、使用ThreadLocal防止资源文件循环加载 Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet<>(4); this.resourcesCurrentlyBeingLoaded.set(currentResources); } //利用set的add去除重复 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()); } //加载xml 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中的变量 this.resourcesCurrentlyBeingLoaded.remove(); } } }
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try {//将xml转成document,利用JAXP(DOM)完成从xml解析问Document对象 Document doc = doLoadDocument(inputSource, resource); //根据document注册bean 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); } }
3.解析Document对象
XmlBeanDefinitionReader.registerBeanDefinitions()
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { //构建读取Document的工具类 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); //获取已注册的bean数量 int countBefore = getRegistry().getBeanDefinitionCount(); //解析document对象 documentReader.registerBeanDefinitions(doc,createReaderContext(resource)); //返回本次注册的bean数量 return getRegistry().getBeanDefinitionCount() - countBefore; }
DefaultBeanDefinitionDocumentReader.registerBeanDefinitions()
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; //传入根节点 doRegisterBeanDefinitions(doc.getDocumentElement()); }
protected void doRegisterBeanDefinitions(Element root) { // Any nested <beans> elements will cause recursion in this method. In // order to propagate and preserve <beans> default-* attributes correctly, // keep track of the current (parent) delegate, which may be null. Create // the new (child) delegate with a reference to the parent for fallback purposes, // then ultimately reset this.delegate back to its original (parent) reference. // this behavior emulates a stack of delegates without actually necessitating one. BeanDefinitionParserDelegate parent = this.delegate; this.delegate = createDelegate(getReaderContext(), root, parent); if (this.delegate.isDefaultNamespace(root)) {// 判断元素节点是不是 beans 命名空间下的节点 // 获取 <beans ... profile="***" /> 中的 profile参数与当前环境是否匹配,如果不匹配则不再进行解析 String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); // We cannot use Profiles.of(...) since profile expressions are not supported // in XML config. See SPR-12458 for details. //如果指定了 profiles 且 不符合 environment定义的 激活的 profiles ,那么直接忽略 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; } } } /** * 改变bean定义的扩展点 * preProcessXml和postProcessXml着两个办法是留给我们实现DefaultBeanDefinitionDocumentReader方法后自定义实现的 */ preProcessXml(root); //利用BeanDefinitionParserDelegate真正的解析节点 parseBeanDefinitions(root, this.delegate); postProcessXml(root); this.delegate = parent; }
3.1解析默认命名空间下的节点
什么是默认命名空间?在配置文件中,有一行配置 xmlns="http://www.springframework.org/schema/beans" 这个就是ioc的默认命名空间。这个命名空间下有4中不同类型的标签,<import />、<alias />、<bean /> 和 <beans />
DefaultBeanDefinitionDocumentReader.parseBeanDefinitions()
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { //default namespace 默认命名空间涉及到的就四个标签 <import />、<alias />、<bean /> 和 <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; if (delegate.isDefaultNamespace(ele)) { // 解析4种默认的 namespace 的元素 parseDefaultElement(ele, delegate); } else { // 解析其他 namespace 的元素,自定义节点,如 <tx:annotation-driven/> delegate.parseCustomElement(ele); } } } } else {// 解析其他 namespace 的元素 delegate.parseCustomElement(root); } }
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {//导入解析 //<import/>导入其他配置文件 importBeanDefinitionResource(ele); } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {//别名解析 processAliasRegistration(ele); } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {//bean解析 processBeanDefinition(ele, delegate); } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {//beans解析 // recurse,嵌套的beans标签解析,又回到了顶层解析方法 doRegisterBeanDefinitions(ele); } }
可以看到,对于<beans>标签的解析,其实是一个嵌套调用,最终归结于对<bean>节点的解析,接下来重点关注
DefaultBeanDefinitionDocumentReader.processBeanDefinition(ele, delegate)
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { //创建BeanDefinition BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { // 装饰bdHolder bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance,注册Bean 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)); } }
创建一个BeanDefinition,bean定义,这个接口的子类AbstractBeanDefinition包含了一个类的所有信息,如作用域,class,以及各种标志位等等(从配置文件中获取)。
BeanDefinitionParserDelegate.parseBeanDefinitionElement()
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) { return parseBeanDefinitionElement(ele, null); }
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) { String id = ele.getAttribute(ID_ATTRIBUTE); String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); List<String> aliases = new ArrayList<>(); //将 name 属性的定义按照 “逗号、分号、空格” 切分,形成一个 别名列表数组 if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id; // 如果没有指定id, 那么用别名列表的第一个名字作为beanName if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { 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) { //校验beanName的唯一性,在同一个Beans标签下面不能重复 checkNameUniqueness(beanName, aliases, ele); } // 根据 <bean ...>...</bean> 中的配置创建 BeanDefinition,然后把配置中的信息都设置到实例中, // 这行执行完毕,一个 BeanDefinition 实例就出来了 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) {//<bean/>标签设置完成 if (!StringUtils.hasText(beanName)) { //如果没有指定beanName使用,使用spring规则生成beanName try { if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { beanName = this.readerContext.generateBeanName(beanDefinition); // Register an alias for the plain bean class name, if still possible, // if the generator returned the class name plus a suffix. // This is expected for Spring 1.2/2.0 backwards compatibility. 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; }
public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, @Nullable BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } String parent = null; if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } try { //创建AbstractBeanDefinition,设置类信息 AbstractBeanDefinition bd = createBeanDefinition(className, parent); //设置其他属性 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); 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); bd.setResource(this.readerContext.getResource()); bd.setSource(extractSource(ele)); return bd; } catch (ClassNotFoundException ex) { error("Bean class [" + className + "] not found", ele, ex); } catch (NoClassDefFoundError err) { error("Class that bean class [" + className + "] depends on not found", ele, err); } catch (Throwable ex) { error("Unexpected failure during bean definition parsing", ele, ex); } finally { this.parseState.pop(); } return null; }
创建好beanDefinition后,需要注册到BeanFactory中,其实就是用一个map保存一下 beanName对应的beanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition()
public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. String beanName = definitionHolder.getBeanName(); //注册bean registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { //注册别名 registry.registerAlias(beanName, alias); } } }
DefaultListableBeanFactory.registerBeanDefinition()
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); } } // 所有的 Bean 注册后都会被放入到这个beanDefinitionMap 中,查看是否已存在这个bean BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); if (existingDefinition != null) {//已经定义了bean if (!isAllowBeanDefinitionOverriding()) { // 如果不允许覆盖的话,抛异常 throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } else if (existingDefinition.getRole() < beanDefinition.getRole()) {// 用框架定义的 Bean 覆盖用户自定义的 Bean // 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)) { // 用新的 Bean 覆盖旧的 Bean(新旧不同) if (logger.isDebugEnabled()) { logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else { //log...用同等的 Bean 覆盖旧的 Bean(新旧相同) if (logger.isTraceEnabled()) { logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } //put进map this.beanDefinitionMap.put(beanName, beanDefinition); } else { // 判断是否已经有其他的 Bean 开始初始化了.注意,"注册Bean" 这个动作结束,Bean 依然还没有初始化,在 Spring 容器启动的最后, // 会初始化所有的 singleton beans if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; removeManualSingletonName(beanName); } } else { // Still in startup registration phase // 将 BeanDefinition 放到这个 map 中,这个 map 保存了所有的 BeanDefinition this.beanDefinitionMap.put(beanName, beanDefinition); // 这是个 ArrayList,所以会按照 bean 配置的顺序保存每一个注册的 Bean 的名字 this.beanDefinitionNames.add(beanName); // 这是个 LinkedHashSet,代表的是手动注册的 singleton bean, removeManualSingletonName(beanName); } this.frozenBeanDefinitionNames = null; } if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }
至此,spring从xml中的配置信息读取出来,解析成BeanDefination对象,并注册到BeanFactory中流程已经结束。后续实例化只需要从BeanFactory中获取这些bean定义即可。
3.2解析自定义命名空间下的节点
什么是自定义命名空间?除了xmlns="http://www.springframework.org/schema/beans 这个命名空间之外的都是自定义。
标签有: <context:component-scan base-package="org.springframework.context.mytest"/> 以及其他标签。
接下来看看如何解析自定义的节点
BeanDefinitionParserDelegate
public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); }
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { //获取命名空间,如:xmlns:tx="http://www.springframework.org/schema/tx" 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; } //parse 自定义标签 return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }
DefaultNamespaceHandlerResolver
public NamespaceHandler resolve(String namespaceUri) { //加载 namespaceUri=namespaceHandler 对应表 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); //init方法,注意这个方法很重要,是用户扩展点中很重要的一点 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); } } }
/** * Load the specified NamespaceHandler mappings lazily. * getHandlerMappings()方法读取了所有的 META-INF/spring.handlers" 文件 */ 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 Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); if (logger.isTraceEnabled()) { logger.trace("Loaded NamespaceHandler mappings: " + mappings); } handlerMappings = new ConcurrentHashMap<>(mappings.size()); 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; }
Spring默认将这些处理器配置放在 META-INF/spring.handlers,这里面有
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
重点关注ContextNamespaceHandler,在下面可以看到熟悉的标签,如property-placeholder,annotation-config,component-scan等等
public class ContextNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { //属性文件 registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); //配置器 registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); //包扫描解析器 registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); } }
获取到NamespaceHandler后,可以开始通过parse方法解析了标签了
NamespaceHandlerSupport
public BeanDefinition parse(Element element, ParserContext parserContext) { BeanDefinitionParser parser = findParserForElement(element, parserContext); return (parser != null ? parser.parse(element, parserContext) : null); }
这里主要分析一下component-scan这个标签。字面意思,包扫描,开启注解扫描。
在配置的路径下,会将带有@Component @Named @ManagedBean等注解注册到BeanFactory
同时会注册一些处理器,用于处理@Resouce @Autowired @Configuration @Value @Required @PostConstruct等等注解
<context:component-scan base-package="org.springframework.context.mytest"/>
分为3个步骤:1.配置扫描器
2.扫描包里面的类
3.注册常用的解析器
ComponentScanBeanDefinitionParser
public BeanDefinition parse(Element element, ParserContext parserContext) { String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); // Actually scan for bean definitions and register them. // 根据xml配置或者默认配置(如果没有指定的话)配置扫描器ClassPathBeanDefinitionScanner ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); //scanner扫描包下面含有特殊注解标注的类 //@Component @Named @ManagedBean (@Controller @Service @Repository @Configuration)都会被注册 Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); //注册常用的解析器 registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }
/** * <context:component-scan base-package="com.wangtao.controller" * use-default-filters="false"> * <context:include-filter * type="annotation" * expression="org.springframework.stereotype.Controller"/> * </context:component-scan> * @param parserContext * @param element * @return */ protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) { boolean useDefaultFilters = true; if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) { useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)); } // Delegate bean definition registration to scanner class. // 生成scanner的时候 在其父类构造函数中调用了`registerDefaultFilters()`方法中加入了3个注解类型的typeFilter 分别是@Component // @ManagedBean @Named 意思也就是看类上面有没有这三个注解或者注解的元注解中是否含有这三个注解之一 // 这里虽然没有加入如@Service的注解 但看@Service的定义会发现@Service注解也被@Component给标注了 ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters); // 利用spring 启动的时候根据xml文件或者默认配置(如果没有指定的话)生成的BeanDefinition规则 scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults()); scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns()); if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) { scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE)); } try { // 扫描注解定义的bean 需要定义一种beanName的生成规则 一般是驼峰命名法 parseBeanNameGenerator(element, scanner); } catch (Exception ex) { parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } try { parseScope(element, scanner); } catch (Exception ex) { parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } // 根据xml配置生成includeFilter excludeFilter,用于过滤特定的bean parseTypeFilters(element, scanner, parserContext); return scanner; }
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) { return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters, readerContext.getEnvironment(), readerContext.getResourceLoader()); }
ClassPathBeanDefinitionScanner
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); this.registry = registry; if (useDefaultFilters) { //注册默认的过滤器,@Component,@Named,@ManagedBean registerDefaultFilters(); } setEnvironment(environment); setResourceLoader(resourceLoader); }
protected void registerDefaultFilters() { this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false)); logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip. } try { this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false)); logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. } }
包扫描器配置完成后,真正开始扫描包里面的类
ClassPathBeanDefinitionScanner
protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); for (String basePackage : basePackages) { //寻找被@Component或者@Named注解标注的类 或者 类的注解的元注解中含有这两个注解 , // 例如常见的@Respsitory @Controller @Service Set<BeanDefinition> candidates = findCandidateComponents(basePackage); // 对于生成的AnnotatedBeanDefinition做一些转化工作 例如前面说到的应用bd(BeanDefinition)默认配置 // 处理@Primary @Lazy @DependsOn @Role注解等 // 转化成BeanDefinitionHolder对象 for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { //添加默认属性 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { //处理lazy,dependOn,Role等属性 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); //注册 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
public Set<BeanDefinition> findCandidateComponents(String basePackage) { if (this.componentsIndex != null && indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); } else { return scanCandidateComponents(basePackage); } }
private Set<BeanDefinition> scanCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<>(); try { String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; //将该路径下的所有类都获取到 Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try { //获取类的元数据信息 MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); // 根据includeFilters excludeFilters做匹配 if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; }
注解类已经注册到BeanFactory当中了,接下去还要注册一些特殊的解析器,用于处理如@Resouce @Autowired @Configuration @Value @Required @PostConstruct等这类型的注解
ComponentScanBeanDefinitionParser
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)); } // Register annotation config processors, if necessary. /** * annotationConfig默认是true * 如果同时配置了annotation-config和component-scan,以annotation-config标签的值为准 * 在只有component-scan标签情况下,会注册常见的注解处理器 */ boolean annotationConfig = true; //判断是否配置了annotation-config if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) { annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE)); } if (annotationConfig) { // 注册组件以及一些我们常见的注解处理器(BPP) 如@Resouce @Autowired @Configuration @Value @Required @PostConstruct Set<BeanDefinitionHolder> processorDefinitions = AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source); for (BeanDefinitionHolder processorDefinition : processorDefinitions) { compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition)); } } readerContext.fireComponentRegistered(compositeDef); }
AnnotationConfigUtils
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<>(8); //不包含就添加相应的Processor if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { /* 对@Configuration、@Bean、@Import、@Component、@ComponentScan、@ImportResource等注解的支持 */ RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); //注册到beanDefinitionMap beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } //解析Autowired,Value 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)); } // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor. //@ Resource 、@ PostConstruct、@ PreDestroy 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. //@PersistenceContext 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)); } 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)); } 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; }
总结
本节内容主要分析的是IOC容器从xml配置文件获取bean信息的过程,重点分析了component-scan这个标签的解析流程。从全局的角度来看,这一节的是将ioc中需要实例化对象的信息收集起来,收集渠道很多,如最原始的xml配置,通过包扫描相应的注解类,然后集中保存到BeanFactory。此时的获取到的都是BeanDefinition,还没有开始实例化。
下一章将分析一下从BeanDefinition到的实例化Bean这之前的过程
结语:沙场秋点兵