refresh這個方法包含了整個BeanFactory初始化的過程,定位資源由obtainFreshBeanFactory()來完成,
- PRotected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
- refreshBeanFactory();
- ConfigurableListableBeanFactory beanFactory = getBeanFactory();
- if (logger.isDebugEnabled()) {
- logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
- }
- return beanFactory;
- }
可以看到其調用了refreshBeanFactory(),refreshBeanFactory()在這個類中是抽象方法,其實現在AbstractRefreshableapplicationContext中。
- protected final void refreshBeanFactory() throws BeansException {
- if (hasBeanFactory()) {
- destroyBeans();
- closeBeanFactory();
- }
- try {
- DefaultListableBeanFactory beanFactory = createBeanFactory();
- beanFactory.setSerializationId(getId());
- customizeBeanFactory(beanFactory);
- loadBeanDefinitions(beanFactory);
- synchronized (this.beanFactoryMonitor) {
- this.beanFactory = beanFactory;
- }
- }
- catch (IOException ex) {
- ……
- }
- }
在這個方法中,先判斷BeanFactory是否存在,如果存在則先銷毀beans并關閉beanFactory,接著創建DefaultListableBeanFactory,并調用loadBeanDefinitions(beanFactory)裝載bean定義。loadBeanDefinitions方法同樣是抽象方法,是由其子類實現的,也即在AbstractxmlApplicationContext中。
- protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
- <span style="color:#33ff33;">
- XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
-
- <span style="color:#33ff33;">
- <span style="color:#33ff33;">
- beanDefinitionReader.setResourceLoader(this);
- beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
-
- initBeanDefinitionReader(beanDefinitionReader);
- <span style="color:#33ff33;">
- loadBeanDefinitions(beanDefinitionReader);
- }
接著我們轉到beanDefinitionReader中進行處理
- protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
- Resource[] configResources = getConfigResources();
- if (configResources != null) {
- <span style="color:#33ff33;">
- reader.loadBeanDefinitions(configResources);
- }
- String[] configLocations = getConfigLocations();
- if (configLocations != null) {
- reader.loadBeanDefinitions(configLocations);
- }
- }
可以到org.springframework.beans.factory.support看一下BeanDefinitionReader的結構

在其抽象父類AbstractBeanDefinitionReader中定義了載入過程
- public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
- <span style="color:#33ff33;">
- ResourceLoader resourceLoader = getResourceLoader();
- <span style="color:#33ff33;">
- if (resourceLoader instanceof ResourcePatternResolver) {
- <span style="color:#33ff33;">
- try {
- Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
- int loadCount = loadBeanDefinitions(resources);
- return loadCount;
- }
- ........
- }
- else {
- <span style="color:#33ff33;">
- Resource resource = resourceLoader.getResource(location);
- <span style="color:#33ff33;">
- int loadCount = loadBeanDefinitions(resource);
- return loadCount;
- }
- }


看到第8、16行,結合上面的ResourceLoader與ApplicationContext的繼承關系圖,可以知道此時調用的是DefaultResourceLoader中的getSource()方法定位Resource,因為ClassPathXmlApplicationContext本身就是DefaultResourceLoader的實現類,所以此時又回到了ClassPathXmlApplicationContext中來。
繼續回到XmlBeanDefinitionReader的loadBeanDefinitions(Resource …)方法看得到代表bean文件的資源定義以后的載入過程。
- public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
- .......
- try {
- <span style="color:#33ff33;">
- InputStream inputStream = encodedResource.getResource().getInputStream();
- try {
- <span style="color:#33ff33;">
- InputSource inputSource = new InputSource(inputStream);
- if (encodedResource.getEncoding() != null) {
- inputSource.setEncoding(encodedResource.getEncoding());
- }
- <span style="color:#33ff33;">
- return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
- }
- finally {
- <span style="BACKGROUND-COLOR: #33ff33">
- inputStream.close();
- }
- }
- .........
- }
-
- protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
- throws BeanDefinitionStoreException {
- try {
- int validationMode = getValidationModeForResource(resource);
- <span style="color:#33ff33;">
- Document doc = this.documentLoader.loadDocument(
- inputSource, this.entityResolver, this.errorHandler, validationMode, this.namespaceAware);
- return registerBeanDefinitions(doc, resource);
- }
- .......
- }
在doLoadBeanDefinitions(…)先把定義文件解析為DOM對象,然后進行具體的注冊過程。
- public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
- <span style="color:#33ff33;">
- BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
- documentReader.setEnvironment(this.getEnvironment());
- int countBefore = getRegistry().getBeanDefinitionCount();
- <span style="color:#33ff33;">
- documentReader.registerBeanDefinitions(doc,createReaderContext(resource));
- return getRegistry().getBeanDefinitionCount() - countBefore;
- }
- <p> </p>
具體的過程在BeanDefinitionDocumentReader中完成,在DefaultBeanDefinitionDocumentReader的方法中完成bean定義文件的解析和IOC容器中bean的初始化。
- public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
- this.readerContext = readerContext;
-
- logger.debug("Loading bean definitions");
- Element root = doc.getDocumentElement();
-
- doRegisterBeanDefinitions(root);
- }
- protected void doRegisterBeanDefinitions(Element root) {
- <span style="color:#33ff33;">……(注:省略號表示省略掉了代碼)
-
- BeanDefinitionParserDelegate parent = this.delegate;
- this.delegate = createHelper(readerContext, root, parent);
-
- preProcessXml(root);
- parseBeanDefinitions(root, this.delegate);
- postProcessXml(root);
-
- this.delegate = parent;
- }
- protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
- if (delegate.isDefaultNamespace(root)) {
- <span style="color:#33ff33;">
- NodeList nl = root.getChildNodes();
- <span style="color:#33ff33;">
- for (int i = 0; i < nl.getLength(); i++) {
- Node node = nl.item(i);
- if (node instanceof Element) {
- Element ele = (Element) node;
- if (delegate.isDefaultNamespace(ele)) {
- <span style="color:#33ff33;">
- parseDefaultElement(ele, delegate);
- }
- else {
- delegate.parseCustomElement(ele);
- }
- }
- }
- }
- else {
- delegate.parseCustomElement(root);
- }
- }
- private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
- <span style="color:#33ff33;">
- if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
- importBeanDefinitionResource(ele);
- }
- else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
- processAliasRegistration(ele);
- }
- <span style="color:#33ff33;">
- else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
- processBeanDefinition(ele, delegate);
- }
- else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
- <span style="color:#33ff33;">
- doRegisterBeanDefinitions(ele);
- }
- }
- protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
- <span style="color:#33ff33;">
- BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
- if (bdHolder != null) {
- bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
- try {
- <span style="color:#33ff33;">
-
- BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
- }
- catch (BeanDefinitionStoreException ex) {
- ……
- }
- <span style="color:#33ff33;">
-
- getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
- }
可以看到在processBeanDefinition中對具體bean元素的解析是交給BeanDefinitionParserDelegate來完成的。我們接著看其實現的函數:
- public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
- <span style="color:#33ff33;">……(省略)</span>
- AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
- if (beanDefinition != null) {
- <span style="color:#33ff33;">
- ……(省略)
- String[] aliasesArray = StringUtils.toStringArray(aliases);
- <span style="color:#33ff33;">
- return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
- }
- return null;
- }
- <p> </p>
在這里對定義文件中的bean元素進行解析,得到AbstractBeanDefinition,并用BeanDefinitionHolder封裝后返回。
下面我們看解析完的bean如何在IOC容器中注冊:在BeanDefinitionReaderUtils中調用的是:
- public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
- throws BeanDefinitionStoreException {
- <span style="color:#33ff33;">
-
- String beanName = definitionHolder.getBeanName();
- <span style="color:#33ff33;">
- registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
-
- <span style="color:#33ff33;">
-
- String[] aliases = definitionHolder.getAliases();
- if (aliases != null) {
- for (String aliase : aliases) {
- registry.registerAlias(beanName, aliase);
- }
- }
- }
接著我們看看bean的注冊實現,從上面看到其調用的是BeanDefinitionRegistry的方法registerBeanDefinition完成注冊,跟蹤代碼可知BeanFactory容器的一個實現DefaultListableBeanFactory實現了這個接口并提供了注冊的具體實現:

- public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {
-
- ......
- if (beanDefinition instanceof AbstractBeanDefinition) {
- try {
- ((AbstractBeanDefinition) beanDefinition).validate();
- }
- catch (BeanDefinitionValidationException ex) {
- <span style="color:#33ff33;">
- ……
- }
- }
-
- synchronized (this.beanDefinitionMap) {
- Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
- if (oldBeanDefinition != null) {
- if (!this.allowBeanDefinitionOverriding) {
- <span style="color:#33ff33;">
- ……
- }
- else {
- if (this.logger.isInfoEnabled()) {
- ……
- }
- }
- }
- else {
- this.beanDefinitionNames.add(beanName);
- this.frozenBeanDefinitionNames = null;
- }
- this.beanDefinitionMap.put(beanName, beanDefinition);
-
- resetBeanDefinition(beanName);
- }
- }
可以看到整個注冊過程很簡單,就是將bean添加到BeanDefinition的map中。這樣就完成了bean定義在IOC容器中的注冊,就可被IOC容器進行管理和使用了。