本文共 8838 字,大约阅读时间需要 29 分钟。
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 ClassPathXmlApplicationContext2、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 MapbeanDefinitionMap = new ConcurrentHashMap (64); private final Map , String[]> allBeanNamesByType = new ConcurrentHashMap , String[]>(64); private final Map , String[]> singletonBeanNamesByType = new ConcurrentHashMap , 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 { ListbeanNames = new ArrayList (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,这个方法超级长。
protectedT doGetBean(final String name, final Class 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
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等等生命周期的方法都在这个方法中体现了。详见: // spring各种初始化方法大乱斗
至此,spring的IOC相关的代码以及spring容器的主要一些接口类都介绍完了。可以自己写一些例子,结合debug进行断点查看。
转载地址:http://yruni.baihongyu.com/