spring源码解析之IOC容器(三)——依赖注入

  上一篇主要是跟踪了IOC容器对bean标签进行解析之后存入Map中的过程,这些bean只是以BeanDefinition为载体单纯的存储起来了,并没有转换成一个个的对象,今天继续进行跟踪,看一看IOC容器是怎样实例化对象的。

  我们都使用过以下代码:

1 FileSystemXmlApplicationContext  context=new FileSystemXmlApplicationContext("bean.xml");
2 User user=context.getBean("user",User.class);

  这样我们就能获取到user对象了,所以,不难想象,这个getBean方法就是实例化对象的入口。接下来我们就以这个方法为切入点,来探究IOC容器中bean的实例化过程。getBean方法是在FileSystemXmlApplicationContext的基类AbstractApplicationContext中定义的,代码如下:

1 public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
2         assertBeanFactoryActive();
3         return getBeanFactory().getBean(name, requiredType);
4     }

  里面有很多重载方法,里面有调用了某个beanFactory的getBean方法。AbstractApplicationContext中并没有定义getBeanFactory这个方法,那一定是在FileSystemXmlApplicatio

—ntext的某个父类中定义的,我们再回过头看一下它的UML图:

  经过查找之后,是在AbstractRefreshableApplicationContext中定义的,且这个beanFactory是DefaultListableBeanFactory类型的:

 1 public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
 2
 3     private Boolean allowBeanDefinitionOverriding;
 4
 5     private Boolean allowCircularReferences;
 6
 7     /** Bean factory for this context */
 8     private DefaultListableBeanFactory beanFactory;
 9
10     /** Synchronization monitor for the internal BeanFactory */
11     private final Object beanFactoryMonitor = new Object();

  直接进入DefaultListableBeanFactory中,查看它的getBean方法:

public <T> T getBean(Class<T> requiredType) throws BeansException {
        return getBean(requiredType, (Object[]) null);
    }
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
        NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);
        if (namedBean != null) {
            return namedBean.getBeanInstance();
        }
        BeanFactory parent = getParentBeanFactory();
        if (parent != null) {
            return parent.getBean(requiredType, args);
        }
        throw new NoSuchBeanDefinitionException(requiredType);
    }

  发现里面只有这两个重载方法,其他getBean方法,包括例子中使用的那个重载方法没有看到,我们看一下DefaultListableBeanFactory类的UML图:

  经查找,发现在父类AbstractBeanFactory中定义了其他的getBean方法,如下:

1 public Object getBean(String name, Object... args) throws BeansException {
2         return doGetBean(name, null, args, false);
3     }
1 public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
2         return doGetBean(name, requiredType, args, false);
3     }

  里面都调用了doGetBean方法,那么进入继续跟踪:

  1 protected <T> T doGetBean(
  2             final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
  3             throws BeansException {
  4         //将bean的name进行转换,比如将name前面的“&”符去掉,带“&”的name,获取的是beanFactory本身,而不是
  5         //beanFactory生成出来的bean实例
  6         final String beanName = transformedBeanName(name);
  7         Object bean;
  8
  9         // Eagerly check singleton cache for manually registered singletons.
 10         //看缓存中是否已经有该bean
 11         Object sharedInstance = getSingleton(beanName);
 12         //如果缓存中有
 13         if (sharedInstance != null && args == null) {
 14             if (logger.isDebugEnabled()) {
 15                 if (isSingletonCurrentlyInCreation(beanName)) {
 16                     logger.debug("Returning eagerly cached instance of singleton bean ‘" + beanName +
 17                             "‘ that is not fully initialized yet - a consequence of a circular reference");
 18                 }
 19                 else {
 20                     logger.debug("Returning cached instance of singleton bean ‘" + beanName + "‘");
 21                 }
 22             }
 23             //如果sharedInstance是FactoryBean类型,则返回它生产的对象,否则,返回它本身
 24             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 25         }
 26         //如果缓存中没有,第一次创建的时候
 27         else {
 28             // Fail if we‘re already creating this bean instance:
 29             // We‘re assumably within a circular reference.
 30             if (isPrototypeCurrentlyInCreation(beanName)) {
 31                 throw new BeanCurrentlyInCreationException(beanName);
 32             }
 33
 34             // Check if bean definition exists in this factory.
 35             //获取父容器
 36             BeanFactory parentBeanFactory = getParentBeanFactory();
 37             //如果父容器存在,且在当前容器中没有找到该名称的bean的数据
 38             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 39                 //则到父容器中进行处理
 40                 // Not found -> check parent.
 41                 //将name前加上“&”
 42                 String nameToLookup = originalBeanName(name);
 43                 //分别对是否有参数的情况进行处理
 44                 if (args != null) {
 45                     // Delegation to parent with explicit args.
 46                     return (T) parentBeanFactory.getBean(nameToLookup, args);
 47                 }
 48                 else {
 49                     // No args -> delegate to standard getBean method.
 50                     return parentBeanFactory.getBean(nameToLookup, requiredType);
 51                 }
 52             }
 53
 54             if (!typeCheckOnly) {
 55                 markBeanAsCreated(beanName);
 56             }
 57
 58             try {
 59                 //将数据封装成RootBeanDefinition对象
 60                 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 61                 //检查是否为抽象类
 62                 checkMergedBeanDefinition(mbd, beanName, args);
 63
 64                 // Guarantee initialization of beans that the current bean depends on.
 65                 //获取当前创建的bean的依赖的bean
 66                 String[] dependsOn = mbd.getDependsOn();
 67                 if (dependsOn != null) {
 68                     for (String dep : dependsOn) {
 69                         if (isDependent(beanName, dep)) {
 70                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 71                                     "Circular depends-on relationship between ‘" + beanName + "‘ and ‘" + dep + "‘");
 72                         }
 73                         //为当前bean和它的依赖对象建立映射关系
 74                         registerDependentBean(dep, beanName);
 75                         try {
 76                             //递归调用getBean方法,创建依赖对象,直到没有依赖对象为止
 77                             getBean(dep);
 78                         }
 79                         catch (NoSuchBeanDefinitionException ex) {
 80                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 81                                     "‘" + beanName + "‘ depends on missing bean ‘" + dep + "‘", ex);
 82                         }
 83                     }
 84                 }
 85
 86                 // Create bean instance.
 87                 if (mbd.isSingleton()) {
 88                     sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
 89                         @Override
 90                         public Object getObject() throws BeansException {
 91                             try {
 92                                 //回调方法
 93                                 return createBean(beanName, mbd, args);
 94                             }
 95                             catch (BeansException ex) {
 96                                 // Explicitly remove instance from singleton cache: It might have been put there
 97                                 // eagerly by the creation process, to allow for circular reference resolution.
 98                                 // Also remove any beans that received a temporary reference to the bean.
 99                                 destroySingleton(beanName);
100                                 throw ex;
101                             }
102                         }
103                     });
104                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
105                 }
106
107                 else if (mbd.isPrototype()) {
108                     // It‘s a prototype -> create a new instance.
109                     Object prototypeInstance = null;
110                     try {
111                         beforePrototypeCreation(beanName);
112                         prototypeInstance = createBean(beanName, mbd, args);
113                     }
114                     finally {
115                         afterPrototypeCreation(beanName);
116                     }
117                     bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
118                 }
119
120                 else {
121                     String scopeName = mbd.getScope();
122                     final Scope scope = this.scopes.get(scopeName);
123                     if (scope == null) {
124                         throw new IllegalStateException("No Scope registered for scope name ‘" + scopeName + "‘");
125                     }
126                     try {
127                         Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
128                             @Override
129                             public Object getObject() throws BeansException {
130                                 beforePrototypeCreation(beanName);
131                                 try {
132                                     return createBean(beanName, mbd, args);
133                                 }
134                                 finally {
135                                     afterPrototypeCreation(beanName);
136                                 }
137                             }
138                         });
139                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
140                     }
141                     catch (IllegalStateException ex) {
142                         throw new BeanCreationException(beanName,
143                                 "Scope ‘" + scopeName + "‘ is not active for the current thread; consider " +
144                                 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
145                                 ex);
146                     }
147                 }
148             }
149             catch (BeansException ex) {
150                 cleanupAfterBeanCreationFailure(beanName);
151                 throw ex;
152             }
153         }
154
155         // Check if required type matches the type of the actual bean instance.
156         if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
157             try {
158                 return getTypeConverter().convertIfNecessary(bean, requiredType);
159             }
160             catch (TypeMismatchException ex) {
161                 if (logger.isDebugEnabled()) {
162                     logger.debug("Failed to convert bean ‘" + name + "‘ to required type ‘" +
163                             ClassUtils.getQualifiedName(requiredType) + "‘", ex);
164                 }
165                 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
166             }
167         }
168         return (T) bean;
169     }

  可以看到对不同scope域的bean的创建过程,其中会进行递归创建,现在进入createBean方法中,其实现是在AbstractAutowireCapableBeanFactory类中,代码如下:

 1 protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
 2         if (logger.isDebugEnabled()) {
 3             logger.debug("Creating instance of bean ‘" + beanName + "‘");
 4         }
 5         RootBeanDefinition mbdToUse = mbd;
 6
 7         // Make sure bean class is actually resolved at this point, and
 8         // clone the bean definition in case of a dynamically resolved Class
 9         // which cannot be stored in the shared merged bean definition.
10         //判断需要创建的bean是否可以实例化,是否可以通过类装载其进行装载
11         Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
12         if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
13             mbdToUse = new RootBeanDefinition(mbd);
14             mbdToUse.setBeanClass(resolvedClass);
15         }
16
17         // Prepare method overrides.
18         try {
19             //这里是对overrides属性和look-up属性的处理
20             mbdToUse.prepareMethodOverrides();
21         }
22         catch (BeanDefinitionValidationException ex) {
23             throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
24                     beanName, "Validation of method overrides failed", ex);
25         }
26
27         try {
28             //AOP就是这里操作的,如果配置了postProcessor,则生成一个proxy返回,即代理类
29             // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
30             Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
31             if (bean != null) {
32                 return bean;
33             }
34         }
35         catch (Throwable ex) {
36             throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
37                     "BeanPostProcessor before instantiation of bean failed", ex);
38         }
39         //创建bean的方法调用
40         Object beanInstance = doCreateBean(beanName, mbdToUse, args);
41         if (logger.isDebugEnabled()) {
42             logger.debug("Finished creating instance of bean ‘" + beanName + "‘");
43         }
44         return beanInstance;
45     }

  进入doCreateBean方法:

  1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
  2             throws BeanCreationException {
  3
  4         // Instantiate the bean.
  5         BeanWrapper instanceWrapper = null;
  6         if (mbd.isSingleton()) {
  7             //如果是单例,先把缓存中的同名Bean清除
  8             instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  9         }
 10         //如果缓存中没有
 11         if (instanceWrapper == null) {
 12             //则创建一个实例
 13             instanceWrapper = createBeanInstance(beanName, mbd, args);
 14         }
 15         final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
 16         Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
 17         mbd.resolvedTargetType = beanType;
 18
 19         // Allow post-processors to modify the merged bean definition.
 20         synchronized (mbd.postProcessingLock) {
 21             if (!mbd.postProcessed) {
 22                 try {
 23                     //使用后置处理器进行处理
 24                     applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
 25                 }
 26                 catch (Throwable ex) {
 27                     throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 28                             "Post-processing of merged bean definition failed", ex);
 29                 }
 30                 mbd.postProcessed = true;
 31             }
 32         }
 33
 34         // Eagerly cache singletons to be able to resolve circular references
 35         // even when triggered by lifecycle interfaces like BeanFactoryAware.
 36         //这里是对单例的循环引用的处理
 37         boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
 38                 isSingletonCurrentlyInCreation(beanName));
 39         if (earlySingletonExposure) {
 40             if (logger.isDebugEnabled()) {
 41                 logger.debug("Eagerly caching bean ‘" + beanName +
 42                         "‘ to allow for resolving potential circular references");
 43             }
 44             addSingletonFactory(beanName, new ObjectFactory<Object>() {
 45                 @Override
 46                 public Object getObject() throws BeansException {
 47                     return getEarlyBeanReference(beanName, mbd, bean);
 48                 }
 49             });
 50         }
 51
 52         //这里是对bean的初始化,依赖注入往往是在这里进行的,这个exposedObject在初始化完成之后会作为依赖注入完成之后的Bean
 53         // Initialize the bean instance.
 54         Object exposedObject = bean;
 55         try {
 56             //属性的填充
 57             populateBean(beanName, mbd, instanceWrapper);
 58             if (exposedObject != null) {
 59                 exposedObject = initializeBean(beanName, exposedObject, mbd);
 60             }
 61         }
 62         catch (Throwable ex) {
 63             if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
 64                 throw (BeanCreationException) ex;
 65             }
 66             else {
 67                 throw new BeanCreationException(
 68                         mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
 69             }
 70         }
 71
 72         if (earlySingletonExposure) {
 73             Object earlySingletonReference = getSingleton(beanName, false);
 74             if (earlySingletonReference != null) {
 75                 if (exposedObject == bean) {
 76                     exposedObject = earlySingletonReference;
 77                 }
 78                 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
 79                     String[] dependentBeans = getDependentBeans(beanName);
 80                     Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
 81                     for (String dependentBean : dependentBeans) {
 82                         if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
 83                             actualDependentBeans.add(dependentBean);
 84                         }
 85                     }
 86                     if (!actualDependentBeans.isEmpty()) {
 87                         throw new BeanCurrentlyInCreationException(beanName,
 88                                 "Bean with name ‘" + beanName + "‘ has been injected into other beans [" +
 89                                 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
 90                                 "] in its raw version as part of a circular reference, but has eventually been " +
 91                                 "wrapped. This means that said other beans do not use the final version of the " +
 92                                 "bean. This is often the result of over-eager type matching - consider using " +
 93                                 "‘getBeanNamesOfType‘ with the ‘allowEagerInit‘ flag turned off, for example.");
 94                     }
 95                 }
 96             }
 97         }
 98
 99         // Register bean as disposable.
100         try {
101             registerDisposableBeanIfNecessary(beanName, bean, mbd);
102         }
103         catch (BeanDefinitionValidationException ex) {
104             throw new BeanCreationException(
105                     mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
106         }
107
108         return exposedObject;
109     }

  这里要说一下,当在创建bean时,IOC会将该bean的名字存一份到singletonsCurrentlyInCreation这个map中,然后每次创建的时候都会到里面进行检查当前bean是否正在被创建。为了避免发生循环引用(A依赖B,B依赖C,C依赖A)引起是循环,在第一次创建bean时,IOC容器会把用于创建这个bean的工厂对象放入singletonFactories这个map中,key是这个正在被创建的bean的名字。这样发生循环依赖的时候,就不再调用getBean方法了,而是直接使用工厂创建一个bean给被依赖的对象。比如第一次创建A时,将A的名称存入了singletonsCurrentlyInCreation这个map中,并且调用addSingletonFactory方法,将创建A的工厂放到singletonFactories中了,然后递归调用getBean创建依赖对象B、C,创建C时,要先创建它的依赖对象A,此时,IOC容器检查到singletonsCurrentlyInCreation中已经有这个A了,说明它已经在创建的过程中,只是还没有完成创建,此时,IOC容器直接就使用这个工厂将A创建出来赋给C了,然后再往回完成B和A的创建。可以看一下addSingletonFactory方法的实现:

 1 protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
 2         Assert.notNull(singletonFactory, "Singleton factory must not be null");
 3         synchronized (this.singletonObjects) {
 4             if (!this.singletonObjects.containsKey(beanName)) {
 5                 this.singletonFactories.put(beanName, singletonFactory);
 6                 this.earlySingletonObjects.remove(beanName);
 7                 this.registeredSingletons.add(beanName);
 8             }
 9         }
10     }
1 public Object getSingleton(String beanName) {
2         return getSingleton(beanName, true);
3     }
 1 protected Object getSingleton(String beanName, boolean allowEarlyReference) {
 2         //从缓存中获取该bean的实例,已经填充了属性值的实例
 3         Object singletonObject = this.singletonObjects.get(beanName);
 4         //创建bean时,IOC会在this.singletonsCurrentlyInCreation中存一个该bean的名称,表示正在创建这个bean
 5         if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
 6             synchronized (this.singletonObjects) {
 7                 //也是从缓存中获取实例,但是这个缓存中的实例是没有经过填充的实例
 8                 singletonObject = this.earlySingletonObjects.get(beanName);
 9                 if (singletonObject == null && allowEarlyReference) {
10                     //获取生成该bean的beanFactory
11                     ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
12                     if (singletonFactory != null) {
13                         //获取这个bean的实例
14                         singletonObject = singletonFactory.getObject();
15                         //将这个还未经填充属性的bean存入新生代缓存中(自己取的名字,类似于JVM)
16                         this.earlySingletonObjects.put(beanName, singletonObject);
17                         //将这个生产bean的工厂移除
18                         this.singletonFactories.remove(beanName);
19                     }
20                 }
21             }
22         }
23         return (singletonObject != NULL_OBJECT ? singletonObject : null);
24     }

  在进行递归调用getBean方法创建依赖对象之前,getSignal方法是先调用的,前面的代码,doGetBean方法中可以看到,可以多看几遍就能理解。另外,对于原型实例,不允许循环引用。循环引用只针对单例。下一篇跟踪bean的属性的填充。

原文地址:https://www.cnblogs.com/helei123/p/11087463.html

时间: 2024-11-08 08:50:22

spring源码解析之IOC容器(三)——依赖注入的相关文章

spring源码解析之IOC容器(一)

学习优秀框架的源码,是提升个人技术水平必不可少的一个环节.如果只是停留在知道怎么用,但是不懂其中的来龙去脉,在技术的道路上注定走不长远.最近,学习了一段时间的spring源码,现在整理出来,以便日后温故知新. IOC容器是spring最核心的模块之一,是整个spring体系的基石,spring其他模块中,都需要用到IOC容器的功能.spring框架为我们提供了多种IOC容器,DefaultableBeanFact ory.FileSystemXmlApplicationContext.Class

spring源码解析之IOC容器(二)------加载和注册

上一篇跟踪了IOC容器对配置文件的定位,现在我们继续跟踪代码,看看IOC容器是怎么加载和注册配置文件中的信息的.开始之前,首先我们先来了解一下IOC容器所使用的数据结构-------BeanDefinition,它是一个上层接口,有很多实现类,分别对应不同的数据载体.我们平时开发的时候,也会定义很多pojo类,来作为获取数据的载体.最常见的就是,从数据库中获取数据之后,使用一个定义的pojo来装载,然后我们就可以在程序中使用这个pojo类来编写各种业务逻辑.同样,IOC容器首先会读取配置的XML

【spring源码分析】IOC容器初始化(总结)

前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正的bean对象. 总结 [spring源码分析]IOC容器初始化(一):主要分析了Spring是如何解析占位符以及BeanFactory的最终实现类DefaultListableBeanFactory. [spring源码分析]IOC容器初始化(二):以loadBeanDefinitions函数为切

Spring源码阅读:IOC容器的设计与实现(二)——ApplicationContext

上一主题中,了解了IOC容器的基本概念,以及BeanFactory的设计与实现方式,这里就来了解一下ApplicationContext方式的实现. ApplicationContext 在Spring的参考文档中,为啥要推荐使用ApplicationContext?它能给我们的应用带来什么好处呢?作为BeanFactory的实现之一,它又是如何设计的?在SpringMVC中使用的WebApplictionContext\XmlApplicationContext与之有何关联? Applicat

【spring源码分析】IOC容器初始化(十二)

前言:在doCreateBean方法中还遗留一个问题没有分析:循环依赖.循环依赖在Spring中是非常重要的一个知识点,因此单独进行分析. 什么是循环依赖 循环依赖就是循环引用,两个或两个以上的bean互相引用对方,最终形成一个闭环.如A依赖B,B依赖C,C依赖A.如下图所示: 循环依赖其实就是一个死循环的过程,在初始化A的时候发现引用了B,则就会去初始化B,然后发现B又引用C,则又去初始化C,在初始化C的时候,再次发现C引用了A,则又去初始化A,这样就处于死循环,除非有终结条件. Spring

【spring源码分析】IOC容器初始化(一)

前言:spring主要就是对bean进行管理,因此IOC容器的初始化过程非常重要,搞清楚其原理不管在实际生产或面试过程中都十分的有用.在[spring源码分析]准备工作中已经搭建好spring的环境,并利用xml配置形式对类进行了实例化.在test代码中有一个非常关键的类ClassPathXmlApplicationContext,在这个类中实现了IOC容器的初始化,因此我们从ClassPathXmlApplicationContext入手开始研究IOC的初始化过程. 1.ClassPathXm

Spring源码分析之IOC容器(一)

Spring作为当今风靡世界的Web领域的第一框架,作为一名Java开发程序员是一定要掌握的,除了需要掌握基本的使用之外,更需要掌握其实现原理,因为我们往往在开发的过程中,会出现各种各样的异常问题.而且这样的问题去百度有时候往往也找不到特别有效的解决方法,因为问题的原因非常多而百度的又不准确,这个时候怎么办呢?在熟练掌握Spring代码的情况下,我们可以根据提示的异常信息,去跟到源代码的地方,可以准确的定位到异常的所在,这就犹如debug调试自己的业务逻辑一样轻松了,所以Spring的源代码非常

spring源码研究之IoC容器在web容器中初始化过程

前段时间在公司做了一个项目,项目用了spring框架实现,WEB容器是Tomct 5,虽然说把项目做完了,但是一直对spring的IoC容器在web容器如何启动和起作用的并不清楚.所以就抽时间看一下spring的源代码,借此了解它的原理. 我们知道,对于使用Spring的web应用,无须手动创建Spring容器,而是通过配置文件,声明式的创建Spring容器.因此在Web应用中创建Spring容器有如下两种方式: 1. 直接在web.xml文件中配置创建Spring容器. 2. 利用第三方MVC

【spring源码分析】IOC容器初始化——查漏补缺(三)

前言:本文分析InitializingBean和init-method方法,其实该知识点在AbstractAutowireCapableBeanFactory#initializeBean方法中有所提及,这里对其进行详细分析. InitializingBean InitializingBean是一个接口,它只包含一个afterPropertiesSet方法: 1 public interface InitializingBean { 2 3 /** 4 * 该方法在BeanFactory设置完了