IOC(Inversion of Control )控制反转,是Spring框架最重要的一个特性,提供了一个装载类的容器来为类之间进行解耦,并提供了一系列的扩展接口,使得开发者能够在bean的生命周期里自定义一些行为操做。java
在没有IOC以前,类与类之间的耦合关系是这样的。这儿仅仅只有5个类,类之间的耦合关系就如此复杂,不可思议当类的数量随着业务发展而爆炸增多的时候,耦合关系是多么的糟糕。spring
在有了IOC以后,类与类之间的耦合关系是这样的。全部类都注册在IOC容器上,全部类只和IOC容器耦合,而且IOC容器为全部管理的类提供生命周期的管理。缓存
能够看出来IOC容器很像咱们生活中的百货商场,咱们须要什么东西均可以去百货商场买到,在没有百货商场之前咱们买菜须要去菜市场,买手机须要去手机店,买电脑须要到电脑城......极大的方便了获取类的方式。接下来我经过Debug源码的方式来追一追整个IOC启动过程的步骤,但愿能揭开这个“百货商场”的神秘面纱。安全
这是咱们debug的入口,用的是最基础的XML解析的方式。数据结构
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); HelloService service = (HelloService) context.getBean("service"); service.say();
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); //设置parent父容器 setConfigLocations(configLocations);//让ioc容器感知到xml配置文件 if (refresh) { refresh(); } }
作的第一步是super(parent),能够看出IOC容器是具有父子关系的,顺便提一下,这个特性在SpringMVC中体现出来了,SpringMVC的容器是 Spring容器的子容器,这样的结果就是Controller(SpringMVC容器中的Bean)能够调用Service(Spring容器中的类),而反过来则不行,这样必定程度保证了类之间的单向关系,以及调用方式不可逆,使得容器更加安全。app
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 为刷新作好准备。 prepareRefresh(); // 告诉子类刷新内部bean工厂。 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 准备beanfactory,为使用ioc容器作好准备 prepareBeanFactory(beanFactory); try { // 容许beanfactory准备好后作一些事情,扩展点 postProcessBeanFactory(beanFactory); // 将bean注册在ioc容器 invokeBeanFactoryPostProcessors(beanFactory); // 注册拦截bean建立的bean处理器。 registerBeanPostProcessors(beanFactory); // 初始化上下文消息 initMessageSource(); // 为这个上下文初始化事件多播器。 initApplicationEventMulticaster(); // 初始化特定上下文子类中的其余特殊bean。 onRefresh(); // 检查listener类并注册它们 registerListeners(); // 实例化全部的lazy-init单例 finishBeanFactoryInitialization(beanFactory); // 最后一步:发布相应的事件 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // 销毁已经建立的单例 destroyBeans(); // 重置active的值 cancelRefresh(ex); // 将异常传播给调用者 throw ex; } finally { //清空一些元数据的内存,这些元数据生成了单例模式后就再也用不到了 resetCommonCaches(); } } }
这里是ioc容器的诞生点 createBeanFactory()框架
protected final void refreshBeanFactory() throws BeansException { ...... DefaultListableBeanFactory beanFactory = createBeanFactory(); ...... loadBeanDefinitions(beanFactory); ...... }
再看看loadBeanDefinitions()方法 ,这里解释下什么是BeanDefinition (全部的Bean在Spring容器中的数据结构都是BeanDefinition,其中包含了跟这个bean相关的全部信息)beanDefinitionReader能够看作是一个IOC容器bean的生产者,能够从外部环境(xml,注解等)获取到bean的信息并装载进去,这个方法对beanDefinitionReader 设置了ResourceLoader,EnitityResolver等等对解析xml文件很重要的类,继续Debug看。ide
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment. beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }
ResourceLoader会去解析xml文件,将每一个xml中的每一个元素都解析而后返回一个DOM的文档树便于后续操做。post
接着会执行prepareBeanFactory方法,这个方法相似一个制定ioc规则的方法,让哪些接口的bean不注册进去,哪些接口的bean注册进去优化
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // Tell the internal bean factory to use the context's class loader etc. beanFactory.setBeanClassLoader(getClassLoader()); beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // Configure the bean factory with context callbacks. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); // BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found for autowiring) as a bean. beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Register early post-processor for detecting inner beans as ApplicationListeners. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // Detect a LoadTimeWeaver and prepare for weaving, if found. if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // Register default environment beans. if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } }
以后会对实现了BeanFactoryPostProcessor接口的类处理,该扩展点容许在(容器已经初始完成,可是bean尚未初始化这部分时间进行扩展),体现了Spring的扩展性。
又看到了一个扩展点,BeanPostProcessor,该扩展点容许在bean 初始化以前或者以后的时候进行扩展
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
接下来回去预实例化没有设置lazy-init的类
beanFactory.preInstantiateSingletons();
进入这个方法体,在debug已经能够看到本身设置的bean的id值了
能够看到除了类以外还有scope,lazyInit,primary等属性
这儿走了一遍getBean的逻辑,不过由于没有初始化,去到的实例都是null,接着会标记即将建立的bean,并将其缓存
/** 标记已建立的(或即将建立的)指定bean。 这容许bean工厂优化其缓存重复。 建立指定的bean。 * @param beanName the name of the bean */ protected void markBeanAsCreated(String beanName) { if (!this.alreadyCreated.contains(beanName)) { synchronized (this.mergedBeanDefinitions) { if (!this.alreadyCreated.contains(beanName)) { // Let the bean definition get re-merged now that we're actually creating // the bean... just in case some of its metadata changed in the meantime. clearMergedBeanDefinition(beanName); this.alreadyCreated.add(beanName); } } } }
立刻进入实例化bean的代码,其中createBean()是重点
// Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } } });
追了好几层终于看到,bean是经过反射实例化的。
Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
若是是singleton,直接从map里面取,若是没有则经过反射生成,放进map中而后返回,若是是prototype则每次获取都会实例化,返回一个新的。
if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); }
这就是缓存单例bean的map
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null); }
ResourceLoader对xml文档树进行读取解析生成Resource文件,Resource文件封装了对xml文件的IO操做,而后BeanDefinitionReader会对Resource文件读取并生成BeanDefinition放在BeanDefinitionRegistry里面,事后beanFactoryPostProcesser会解析占位符,而后SimpleInstantiationStrategy会经过反射实例化,而后BeanWrapper会对非lazy-init的bean进行赋值,在getBean的时候IOC容器经过Map缓存的方式来达到单例的效果。