• Spring IOC 源码解析(持续)


    如何查看源码

    Spring源码下载https://github.com/spring-projects/spring-framework/tags?after=v3.1.0.RC1

    eclipse关联源码 自己百度吧

    源代码结构组织

    Build-spring-framework是整个Spring源代码的构建目录,里面是项目的构建脚本,如果要自己动手构建Spring,可以进入这个目录使用ANT进行构建。

    l  org.springframework.context是IoC容器的源代码目录

    l  org.springframework.aop是AOP实现的源代码目录

    l  org.springframework.jdbc是JDBC的源代码部分

    l  org.springframework.orm是O/R Mapping对应的源代码实现部分

    SpringIOC源码分析

    IOC初始化

    1、 XmlBeanFactory(屌丝IOC)的整个流程

    2、 FileSystemXmlApplicationContext 的IOC容器流程

    1、高富帅IOC解剖

    2、 设置资源加载器和资源定位

    3、AbstractApplicationContext的refresh函数载入Bean定义过程:

    4、AbstractApplicationContext子类的refreshBeanFactory()方法:

    5、AbstractRefreshableApplicationContext子类的loadBeanDefinitions方法:

    6、AbstractBeanDefinitionReader读取Bean定义资源:

    7、资源加载器获取要读入的资源:

    8、XmlBeanDefinitionReader加载Bean定义资源:

    9、DocumentLoader将Bean定义资源转换为Document对象:

    10、XmlBeanDefinitionReader解析载入的Bean定义资源文件:

    11、DefaultBeanDefinitionDocumentReader对Bean定义的Document对象解析:

    12、BeanDefinitionParserDelegate解析Bean定义资源文件中的<Bean>元素:

    13、BeanDefinitionParserDelegate解析<property>元素:

    14、解析<property>元素的子元素:

    15、解析<list>子元素:

    16、解析过后的BeanDefinition在IoC容器中的注册:

    17、DefaultListableBeanFactory向IoC容器注册解析后的BeanDefinition:

    IOC体系

    BeanFactory

             Spring Bean的创建是典型的工厂模式,这一系列的Bean工厂,也即IOC容器为开发者管理对象间的依赖关系提供了很多便利和基础服务,在Spring中有许多的IOC容器的实现供用户选择和使用,其相互关系如下:

     

     

     

    BeanFactory 

     BeanFactory定义了 IOC 容器的最基本形式,并提供了 IOC 容器应遵守的的最基本的接口,也就是Spring IOC 所遵守的最底层和最基本的编程规范。在  Spring 代码中, BeanFactory 只是个接口,并不是 IOC容器的具体实现,但是 Spring 容器给出了很多种实现,如 DefaultListableBeanFactory 、 XmlBeanFactory 、ApplicationContext 等,都是附加了某种功能的实现。

     大体思路是 反射+DOM4J, 解析配置文件,通过beanId查找bean是否存在

     存在的话,获取该节点class地址,使用反射机制初始化。

     Spring 使用了很多抽象类

     Spring核心jar包:

     SpringCore -- Spring 核心jar

     SpringContext--上下文IOC具体实现

     Spring-Bean --  Spring实例

     Spring-jdbc

     SpringAOP

     

    BeanFactory接口: ctrl+T

     核心方法查看:Bean的工厂

    定义接口去进行规范

    public interface BeanFactory {
        //这里是对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,  
      //如果需要得到工厂本身,需要转义    
        //转义符“&”用来获取FactoryBean本身
        String FACTORY_BEAN_PREFIX = "&";
    //根据bean的名字进行获取bean的实例,这是IOC最大的抽象方法
        Object getBean(String name) throws BeansException;
    //根据bean的名字和Class类型进行获取Bean的实例,和上面方法不同的是,bean名字和Bean 的class类型不同时候会爆出异常
        <T> T getBean(String name, Class<T> requiredType) throws BeansException;
        <T> T getBean(Class<T> requiredType) throws BeansException;
        Object getBean(String name, Object... args) throws BeansException;
    //检测这个IOC容器中是否含有这个Bean
    boolean containsBean(String name);
    //判断这个Bean是不是单利
    
        boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    //判断这个Bean是不是原型
        boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    //查询指定的bean的名字和Class类型是不是指定的Class类型
        boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;
    //这里对得到bean实例的Class类型
        Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    //这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来 
        String[] getAliases(String name);
    }

    BeanDefinition 

    这个接口,可以理解为xml bean元素的数据载体。通过对比xml bean标签的属性列表和BeanDefinition的属性列表一看便知。
    我的理解,是解析XML的过程,就是 xml <bean>元素内容 转换为BeanDefinition对象的过程。而且这个接口,支持层级,对应对象的继承。
    有一个类BeanDefinitionHolder,BeanDefinitionHolder,根据名称或者别名持有beanDefinition,它承载了name和BeanDefinition的映射信息。
    BeanWarpper:
    提供对标准javabean的分析和操作方法:单个或者批量获取和设置属性值,获取属性描述符,查询属性的可读性和可写性等。支持属性的嵌套设置,深度没有限制。
    AbstractRefreshableApplicationContext的refreshBeanFactory()这个方法

    核心类:

     核心方法:

     这个接口主要做xml解析的

       封装xml解析Spring Bean文件的解析封装 (可以get出来个Bean属性哈哈)

       方法: 

    一:

    /**
         * Return the current bean class name of this bean definition.
         * <p>Note that this does not have to be the actual class name used at runtime, in
         * case of a child definition overriding/inheriting the class name from its parent.
         * Also, this may just be the class that a factory method is called on, or it may
         * even be empty in case of a factory bean reference that a method is called on.
         * Hence, do <i>not</i> consider this to be the definitive bean type at runtime but
         * rather only use it for parsing purposes at the individual bean definition level.
         * @see #getParentName()
         * @see #getFactoryBeanName()
         * @see #getFactoryMethodName()
         */
        @Nullable
        String getBeanClassName();

    获取bean的class文件地址  id = xx  class=“”com.tooc5.car“

     

    二:

    /**
    * Override the target scope of this bean, specifying a new scope name.
    * @see #SCOPE_SINGLETON
    * @see #SCOPE_PROTOTYPE
    */
    void setScope(@Nullable String scope);

     xml的配置的范围属性

     

    分析看一个类: 分析要分析父类 一直追踪。核心的都封装在父类

    点击进入这个抽象类 AbstractRefreshableApplicationContext

    看它的方法:refreshBeanFactory()

    protected final void refreshBeanFactory() throws BeansException {
            if (hasBeanFactory()) {
                destroyBeans();
                closeBeanFactory();
            }
            try {
                DefaultListableBeanFactory beanFactory = createBeanFactory();//创建IOC容器(Bean工厂)!!!!!!
                beanFactory.setSerializationId(getId()); 
                customizeBeanFactory(beanFactory);
                loadBeanDefinitions(beanFactory);    //载入loadBeanDefinitions  直接把工厂传入进去了
                synchronized (this.beanFactoryMonitor) {
                    this.beanFactory = beanFactory;
                }
            }
            catch (IOException ex) {
                throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
            }
        }

     点进入看:

     loadBeanDefinitions(beanFactory); 

    实现类:
    @Override
        protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
            // Create a new XmlBeanDefinitionReader for the given BeanFactory.
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);  //读取容器
    
            // Configure the bean definition reader with this context's
            // resource loading environment.
            beanDefinitionReader.setEnvironment(this.getEnvironment());
            beanDefinitionReader.setResourceLoader(this);  //获取到当前上下文
            beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    
            // Allow a subclass to provide custom initialization of the reader,
            // then proceed with actually loading the bean definitions.
            initBeanDefinitionReader(beanDefinitionReader);
            loadBeanDefinitions(beanDefinitionReader);   
        }

    继续点进去看:

    loadBeanDefinitions(beanDefinitionReader);    加载配置文件
        protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
            Resource[] configResources = getConfigResources();
            if (configResources != null) {
                reader.loadBeanDefinitions(configResources);
            }
            String[] configLocations = getConfigLocations();  //数组形式 可以加载多个配置文件
            if (configLocations != null) {
                reader.loadBeanDefinitions(configLocations);
            }
        }

    持续点击: 

     reader.loadBeanDefinitions(configLocations);   
        @Override
        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;
        }

    持续点击:

    loadBeanDefinitions(location);
    循环读取配置文件
    @Override
    public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(location, null);
    }

    持续点击:

    loadBeanDefinitions(location, null);
    
    
    /**
         * Load bean definitions from the specified resource location.
         * <p>The location can also be a location pattern, provided that the
         * ResourceLoader of this bean definition reader is a ResourcePatternResolver.
         * @param location the resource location, to be loaded with the ResourceLoader
         * (or ResourcePatternResolver) of this bean definition reader
         * @param actualResources a Set to be filled with the actual Resource objects
         * that have been resolved during the loading process. May be {@code null}
         * to indicate that the caller is not interested in those Resource objects.
         * @return the number of bean definitions found
         * @throws BeanDefinitionStoreException in case of loading or parsing errors
         * @see #getResourceLoader()
         * @see #loadBeanDefinitions(org.springframework.core.io.Resource)
         * @see #loadBeanDefinitions(org.springframework.core.io.Resource[])
         */
        public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
            ResourceLoader resourceLoader = getResourceLoader();   //获取到当配置路径
            if (resourceLoader == null) {
                throw new BeanDefinitionStoreException(
                        "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
            }
    
            if (resourceLoader instanceof ResourcePatternResolver) {
                // Resource pattern matching available.
                try {
                    Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
                    int count = loadBeanDefinitions(resources);
                    if (actualResources != null) {
                        Collections.addAll(actualResources, resources);
                    }
                    if (logger.isTraceEnabled()) {
                        logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
                    }
                    return count;
                }
                catch (IOException ex) {
                    throw new BeanDefinitionStoreException(
                            "Could not resolve bean definition resource pattern [" + location + "]", ex);
                }
            }
            else {  //////// 看这里
                // Can only load single resources by absolute URL.
                Resource resource = resourceLoader.getResource(location);  //获取资源文件
                int count = loadBeanDefinitions(resource);
                if (actualResources != null) {
                    actualResources.add(resource);
                }
                if (logger.isTraceEnabled()) {
                    logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
                }
                return count;
            }
        }

    拿到resource后继续读取,点击

    int count = loadBeanDefinitions(resource);

    点击xml的 不是配置 文件的

        /**
         * Load bean definitions from the specified XML file.
         * @param resource the resource descriptor for the XML file
         * @return the number of bean definitions found
         * @throws BeanDefinitionStoreException in case of loading or parsing errors
         */
        @Override
        public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
            return loadBeanDefinitions(new EncodedResource(resource));
        }

    持续点击:

     return loadBeanDefinitions(new EncodedResource(resource));
        /**
         * Load bean definitions from the specified XML file.
         * @param encodedResource the resource descriptor for the XML file,
         * allowing to specify an encoding to use for parsing the file
         * @return the number of bean definitions found
         * @throws BeanDefinitionStoreException in case of loading or parsing errors
         */
        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);
            }
    
            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 {
                InputStream inputStream = encodedResource.getResource().getInputStream();  //拿到input流
                try {
                    InputSource inputSource = new InputSource(inputStream);  //读取input流
                    if (encodedResource.getEncoding() != null) {
                        inputSource.setEncoding(encodedResource.getEncoding());  //进行转码
                    }
                    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();
                }
            }
        }
    拿到文件流之后? 持续点击
    return doLoadBeanDefinitions(inputSource, encodedResource.getResource());

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
                throws BeanDefinitionStoreException {
    
            try {  //XML的DOM4J解析
                Document doc = doLoadDocument(inputSource, resource);
                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);
            }
        }

    如何解析的?持续点击:
    /**
         * Actually load bean definitions from the specified XML file.
         * @param inputSource the SAX InputSource to read from
         * @param resource the resource descriptor for the XML file
         * @return the number of bean definitions found
         * @throws BeanDefinitionStoreException in case of loading or parsing errors
         * @see #doLoadDocument
         * @see #registerBeanDefinitions
         */
        protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
                throws BeanDefinitionStoreException {
    
            try {
                Document doc = doLoadDocument(inputSource, resource);  //解析出doc
                int count = registerBeanDefinitions(doc, resource);    //注册bean
                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);
            }
        }

    拿到:doc 和 resource后,注册bean:持续点击

     int count = registerBeanDefinitions(doc, resource); 
    
    
    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
            BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
            int countBefore = getRegistry().getBeanDefinitionCount();
            documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); // 作bean的注册
            return getRegistry().getBeanDefinitionCount() - countBefore;
        }
    持续点击:
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); 
        @Override
        public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
            this.readerContext = readerContext;
            doRegisterBeanDefinitions(doc.getDocumentElement());
        }

    继续点击进入: 从根目录获取到配置文件document。拿到根路径后正式做解析。

        /**
         * Register each bean definition within the given root {@code <beans/>} element.
         */
        @SuppressWarnings("deprecation")  // for Environment.acceptsProfiles(String...)
        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)) {
                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.
                    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);
            parseBeanDefinitions(root, this.delegate);  //做documet解析
            postProcessXml(root);
    
            this.delegate = parent;
        }
    持续点击:
      parseBeanDefinitions(root, this.delegate);  //做documet解析  从根路径开始解析 遍历节点 
    /**
         * Parse the elements at the root level in the document:
         * "import", "alias", "bean".
         * @param root the DOM root element of the document
         */
        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);
            }
        }

    持续点击进入默认解析:

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
            if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {    // input解析
                importBeanDefinitionResource(ele);
            }
            else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {  //别名解析
                processAliasRegistration(ele);
            }
            else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {    //解析beans
                processBeanDefinition(ele, delegate);
            }
            else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {  
                // recurse
                doRegisterBeanDefinitions(ele);
            }
        }

    持续查看解析bean: 

     processAliasRegistration(ele);
        /**
         * Process the given bean element, parsing the bean definition
         * and registering it with the registry.
         */
        protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
            BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
            if (bdHolder != null) {
                bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
                try {
                    // Register the final decorated instance.
                    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));
            }
        }
    可以持续点击查看这里
    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); 
    /**
         * Register the given bean definition with the given bean factory.
         * @param definitionHolder the bean definition including name and aliases
         * @param registry the bean factory to register with
         * @throws BeanDefinitionStoreException if registration failed
         */
        public static void registerBeanDefinition(
                BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
                throws BeanDefinitionStoreException {
    
            // Register bean definition under primary name.
            String beanName = definitionHolder.getBeanName();
            registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());  //beanName beanId的名称 
     
            // Register aliases for bean name, if any.
            String[] aliases = definitionHolder.getAliases();
            if (aliases != null) {
                for (String alias : aliases) {
                    registry.registerAlias(beanName, alias);
                }
            }
        }
    beanName beanId的名称 是通过
       String beanName = definitionHolder.getBeanName();
    获取的:点击查看 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

    @Nullable
        public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
            String id = ele.getAttribute(ID_ATTRIBUTE);   //解析 id
            String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);  // 解析 name
    
            List<String> aliases = new ArrayList<>();
            if (StringUtils.hasLength(nameAttr)) {
                String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                aliases.addAll(Arrays.asList(nameArr));
            }
    
            String beanName = id;    //通过beanId 找
            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) {
                checkNameUniqueness(beanName, aliases, ele);
            }
    
            AbstractBeanDefinition beanDefinition = 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);
                            // 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;
        }
    回退 查看注册的代码,持续点击进入:
    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
    /**
         * Register the given bean definition with the given bean factory.
         * @param definitionHolder the bean definition including name and aliases
         * @param registry the bean factory to register with
         * @throws BeanDefinitionStoreException if registration failed
         */
        public static void registerBeanDefinition(
                BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
                throws BeanDefinitionStoreException {
    
            // Register bean definition under primary name.
            String beanName = definitionHolder.getBeanName();
            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);
                }
            }
        }

    重点点击:

    好几种注册方式:

    选择一种:

    @Override
        public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
                throws BeanDefinitionStoreException {
    
            Assert.hasText(beanName, "'beanName' must not be empty");
            Assert.notNull(beanDefinition, "BeanDefinition must not be null");
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }

    下面插入一段反射代码:

    从这里点击进入:

     点击:

     持续点击进入:

    持续点击:

    @Nullable
        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<>();
            if (StringUtils.hasLength(nameAttr)) {
                String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                aliases.addAll(Arrays.asList(nameArr));
            }
    
            String beanName = id;
            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) {
                checkNameUniqueness(beanName, aliases, ele);
            }
    
            AbstractBeanDefinition beanDefinition = 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);
                            // 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;
        }
    持续点击关键代码 注册bean:
    核心代码:

    持续点击:

    持续点击:

    public static AbstractBeanDefinition createBeanDefinition(
                @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
    
            GenericBeanDefinition bd = new GenericBeanDefinition();
            bd.setParentName(parentName);
            if (className != null) {
                if (classLoader != null) {
                    bd.setBeanClass(ClassUtils.forName(className, classLoader));   //反射机制初始化bean!
                }
                else {
                    bd.setBeanClassName(className);
                }
            }
            return bd;
        }
    注意啊 不要点击classPatxXmlApplicationContext  里面没有! 核心 在父类!


      很多方法写成了一个类 ,一层一个类。看起类是挺不爽的,下伙伴耐心看昂。

     

      可以参考:

    https://www.cnblogs.com/ITtangtang/p/3978349.html

  • 相关阅读:
    象棋中马的遍历
    字符串压缩
    寻找丑数
    Educoder
    Educoder
    以太坊:EVM的存储结构
    以太坊:EVM执行字节码的过程
    以太坊:底层序列化编码方式RLP
    以太坊:在合约里调用指定地址的另一已部署合约
    以太坊:创建合约
  • 原文地址:https://www.cnblogs.com/toov5/p/10707251.html
Copyright © 2020-2023  润新知