spring源码分析之bean之IOC
最近在看spring的源码,正好把其记录下来
一 。 启动过程
在Web服务器tomcat(应用的容器)启动的时候的时候,首先web.xml会自动的加载到容器tomcat里面,所以我们会在web.xml里面加载spring的配置文件,是通过org.springframework.web.context.ContextLoaderListener或者org.springframework.web.context.ContextLoaderServlet加载我们的spring配置文件,我们就拿ContextLoaderListener为例子吧
在ContextLoaderListener这个类中,其实是调用的ContextLoader的initWebApplicationContext方法,而在initWebApplicationContext调用createWebApplicationContext来创建一个context
/* */ protected WebApplicationContext createWebApplicationContext(ServletContext servletContext, ApplicationContext parent) /* */ throws BeansException /* */ { /* 230 */ Class contextClass = determineContextClass(servletContext); /* 231 */ if (!(ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass))) { /* 232 */ throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type ConfigurableWebApplicationContext"); /* */ } /* */ /* 236 */ ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass); /* */ /* 238 */ wac.setParent(parent); /* 239 */ wac.setServletContext(servletContext); /* 240 */ String configLocation = servletContext.getInitParameter("contextConfigLocation"); /* 241 */ if (configLocation != null) { /* 242 */ wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation, ",; \t\n")); /* */ } /* */ /* 246 */ wac.refresh(); /* 247 */ return wac; /* */ }
我们会注意到这个createWebApplicationContext方法里面有一个有一个wac.refresh()方法,这个方法很重要,作用主要是对context进行更新,加载xml的spring配置文件到spring的容器的缓存中
在org.springframework.context.support.AbstractApplicationContext 中我们可以找到这个refresh方法的具体实现
/* */ public synchronized void refresh() throws BeansException, IllegalStateException /* */ { /* 275 */ this.startupTime = System.currentTimeMillis(); /* */ /* 278 */ refreshBeanFactory(); /* 279 */ ConfigurableListableBeanFactory beanFactory = getBeanFactory(); /* */ /* 282 */ beanFactory.setBeanClassLoader(getClassLoader()); /* */ /* 285 */ beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this)); /* */ /* 288 */ beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); /* 289 */ beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); /* 290 */ beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); /* 291 */ beanFactory.ignoreDependencyInterface(MessageSourceAware.class); /* 292 */ beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); /* */ /* 295 */ postProcessBeanFactory(beanFactory); /* */ /* 298 */ for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext(); ) { /* 299 */ BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor)it.next(); /* 300 */ factoryProcessor.postProcessBeanFactory(beanFactory); /* */ } /* */ /* 303 */ if (this.logger.isInfoEnabled()) { /* 304 */ if (getBeanDefinitionCount() == 0) { /* 305 */ this.logger.info("No beans defined in application context [" + getDisplayName() + "]"); /* */ } /* */ else { /* 308 */ this.logger.info(getBeanDefinitionCount() + " beans defined in application context [" + getDisplayName() + "]"); /* */ } /* */ } /* */ /* */ try /* */ { /* 314 */ invokeBeanFactoryPostProcessors(); /* */ /* 317 */ registerBeanPostProcessors(); /* */ /* 320 */ initMessageSource(); /* */ /* 323 */ initApplicationEventMulticaster(); /* */ /* 326 */ onRefresh(); /* */ /* 329 */ registerListeners(); /* */ /* 332 */ beanFactory.preInstantiateSingletons(); /* */ /* 335 */ publishEvent(new ContextRefreshedEvent(this)); /* */ /* 337 */ this.active = true; /* */ } /* */ catch (BeansException ex) /* */ { /* 342 */ beanFactory.destroySingletons(); /* 343 */ throw ex; /* */ } /* */ }
在refresh方法中,refreshBeanFactory(); 这个方法的实现在 org.springframework.context.support.AbstractRefreshableApplicationContext 中,
protected final synchronized void refreshBeanFactory() /* */ throws BeansException /* */ { /* 81 */ if (this.beanFactory != null) { /* 82 */ this.beanFactory.destroySingletons(); /* 83 */ this.beanFactory = null; /* */ } /* */ /* */ try /* */ { /* 88 */ DefaultListableBeanFactory beanFactory = createBeanFactory(); /* 89 */ loadBeanDefinitions(beanFactory); /* 90 */ this.beanFactory = beanFactory; /* 91 */ if (this.logger.isInfoEnabled()) /* 92 */ this.logger.info("Bean factory for application context [" + getDisplayName() + "]: " + beanFactory); /* */ } /* */ catch (IOException ex) /* */ { /* 96 */ throw new ApplicationContextException("I/O error parsing XML document for application context [" + getDisplayName() + "]", ex); /* */ } /* */ }
我们可以看到一个很显眼的方法叫做 loadBeanDefinitions(beanFactory); 他是做什么的呢,看他的名字我们就猜的出来他是做什么的,他就是load spring的配置文件到spring容器的内存中,由于时间的关系,我就不详细的往下写了,具体的及时将xml拆分一个一个的BeanDefinition 然后放到一个Map中缓存起来。而这个时候Web服务器已经启动完成了,同时spring的容器也完成了spring配置文件的解析以及缓存过程。
二 。 依赖注入过程
用的spring的童鞋都知道,如何实例化一个bean吗,那就是
Object beanInstance = conext.getBean("beanName");
但是这个过程是怎么做到的呢,让我们继续分析代码,首先我们的xml已经缓存在spring容器的内存中了,这个时候我们要用了,首先我们看看getBean的实现吧,getBean的实现在 org.springframework.beans.factory.support.AbstractBeanFactory 中,
/* */ public Object getBean(String name, Class requiredType, Object[] args) /* */ throws BeansException /* */ { /* 194 */ String beanName = transformedBeanName(name); /* 195 */ Object bean = null; /* */ /* 198 */ Object sharedInstance = null; /* 199 */ synchronized (this.singletonCache) { /* 200 */ sharedInstance = this.singletonCache.get(beanName); /* */ } /* 202 */ if (sharedInstance != null) { /* 203 */ if (isSingletonCurrentlyInCreation(beanName)) { /* 204 */ if (this.logger.isDebugEnabled()) { /* 205 */ this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); /* */ } /* */ /* */ } /* 210 */ else if (this.logger.isDebugEnabled()) { /* 211 */ this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); /* */ } /* */ /* 214 */ bean = getObjectForBeanInstance(sharedInstance, name, true); /* */ } /* */ else /* */ { /* 220 */ if (isSingletonCurrentlyInCreation(beanName)) { /* 221 */ throw new BeanCurrentlyInCreationException(beanName); /* */ } /* */ /* 225 */ if ((getParentBeanFactory() != null) && (!(containsBeanDefinition(beanName)))) /* */ { /* 227 */ if (getParentBeanFactory() instanceof AbstractBeanFactory) /* */ { /* 229 */ return ((AbstractBeanFactory)getParentBeanFactory()).getBean(name, requiredType, args); /* */ } /* 231 */ if (args == null) /* */ { /* 233 */ return getParentBeanFactory().getBean(name, requiredType); /* */ } /* */ /* 236 */ throw new NoSuchBeanDefinitionException(beanName, "Cannot delegate to parent BeanFactory because it does not supported passed-in arguments"); /* */ } /* */ /* 241 */ this.alreadyCreated.add(beanName); /* 242 */ RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition(beanName, false); /* 243 */ checkMergedBeanDefinition(mergedBeanDefinition, beanName, requiredType, args); /* */ /* 246 */ if (mergedBeanDefinition.isSingleton()) { /* 247 */ synchronized (this.singletonCache) /* */ { /* 249 */ sharedInstance = this.singletonCache.get(beanName); /* 250 */ if (sharedInstance == null) { /* 251 */ if (this.logger.isDebugEnabled()) { /* 252 */ this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); /* */ } /* 254 */ this.currentlyInCreation.add(beanName); /* */ try { /* 256 */ sharedInstance = createBean(beanName, mergedBeanDefinition, args); /* 257 */ addSingleton(beanName, sharedInstance); /* */ } /* */ catch (BeansException ex) /* */ { /* 264 */ throw ex; /* */ } /* */ finally { /* 267 */ this.currentlyInCreation.remove(beanName); /* */ } /* */ } /* */ } /* 271 */ bean = getObjectForBeanInstance(sharedInstance, name, true); /* */ } /* 274 */ else if (mergedBeanDefinition.isPrototype()) /* */ { /* 276 */ Object prototypeInstance = createBean(beanName, mergedBeanDefinition, args); /* 277 */ bean = getObjectForBeanInstance(prototypeInstance, name, false); /* */ } /* */ else /* */ { /* 281 */ String scopeName = mergedBeanDefinition.getScope(); /* 282 */ Scope scope = (Scope)this.scopes.get(scopeName); /* 283 */ if (scope == null) /* 284 */ throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'"); /* */ try /* */ { /* 287 */ Object scopedInstance = scope.get(beanName, new ObjectFactory(beanName, mergedBeanDefinition, args) { private final String val$beanName; /* */ private final RootBeanDefinition val$mergedBeanDefinition; /* */ private final Object[] val$args; /* */ /* */ public Object getObject() throws BeansException { return AbstractBeanFactory.this.createBean(this.val$beanName, this.val$mergedBeanDefinition, this.val$args); /* */ } /* */ }); /* 292 */ bean = getObjectForBeanInstance(scopedInstance, name, false); /* */ } /* */ catch (IllegalStateException ex) { /* 295 */ throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active", ex); /* */ } /* */ } /* */ /* */ } /* */ /* 301 */ if ((requiredType != null) && (!(requiredType.isAssignableFrom(bean.getClass())))) { /* 302 */ throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); /* */ } /* 304 */ return bean; /* */ }
我们看见有一个行代码
RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition(beanName, false);
看名字貌似是根据beanName获取 一个BeanDefinition对象,我们继续跟踪下去
/* */ protected RootBeanDefinition getMergedBeanDefinition(String name, boolean includingAncestors) /* */ throws BeansException /* */ { /* 769 */ String beanName = transformedBeanName(name); /* */ /* 772 */ if ((includingAncestors) && (!(containsBeanDefinition(beanName))) && (getParentBeanFactory() instanceof AbstractBeanFactory)) /* */ { /* 774 */ return ((AbstractBeanFactory)getParentBeanFactory()).getMergedBeanDefinition(beanName, true); /* */ } /* */ /* 778 */ return getMergedBeanDefinition(beanName, getBeanDefinition(beanName)); /* */ }
我们发现最后一句话,return getMergedBeanDefinition(beanName, getBeanDefinition(beanName)); 里面有个 getBeanDefinition(beanName), 但是这个方法是
/* */ protected abstract BeanDefinition getBeanDefinition(String paramString) /* */ throws BeansException;
怎么是个抽象方法啊,怎么回事呢,别急,一般的情况下,这个方法肯定是由他子类实现的,我们先找到他在子类的实现
在 org.springframework.beans.factory.support.DefaultListableBeanFactory 找到了他的实现
/* */ public BeanDefinition getBeanDefinition(String beanName) /* */ throws NoSuchBeanDefinitionException /* */ { /* 313 */ BeanDefinition bd = (BeanDefinition)this.beanDefinitionMap.get(beanName); /* 314 */ if (bd == null) { /* 315 */ if (this.logger.isDebugEnabled()) { /* 316 */ this.logger.debug("No bean named '" + beanName + "' found in " + toString()); /* */ } /* 318 */ throw new NoSuchBeanDefinitionException(beanName); /* */ } /* 320 */ return bd; /* */ }
额,原来如此,BeanDefinition bd = (BeanDefinition)this.beanDefinitionMap.get(beanName);
原来是通过缓存读取的BeanDefinition啊,而这个缓存beanDefinitionMap 正是第一步缓存的结果
接下来就是通过反射机制依照 BeanDefinition的定义来实例化 Bean然后返回