spring的IoC原理

1.IoC简介

IoC:控制反转,即把对象交由spring容器进行统一的管理,不需要再手动的new,不仅降低了代码的耦合性,而且提高了程序的易扩展性和健壮性。

2.spring IoC容器初始化原理

2.1 BeanDefinitionRegistry和BeanFactory

spring的初始化过程可以简化为,获取资源定位,载入资源,解析资源(例如xml声明的bean和注解声明的),由相应的BeanDefinitionReader转换成一个个beanDefinition,
然后再有工厂创建和统一管理。BeanDefinitionRegistry负责将bean注册,BeanFactory负责bean的管理。DefaultListableBeanFactory则同时直接和间接实现了上述2个接口,DefaultListableBeanFactory是spring 框架中比较通用的一个BeanFactory。
spring的IoC原理_第1张图片

spring对beanFactory接口下提供几个扩展的子接口
ListableBeanFactory:提供了列举所有bean和bean的类型
HierarchicalBeanFactory:提供了层级的beanFactory,拥有一个获取父类beanFactory的工厂。
AutowireCapableBeanFactory:为已经实例化的对象装配属性,这些属性对象都是Spring管理的。实例化一个类型,并自动装配,这些属性对象都是Spring管理的

2.2 ApplicationContext 简介

ApplicationContext是spring容器核心的容器接口,包含了运行环境的配置,bean实例的获取,spring bean注册资源的定位和装载,事件的发布,国际化信息的接口。
spring的IoC原理_第2张图片

3.spring 启动流程简介。

我们这里以ClassPathXmlApplicationContext的spring容器初始化,来对ioc容器做个简单的讲解。
spring的IoC原理_第3张图片
ClassPathXmlApplicationContext是以xml的形式加载spring 容器的。实现类提供了多个构造器的重载,首先调用setConfigLocations获取xml文件资源,文件支持默认支持ANT风格,
spring的IoC原理_第4张图片
调用了AbstractApplicationContext的refresh方法,该方法会销毁并重新载入spring容器。
spring的IoC原理_第5张图片

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
		     刷新spring容器前的准备工作,设置容器当前时间,和一些准备工作
			// Prepare this context for refreshing.
			prepareRefresh();

           销毁并刷新spring容器
			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            
            为bean工厂配置设置bean的类加载器,spel表达式解析器,以及一些忽略一些自动注入的接口和注册一些自动注入的接口,添加BeanPostProcessor后置处理器
			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				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.
				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.
				destroyBeans();

				// Reset 'active' flag.
				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();
			}
		}
	}

refresh是创建spring容器的核心方法,代码如上。
1.prepareRefresh()
spring的IoC原理_第6张图片
设置容器启动时间和一些标志位和属性资源的初始化。
2.obtainFreshBeanFactory();
获取刷新后的工厂,
spring的IoC原理_第7张图片
spring的IoC原理_第8张图片
销毁和创建新的工厂,并加载加载beandefine到新的spring工厂

spring的IoC原理_第9张图片更据依赖的关系递归的创建beandefinition,并将其添加至工厂内。
3.prepareBeanFactory(beanFactory);
在上下文使用前,再对工厂进行一些准备工作,设置bean的类加载器,spel表达式的解析器,以及自动注入该忽略的类,注册自动注入的类。。。等。
spring的IoC原理_第10张图片
4.postProcessBeanFactory(beanFactory);
工厂bean实例初始化前,调用beanFactory的后置处理
spring的IoC原理_第11张图片
5.invokeBeanFactoryPostProcessors(beanFactory);
调用实现了BeanFactoryPostProcessor的beanDefinition的钩子方法,比如修改beanDefinition的属性啊,做一些实例化前的准备工作。比如
在Spring项目的XML配置文件中,经常可以看到许多配置项的值使用占位符,我们可以将占位符所代表的值单独配置到独立的properties文件,容器会自动帮我们解析占位符,底层的工作就是由PropertyPlaceholderConfigurer负责实现的。它间接的实现了BeanFactoryPostProcessor接口。当BeanFactory在第一阶段加载完所有配置信息时,BeanFactory中保存的对象的属性还是以占位符方式存在的,比如 ${port}。当PropertyPlaceholderConfigurer作为BeanFactoryPostProcessor被应用时,它会使用properties配置文件中的值来替换相应的BeanDefinition中占位符所表示的属性值。当需要实例化bean时,bean定义中的属性值会被替换成我们配置的值。
6.registerBeanPostProcessors(beanFactory);
向工厂注册实现了BeanPostProcessors的bean。该接口方法会在每个bean实例化前后,调用其钩子方法。

/*

public interface BeanPostProcessor {


	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

	
	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

7.initMessageSource();
向工厂注册消息资源的bean,与国家化信息有关的。
8.initApplicationEventMulticaster();
发布spring的事件。事件驱动模型,也就是我们所说的观察者模式。观察者模式有3个对象,目标,观察者,和发布者。容器会检查是否存在name为applicationEventMulticaster的bean,这就是spring事件的发布者,如果没有回创建一个SimpleApplicationEventMulticaster实例,添加至工厂中。观察者模式的好处就是:解耦目标对象和它的依赖对象,目标只需要通知它的依赖对象,具体怎么处理,依赖对象自己决定。
spring的IoC原理_第12张图片
9.finishBeanFactoryInitialization(beanFactory)
递归的创建不是懒加载的bean到spring容器中。
spring的IoC原理_第13张图片
10.finishRefresh()
执行容器最后完成前的操作

/**
	 * Finish the refresh of this context, invoking the LifecycleProcessor's
	 * onRefresh() method and publishing the
	 * {@link org.springframework.context.event.ContextRefreshedEvent}.
	 */
	protected void finishRefresh() {
		// Initialize lifecycle processor for this context.
		从工厂中获取lifecycleProcessor的实例,如果没有就创建一个默认的。lifecycleProcessor提供了感知容器启动和关闭的方法。
		initLifecycleProcessor();

		调用其刷新方法
		// Propagate refresh to lifecycle processor first.
		getLifecycleProcessor().onRefresh();

		发布上下文刷新事件
		publishEvent(new ContextRefreshedEvent(this));

		// Participate in LiveBeansView MBean, if active.
		LiveBeansView.registerApplicationContext(this);
	}

你可能感兴趣的:(java)