Spring IOC 容器源码阅读笔记

来源:互联网 发布:少儿编程是什么意思 编辑:程序博客网 时间:2024/06/08 11:28

参考的文章

  • Spring IOC容器源代码解析,作者带着看了一遍源码,边看边讲,非常nice。

正文

  • 我对于Spring IOC(控制反转)的理解,是将对象的管理(控制)权从以前的程序员手中“反转”到了Spring IOC容器手中。
  • Spring IOC容器的定义接口(最基本的IOC容器):BeanFactory,这个借口为具体的IOC容器的实现做了最基本的功能规定。
public interface BeanFactory {    String FACTORY_BEAN_PREFIX = "&";    Object getBean(String var1) throws BeansException;    <T> T getBean(String var1, Class<T> var2) throws BeansException;    <T> T getBean(Class<T> var1) throws BeansException;    Object getBean(String var1, Object... var2) throws BeansException;    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;    boolean containsBean(String var1);    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;    boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;    boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;    String[] getAliases(String var1);}
  • 围绕着BeanFactory,pring对于IOC容器有许多种实现(XmlBeanFactory,XmlWebApplicationContext.java,ClassPathXmlApplicationContext.java FileSystemXmlApplicationContext.java)。
  • 我是以ClassPathXmlApplicationContext.java为例去看的源码。

ClassPathXmlApplicationContext构造器代码

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {        super(parent);        this.setConfigLocations(configLocations);        if(refresh) {            this.refresh();        }    }
  • 主要是调用了refresh()方法。bean的初始化逻辑是在这里完成的。

refresh()方法(refresh方法是在AbstractApplicationContext里的)

public void refresh() throws BeansException, IllegalStateException {        Object var1 = this.startupShutdownMonitor;        synchronized(this.startupShutdownMonitor) {            this.prepareRefresh();            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();            this.prepareBeanFactory(beanFactory);            try {                this.postProcessBeanFactory(beanFactory);                this.invokeBeanFactoryPostProcessors(beanFactory);                this.registerBeanPostProcessors(beanFactory);                this.initMessageSource();                this.initApplicationEventMulticaster();                this.onRefresh();                this.registerListeners();                this.finishBeanFactoryInitialization(beanFactory);                this.finishRefresh();            } catch (BeansException var9) {                if(this.logger.isWarnEnabled()) {                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);                }                this.destroyBeans();                this.cancelRefresh(var9);                throw var9;            } finally {                this.resetCommonCaches();            }        }    }
  • 这里重要的是ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();,获取一个新的beanFactory

obtainFreshBeanFactory()

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {        this.refreshBeanFactory();        ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();        if(this.logger.isDebugEnabled()) {            this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);        }        return beanFactory;    }
  • this.refreshBeanFactory();刷新beanFactory,如果已经建立了那么应该销毁重建。该方法是一个abstract方法,通过调试发现调用的是AbstractRefreshableApplicationContext中实现的refreshBeanFactory方法

refreshBeanFactory()

protected final void refreshBeanFactory() throws BeansException {        if(this.hasBeanFactory()) {            this.destroyBeans();            this.closeBeanFactory();        }        try {            DefaultListableBeanFactory beanFactory = this.createBeanFactory();            beanFactory.setSerializationId(this.getId());            this.customizeBeanFactory(beanFactory);            this.loadBeanDefinitions(beanFactory);            Object var2 = this.beanFactoryMonitor;            synchronized(this.beanFactoryMonitor) {                this.beanFactory = beanFactory;            }        } catch (IOException var5) {            throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);        }    }
  • 实现了如果已经建立了beanFactory,那么就销毁并关闭,重新建立。这里的this.loadBeanDefinitions(beanFactory);需要讲一下,它去加载那些bean的定义。
  • 在AbstractXmlApplicationContext中定义了对资源的读取过程,默认由XmlBeanDefinitionReader来读取:

loadBeanDefinitions()

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {        Resource[] configResources = this.getConfigResources();        if(configResources != null) {            reader.loadBeanDefinitions(configResources);        }        String[] configLocations = this.getConfigLocations();        if(configLocations != null) {            reader.loadBeanDefinitions(configLocations);        }    }

doLoadBeanDefinitions()

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {        try {            Document doc = this.doLoadDocument(inputSource, resource);            return this.registerBeanDefinitions(doc, resource);...}

registerBeanDefinitions()

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {        BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();        int countBefore = this.getRegistry().getBeanDefinitionCount();        documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));        return this.getRegistry().getBeanDefinitionCount() - countBefore;    }
  • 主要作用的还是documentReader.registerBeanDefinitions()方法。经过调试,发现调用的是DefaultBeanDefinitionDocumentReader中的registerBeanDefinitions()。
  • 又经过调试发现是documentReader.registerBeanDefinitions()中的doRegisterBeanDefinitions()。实现的。

doRegisterBeanDefinitions

protected void doRegisterBeanDefinitions(Element root) {        BeanDefinitionParserDelegate parent = this.delegate;        this.delegate = this.createDelegate(this.getReaderContext(), root, parent);        if(this.delegate.isDefaultNamespace(root)) {            String profileSpec = root.getAttribute("profile");            if(StringUtils.hasText(profileSpec)) {                String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");                if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {                    if(this.logger.isInfoEnabled()) {                        this.logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource());                    }                    return;                }            }        }        this.preProcessXml(root);        this.parseBeanDefinitions(root, this.delegate);        this.postProcessXml(root);        this.delegate = parent;    }

实际上的解析工作都是交给delegate代理完成的。

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) {                    Element ele = (Element)node;                    if(delegate.isDefaultNamespace(ele)) {                        this.parseDefaultElement(ele, delegate);                    } else {                        delegate.parseCustomElement(ele);                    }                }            }        } else {            delegate.parseCustomElement(root);        }    }
  • 该方法是遍历所有的子节点,然后分为默认的命名空间(import,alias,bean,beans)和自定义的命名空间(dubbo,shiro等等)。

parseDefaultElement()

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {        if(delegate.nodeNameEquals(ele, "import")) {            this.importBeanDefinitionResource(ele);        } else if(delegate.nodeNameEquals(ele, "alias")) {            this.processAliasRegistration(ele);        } else if(delegate.nodeNameEquals(ele, "bean")) {            this.processBeanDefinition(ele, delegate);        } else if(delegate.nodeNameEquals(ele, "beans")) {            this.doRegisterBeanDefinitions(ele);        }    }
  • 根据不同的nodeName做不同处理。

processBeanDefinition

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);        if(bdHolder != null) {            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);            try {                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());            } catch (BeanDefinitionStoreException var5) {                this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);            }            this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));        }    }
  • 这里执行了delegate.parseBeanDefinitionElement()完成了对bean定义的解析,返回的BeanDefinitionHolder交给BeanDefinitionReaderUtils.registerBeanDefinition(),完成对一个bean的定义。
先说parseBeanDefinitionElement()

parseBeanDefinitionElement()

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {        String id = ele.getAttribute("id");        String nameAttr = ele.getAttribute("name");        List<String> aliases = new ArrayList();        if(StringUtils.hasLength(nameAttr)) {            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");            aliases.addAll(Arrays.asList(nameArr));        }        String beanName = id;        if(!StringUtils.hasText(id) && !aliases.isEmpty()) {            beanName = (String)aliases.remove(0);            if(this.logger.isDebugEnabled()) {                this.logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");            }        }        if(containingBean == null) {            this.checkNameUniqueness(beanName, aliases, ele);        }        AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);        if(beanDefinition != null) {            if(!StringUtils.hasText(beanName)) {                try {                    if(containingBean != null) {                        beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);                    } else {                        beanName = this.readerContext.generateBeanName(beanDefinition);                        String beanClassName = beanDefinition.getBeanClassName();                        if(beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {                            aliases.add(beanClassName);                        }                    }                    if(this.logger.isDebugEnabled()) {                        this.logger.debug("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]");                    }                } catch (Exception var9) {                    this.error(var9.getMessage(), ele);                    return null;                }            }            String[] aliasesArray = StringUtils.toStringArray(aliases);            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);        } else {            return null;        }    }
  • parseBeanDefinitionElement()方法具体完成。

parseBeanDefinitionElement()

public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {        this.parseState.push(new BeanEntry(beanName));        String className = null;        if(ele.hasAttribute("class")) {            className = ele.getAttribute("class").trim();        }        try {            String parent = null;            if(ele.hasAttribute("parent")) {                parent = ele.getAttribute("parent");            }    //创建一个AbstractBeanDefinition并设置好'类名'和'parent'            AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);    //解析了Element的属性并设置到beanDefinition中去            this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));    //设置启动参数            this.parseMetaElements(ele, bd);    //设置被期望重写            this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());    //设置被替换的方法                          this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());            this.parseConstructorArgElements(ele, bd);            this.parsePropertyElements(ele, bd);            this.parseQualifierElements(ele, bd);            bd.setResource(this.readerContext.getResource());            bd.setSource(this.extractSource(ele));    //这里,是为了防止并发问题?????Spring在后面还用到了类似的手法            AbstractBeanDefinition var7 = bd;            return var7;        } catch (ClassNotFoundException var13) {            this.error("Bean class [" + className + "] not found", ele, var13);        } catch (NoClassDefFoundError var14) {            this.error("Class that bean class [" + className + "] depends on not found", ele, var14);        } catch (Throwable var15) {            this.error("Unexpected failure during bean definition parsing", ele, var15);        } finally {            this.parseState.pop();        }        return null;    }
经过parseBeanDefinitionElement完成了beanDefinition的各种设置,再说registerBeanDefinition,把设置完成的beanDefinition注册到IOC容器中

registerBeanDefinition()

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {        String beanName = definitionHolder.getBeanName();        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());        String[] aliases = definitionHolder.getAliases();        if(aliases != null) {            String[] var4 = aliases;            int var5 = aliases.length;            for(int var6 = 0; var6 < var5; ++var6) {                String alias = var4[var6];                registry.registerAlias(beanName, alias);            }        }    }
  • 主要有通过传来的参数注册器.registerBeanDefinition(),再就是注册别名。这里只看registerBeanDefinition()方法。

registerBeanDefinition()这里用的是DefaultListableBeanFactory,PS:XmlBeanFactory是继承的DefaultListableBeanFactory。

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 var9) {                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9);            }        }        BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);        if(oldBeanDefinition != null) {            if(!this.isAllowBeanDefinitionOverriding()) {                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");            }            if(oldBeanDefinition.getRole() < beanDefinition.getRole()) {                if(this.logger.isWarnEnabled()) {                    this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");                }            } else if(!beanDefinition.equals(oldBeanDefinition)) {                if(this.logger.isInfoEnabled()) {                    this.logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");                }            } else if(this.logger.isDebugEnabled()) {                this.logger.debug("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");            }            this.beanDefinitionMap.put(beanName, beanDefinition);        } else {            if(this.hasBeanCreationStarted()) {                Map var4 = this.beanDefinitionMap;                synchronized(this.beanDefinitionMap) {                    this.beanDefinitionMap.put(beanName, beanDefinition);    //这种new一个新对象,处理完后,将需要修改的引用指向new的新对象,可以降低并发的影响,也就是避免多线程操作同一对象喽。                    List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);                    updatedDefinitions.addAll(this.beanDefinitionNames);                    updatedDefinitions.add(beanName);                    this.beanDefinitionNames = updatedDefinitions;                    if(this.manualSingletonNames.contains(beanName)) {                        Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames);                        updatedSingletons.remove(beanName);                        this.manualSingletonNames = updatedSingletons;                    }                }            } else {                this.beanDefinitionMap.put(beanName, beanDefinition);                this.beanDefinitionNames.add(beanName);                this.manualSingletonNames.remove(beanName);            }            this.frozenBeanDefinitionNames = null;        }        if(oldBeanDefinition != null || this.containsSingleton(beanName)) {            this.resetBeanDefinition(beanName);        }    }
  • 可以看到最后IOC容器是基于private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);对象的,所有定义好的bean都是在这个线程安全的hashmap中存取的,而且Spring用到了大量的以空间换取“避免多个线程操作同一个对象”这种方法。
阅读全文
0 0
原创粉丝点击