spring源码分析(一) IOC源码分析

spring-ioc源码分析

概述:spring是一个ioc容器,ioc就是我们把对象之间的依赖关系交给spring进行管理,比如说,我们在配置文件或者java配置类定义了bean的各种关系,spring负责加载这些bean,并维护了类之间的依赖,如果我们需要使用bean,直接getBean即可,这个就是spring作为Ioc容器的主要功能。

一、类介绍

1、ApplicationContext的总览

为了分析ioc的原理,我们先从可以接触到的applicationContent类进行入手,下面这个是我们的启动代码。

ApplicationContext context = new ClassPathXmlApplicationContext(xmlPath)。

以上代码就可以利用配置文件来启动一个 Spring 容器了,这段代码即是从配置文件加载bean到spring容器中,除了ClassPathXmlApplicationContext,我们还有AnnotationConfigApplicationContext(java配置)和FileSystemXmlApplicationContext (和ClassPathXml类似)。

下面我们先看看ApplicationContext的类结构,我们使用过的实现类主要是ClassPathXmlApplicationContext、AnnotationConfigApplicationContext。

ApplicationContext
           ConfigurableApplicationContext
            AbstractApplicationContext
            AbstractRefreshableApplicationContext                  GenericApplicationContext
                                                                                             AnnotationConfigApplicationContext
            AbstractRefreshableConfigApplicationContext
            AbstractXmlApplicationContext
           ClassPathXmlApplicationContext

2、BeanFactory的介绍

我们在说下BeanFactory这个接口,BeanFactory就是提供bean的接口,它的子接口在这基础上增加了扩展功能,我们上面的ApplicationContext也是实现了BeanFactory接口的,但是真正负责加载bean的是另外一个实现子类DefaultListableBeanFactory完成bean解析注册等工作。  // 可以从AbstractRefreshableConfigApplicationContext内找到DefaultListableBeanFactory类型的属性查看。

    BeanFactory   (ApplicationContext系列也有很多类或接口是实现BeanFactory)
    AutowireCapableBeanFactory    HierarchicalBeanFactory    ListableBeanFactory
    ConfigurableListableBeanFactory  // 继承了上面三个接口
    DefaultListableBeanFactory // 实现了ConfigurableListableBeanFactory  和 BeanDefinitionRegistry (负责注册beanDefinition)

3、BeanDefinition的介绍

在介绍BeanDefinition时,我们知道DefaultListableBeanFactory实现了BeanDefinitionRegistry接口功能用来加载并且注册bean。

我们先看看DefaultListableBeanFactory内部用什么来存储创建的bean,截取部分成员变量,beanDefinitionMap就是存储BeanDefinition信息。

    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
    private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
    private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);

BeanDefinition就是保存了我们的bean的名称、bean的类型,依赖那个类,以及是否单例等等信息。
 

二、流程分析

1、refresh主干方法

ClassPathXmlApplicationContext主要是调用refresh方法,refresh() 方法里面又调用了很多方法,详见下面。

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			prepareRefresh();
			// 标记1---加载bean配置以及注册 
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			prepareBeanFactory(beanFactory);
			try {
				postProcessBeanFactory(beanFactory);
				invokeBeanFactoryPostProcessors(beanFactory);
				registerBeanPostProcessors(beanFactory);
				initMessageSource();
				initApplicationEventMulticaster();
				onRefresh();
				registerListeners();
				// 标记2--- 初始化所有的 singleton beans
				finishBeanFactoryInitialization(beanFactory);
				finishRefresh();
			}
		}
	}

上面的标记1方法功能表示如何加载BeanDefinition到容器,标记2方法是创建Bean和初始化,其他都是一些附属处理功能。

我们先看看这些附属方法的主要功能:

prepareBeanFactory : 注册默认BeanPostProcessor用来实现一些功能。

invokeBeanFactoryPostProcessors : 执行BeanFactoryPostProcessor的各种实现类的方法。

registerBeanPostProcessors:注册 BeanPostProcessor 的实现类,这个方法会在初始前初始后增强bean,这里还未初始化的。

2、obtainFreshBeanFactory--加载注册bean

介绍完一些refresh的一些公共处理,我们就从refresh的起点方法obtainFreshBeanFactory来看看spring如何把各种bean从配置文件加载到内部的DefaultListableBeanFactory中。

obtainFreshBeanFactory实际调用obtainFreshBeanFactory方法。

    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {// ... }
        try {
           // 创建了DefaultListableBeanFactory,下面设置成this.beanFactory赋值
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            // 实际加载方法
            loadBeanDefinitions(beanFactory); 
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
    }
	protected DefaultListableBeanFactory createBeanFactory() {
		return new DefaultListableBeanFactory(getInternalParentBeanFactory());
	}

从上面我们可以看到refreshBeanFactory是创建一个DefaultListableBeanFactory来进行加载注册bean。

loadBeanDefinitions 系列调用栈,具体实现过于繁杂,我们知道主要是把配置的bean加载到DefaultListableBeanFactory即可。 (后续补充)

3、finishBeanFactoryInitialization  --- 创建bean和初始化bean

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // ....
		beanFactory.setTempClassLoader(null);

		// 允许缓存元数据,即以后不会变更 
		beanFactory.freezeConfiguration();

		// 实例化所有此时没有实例的单例bean  【主要调用方法】
		beanFactory.preInstantiateSingletons();
	}

从上面代码可以看到,finishBeanFactoryInitialization实际上是调用DefaultListableBeanFactory的preInstantiateSingletons方法。

public void preInstantiateSingletons() throws BeansException {
		
		List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

		for (String beanName : beanNames) {
            // 得到的BeanDefinition加工成RootBeanDefinition
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            // 不是抽象方法不是懒加载和多例
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { 
				if (isFactoryBean(beanName)) {
					final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
					   // ....
					}
					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}
					if (isEagerInit) {
						getBean(beanName);  
					}
				}
				else { // 创建bean的核心方法
					getBean(beanName);
				}
			}
		}

	    // ....略
	}

从上面可以看到,只有单例不是懒加载和多例的才会执行到get'Bean方法,并且这个方法调用doGetBean,这个方法超级长。

	protected <T> T doGetBean(final String name, final Class<T> requiredType, finalObject[] args, boolean typeCheckOnly)throws BeansException {

		final String beanName = transformedBeanName(name);
		Object bean;

		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			// 缓存中取
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		} else {
			// 父工厂取
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				String nameToLookup = originalBeanName(name);
				if (args != null) {
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}
			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dependsOnBean : dependsOn) {
						if (isDependent(beanName, dependsOnBean)) {
							throw new BeanCreationException(""); //循环依赖了
 						}
						registerDependentBean(dependsOnBean, beanName);
						getBean(dependsOnBean); // 依赖执行注册和getBean
					}
				}

				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
                                // 创建bean 核心调用方法
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
					
								destroySingleton(beanName);
								throw ex;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {
					 // 多例略....
				}

				else {
					 // 其他略....
				}
			}
		}

		// ....

		return (T) bean;
	}

doGetBean方法,经过我的删减还有很长,主要包含从缓存取,如果存在返回,从父容器取,如果找到就返回,然后判断BeanDefinition内部的依赖bean,如果有依赖就注册这个依赖,并且同样执行getBean(),等于递归调用所有依赖的bean,执行一系列的getBean方法。最终,依赖都创建好了,当前Bean开始创建,执行的是createBean方法。实际调用的是doCreateBean。

doCreateBean的代码比较长,只贴主要的。

   Object exposedObject = bean;
        try {
            填充属性
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                初始化,包含BeanPostProcess的前置和后置处理
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
        }
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
	
        // 各种awre的执行
		invokeAwareMethods(beanName, bean);

		if (mbd == null || !mbd.isSynthetic()) {
        // 其他BeanPostProcess对本Bean的前置处理
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName);
		}

		try {
            // 初始化方法执行
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			// ...
		}

		if (mbd == null || !mbd.isSynthetic()) {
        // 其他BeanPostProcess对本Bean的后置处理
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

从initializeBean方法,我们可以知道,spring一个bean的创建过程的一些Aware、BeanPostProcess、InitMethod等等生命周期的方法都在这个方法中体现了。详见:https://blog.csdn.net/shuixiou1/article/details/79682954  // spring各种初始化方法大乱斗

至此,spring的IOC相关的代码以及spring容器的主要一些接口类都介绍完了。可以自己写一些例子,结合debug进行断点查看。

猜你喜欢

转载自blog.csdn.net/shuixiou1/article/details/113358591