美文网首页
Spring之对象解析及注册(一)

Spring之对象解析及注册(一)

作者: OPice | 来源:发表于2019-10-14 09:09 被阅读0次

    首先先看一下Spring是如何创建对象的

    Spring创建对象

    public interface IService {
        public String hello();
    }
    public class ServiceImpl implements IService {
        private String name;
    
        @Override
        public String hello() {
            return "hello";
        }
    }
    

    引入最小依赖POM&bean配置

     <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>5.1.7.RELEASE</version>
     </dependency>
     <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>5.1.7.RELEASE</version>
     </dependency>
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
        <bean id="service" class="com.wyh.spring.core.ServiceImpl"
              init-method="hello">
        </bean>
    </beans>
    

    使用XmlBeanFactory创建对象

    public class BeanFactoryDemo {
        public static void main(String[] args) {
            XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
            IService service = (IService) xmlBeanFactory.getBean("service");
            String hello = service.hello();
            System.out.println(hello);
        }
    }
    

    Bean解析及注册

    首先看下new XmlBeanFactory(new ClassPathResource("beans.xml"))这行代码

    1、构造ClassPathResource

    获取到了Resource对象也就等于获取到了该资源文件,后面可以根据方法的定义对文件进行相关操作

    public ClassPathResource(String path) {
            this(path, (ClassLoader)null);
        }
    
        public ClassPathResource(String path, @Nullable ClassLoader classLoader) {
            Assert.notNull(path, "Path must not be null");
            String pathToUse = StringUtils.cleanPath(path);
            if (pathToUse.startsWith("/")) {
                pathToUse = pathToUse.substring(1);
            }
    
            this.path = pathToUse;
            this.classLoader = classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader();
        }
    
    ClassPathResource.png

    2、初始化XmlBeanFactory

    先放一张UML类图,对整体结构有个了解


    XmlBeanFactory

    构造方法

    /**
         * Create a new XmlBeanFactory with the given resource,
         * which must be parsable using DOM.
         * @param resource the XML resource to load bean definitions from
         * @throws BeansException in case of loading or parsing errors
         */
        public XmlBeanFactory(Resource resource) throws BeansException {
            this(resource, null);
        }
    
        /**
         * Create a new XmlBeanFactory with the given input stream,
         * which must be parsable using DOM.
         * @param resource the XML resource to load bean definitions from
         * @param parentBeanFactory parent bean factory
         * @throws BeansException in case of loading or parsing errors
         */
        public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
            super(parentBeanFactory);
            this.reader.loadBeanDefinitions(resource);
        }
    

    super(parentBeanFactory);跟踪到父类AbstractAutowireCapableBeanFactory

    /**
         * Create a new AbstractAutowireCapableBeanFactory.
         */
        public AbstractAutowireCapableBeanFactory() {
            super();
            ignoreDependencyInterface(BeanNameAware.class);
            ignoreDependencyInterface(BeanFactoryAware.class);
            ignoreDependencyInterface(BeanClassLoaderAware.class);
        }
    

    ignoreDependencyInterface方法主要功能是忽略给定接口的自动装配功能。
    例如:A有属性B,当Spring获取A对象时,B没有初始化,先初始化B。

    下面重要的关键是loadBeanDefinitions方法,借了张时序图


    image.png
    1. 封装资源文件
    2. 获取输入流
    3. 通过构造InputSource和Resource继续执行doLoadBeanDefinitions()
      doLoadBeanDefinitions函数里主要做了三件事:
    • 获取对XML文件的验证模式
    • 加载XML文件,获取相应的Document
    • 根据返回Document注册Bean信息
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
                throws BeanDefinitionStoreException {
    
            try {
                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;
            }
               ......
        }
    

    流程图:


    image.png

    相关文章

      网友评论

          本文标题:Spring之对象解析及注册(一)

          本文链接:https://www.haomeiwen.com/subject/ioqmuctx.html