• Spring-IOC源码解读2-容器的初始化过程


    1. IOC容器的初始化过程:IOC容器的初始化由refresh()方法启动,这个启动包括:BeanDifinition的Resource定位,加载和注册三个过程。初始化的过程不包含Bean依赖注入的实现。

    •  第一个过程是Resource的定位过程。这个Resource的定位指的是BeanDefinition的资源定位,它由ResourceLoader通过统一的Resource接口完成。
    •  第二个过程是BeanDefinition的载入,这个过程是把用户定义好的Bean表示为容器的内部数据结构(即BeanDefinition)
    •  第三个过程是向IOC容器注册这些BeanDefinition的过程。

    2. 下面我们以ClassPathXmlApplicationContext 为例分析这个ApplicationContext的实现,使用的spring版本是3.0.2版本。首先看下我们测试的代码和配置文件:

    • 2.1:javaBean的定义
    public class Person {
    	private String name;
    	private int age;
    	private int sex;
    	private Dog dog;
    	private List<Address> addressList;
           } public class Dog { private String dogName; } public class Address { private String type; private String city; }
    • 2. 2beans.xml文件定义:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns="http://www.springframework.org/schema/beans"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
        <!-- person对象 -->
    	<bean id="person" class="com.pepper.spring.model.Person" >
    		<property name="name" value="pepper" />
    		<property name="age" value="24" />
    		<property name="sex" value="1" />
    		<property name="dog" ref="dog" />
    		<property name="addressList">
    			<list>
    				<ref bean="home"/>
    				<ref bean="work"/>
    			</list>
    		</property>
    	</bean>
    	
    	<!-- person对象的Dog属性 -->
    	<bean id="dog" class="com.pepper.spring.model.Dog">
    		<property name="dogName" value="Edward" />
    	</bean>
    	
    	<!-- person对象AddressList属性的两个值 -->
    	<bean id="home" class="com.pepper.spring.model.Address">
    		<property name="type" value="home" />
    		<property name="city" value="SX" />
    	</bean>
    	<bean id="work" class="com.pepper.spring.model.Address">
    		<property name="type" value="work" />
    		<property name="city" value="SZ" />
    	</bean>
    </beans>
    
    • 2.3. 容器启动类:
    public class TestSpring {
    
    	public static final String BEAN_CONFIG_FILE = "E:/workspace_selflearn/read-spring/src/spring-beans.xml";
    	public static final String BEAN_CONFIG_CLASS = "spring-beans.xml";
    	
    	public static void main(String[] args) {
    		testApplicationContext();
    	}
    	//使用XmlBeanFactory
    	public static void testBeanFactory() {
    		Resource res = new ClassPathResource(BEAN_CONFIG_CLASS);
    		BeanFactory fac = new XmlBeanFactory(res);
    		Person p = fac.getBean("person", Person.class);
    		System.out.println(p);
    	}
    	
            //使用ApplicationContext
    	public static void testApplicationContext() {
    		ApplicationContext ac = null;
    	     // ac = new FileSystemXmlApplicationContext(BEAN_CONFIG_FILE);
    		ac = new ClassPathXmlApplicationContext(BEAN_CONFIG_CLASS);
    		Person p = ac.getBean("person", Person.class);
    		System.out.println(p);
    	}
    }
    

    3. 我们先看下ClassPathXmlApplicationContext类的定义:

    public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
    
        private Resource[] configResources;
    
        public ClassPathXmlApplicationContext() {
        }
    
        public ClassPathXmlApplicationContext(ApplicationContext parent) {
            super(parent);
        }
        // configLocation对象表示BeanDefinition所在的文件路径
        public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
            this(new String[] {configLocation}, true, null);
        }
        // Spring支持传入多个BeanDefinition配置文件
        public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
            this(configLocations, true, null);
        }
        // 此构造方法除了包含配置文件路径,还允许指定想要使用的父类IOC容器
        public ClassPathXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
            this(configLocations, true, parent);
        }
    
        public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
            this(configLocations, refresh, null);
        }
        //对象的初始化过程中,调用refresh()方法启动BeanDefinition的载入过程
        public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)throws BeansException {
            super(parent);
            setConfigLocations(configLocations);
            if (refresh) {
                refresh();
            }
        }
    
        public ClassPathXmlApplicationContext(String[] paths, Class clazz) throws BeansException {
            this(paths, clazz, null);
        }
    
        public ClassPathXmlApplicationContext(String[] paths, Class clazz, ApplicationContext parent) throws BeansException {
    
            super(parent);
            Assert.notNull(paths, "Path array must not be null");
            Assert.notNull(clazz, "Class argument must not be null");
            this.configResources = new Resource[paths.length];
            for (int i = 0; i < paths.length; i++) {
                this.configResources[i] = new ClassPathResource(paths[i], clazz);
            }
            refresh();
        }
        //获取资源配置文件
        @Override
        protected Resource[] getConfigResources() {
            return this.configResources;
        }
    
    } 

    容器启动的时候会调用ClassPathXmlApplicationContext的构造方法,在这个构造方法中会调用refresh()方法,这个方法十分重要,这是我们分析容器初始化过程中至关重要的一个接口,我们后面分析的Bean的载入,解析,注册都是以这个方法作为入口开始的。

    public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                // Prepare this context for refreshing.准备上下文
                prepareRefresh();
    
                // Tell the subclass to refresh the internal bean factory.通知子类刷新内部的bean工厂
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
                // Prepare the bean factory for use in this context.准备beanfactory来使用这个上下文.做一些准备工作,例如classloader,beanfactoryPostProcessor等
                prepareBeanFactory(beanFactory);
    
                try {
                    // Allows post-processing of the bean factory in context subclasses.在子类上下文中允许beanfactory进行后置处理
                    postProcessBeanFactory(beanFactory);
    
                    // Invoke factory processors registered as beans in the context.调用工厂处理器作为bean注册到上下文中
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    // Register bean processors that intercept bean creation.开始注册BeanPostProcessor来拦截bean的创建过程
                    registerBeanPostProcessors(beanFactory);
    
                    // Initialize message source for this context.为上下文初始化消息源
                    initMessageSource();
    
                    // Initialize event multicaster for this context.为上下文初始化事件广播
                    initApplicationEventMulticaster();
    
                    // Initialize other special beans in specific context subclasses.在具体的子类上下文中初始化特殊的bean
                    onRefresh();
    
                    // Check for listener beans and register them.检查监听器bean并注册
                    registerListeners();
    
                    // Instantiate all remaining (non-lazy-init) singletons.实例化所有的剩余的singleton的bean
                    finishBeanFactoryInitialization(beanFactory);
    
                    // Last step: publish corresponding event.最后一步,发布应用
                    finishRefresh();
                }
    
                catch (BeansException ex) {
                    // Destroy already created singletons to avoid dangling resources.
                    destroyBeans();
    
                    // Reset 'active' flag.
                    cancelRefresh(ex);
    
                    // Propagate exception to caller.
                    throw ex;
                }
            }
        }
    

      

  • 相关阅读:
    jquery异步加载json格式的数据
    三角形及选中取消按钮的css代码
    css实现自适应宽度布局
    table表格中实现tbody部分可滚动,且thead部分固定
    table数据表格添加checkbox进行数据进行两个表格左右移动。
    对checkbox 的checked的一些总结
    Java多线程同步器
    Springboot动态获取bean对象工具类
    并发阻塞队列和非阻塞队列详解
    多线程-volatile关键字和ThreadLocal详解
  • 原文地址:https://www.cnblogs.com/pepper7/p/7672560.html
Copyright © 2020-2023  润新知