Spring BeanFactory getBean 源码剖析

本文详细解析了Spring中获取bean的流程,包括缓存机制、循环依赖处理、单例与原型bean的创建过程以及参数类型匹配等内容。

首先看一张时序图


最开始,一切都来自这里:

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext3.xml");
		context.getBean("newsBean"); 

	}

如果我们是通过BeanFactory来构造IoC容器的话,那就是直接从上面的时序图的第五步开始

[java]  view plain copy
  1. public static  void main(String[] args){  
  2.   
  3.         Resource resource=new ClassPathResource("applicationContext2.xml");  
  4.         BeanFactory factory=new DefaultListableBeanFactory();  
  5.         BeanDefinitionReader bdr=new XmlBeanDefinitionReader((BeanDefinitionRegistry) factory);  
  6.         bdr.loadBeanDefinitions(resource);  
  7.   
  8.         String url=((FXNewsBean) factory.getBean("newsBean2")).getUrl();  
  9.         System.out.println(url);          
  10.     }  

当然,ApplicatonContext有缓存机制,在容器启动的时候,就加载了所有的bean,并缓存之,如果有了显式或隐式的调用,直接从缓存里拿就是了

********************

我们从上面的代码很容易追踪到AbstractBeanFactory的doGetBean方法
[java]  view plain copy
  1. @SuppressWarnings("unchecked")  
  2.     protected <T> T doGetBean(  
  3.             final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)  
  4.             throws BeansException {  
  5.         //*************************1  
  6.         final String beanName = transformedBeanName(name);  
  7.         Object bean;  
  8.   
  9.   
  10.         // Eagerly check singleton cache for manually registered singletons.  
  11.         //*************************2  
  12.         Object sharedInstance = getSingleton(beanName);  
  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.             //判断要获得的bean是否实现了FactoryBean,是获得工厂本身还是获得工厂生产的产品  
  24.                         //如果要获得工厂本身 beanName就要以&开头  
  25.                         bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  
  26.         }  
  27.   
  28.   
  29.         else {  
  30.             // Fail if we're already creating this bean instance:  
  31.             // We're assumably within a circular reference.  
  32.             //下面这个是关于循环依赖的处理    
  33.             if (isPrototypeCurrentlyInCreation(beanName)) {  
  34.                 throw new BeanCurrentlyInCreationException(beanName);  
  35.             }  
  36.   
  37.   
  38.             // Check if bean definition exists in this factory.  
  39.             //如果存在父容器,且当前容器中不存在要获取的对象 那就去父容器去找  
  40.             BeanFactory parentBeanFactory = getParentBeanFactory();  
  41.             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {  
  42.                 // Not found -> check parent.  
  43.                 String nameToLookup = originalBeanName(name);  
  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.   
  55.             //typeCheckOnly参数 调用是就是false  
  56.             //标明这个beanname已经被创建了  
  57.             //后面会用到  
  58.             if (!typeCheckOnly) {  
  59.                 markBeanAsCreated(beanName);  
  60.             }  
  61.   
  62.   
  63.             //*************************3  
  64.             final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);  
  65.             checkMergedBeanDefinition(mbd, beanName, args);  
  66.   
  67.   
  68.             // Guarantee initialization of beans that the current bean depends on.  
  69.             //*************************4  
  70.             String[] dependsOn = mbd.getDependsOn();  
  71.             if (dependsOn != null) {  
  72.                 for (String dependsOnBean : dependsOn) {  
  73.                     getBean(dependsOnBean);  
  74.                     registerDependentBean(dependsOnBean, beanName);  
  75.                 }  
  76.             }  
  77.   
  78.   
  79.             // Create bean instance.  
  80.             //*************************5  
  81.             if (mbd.isSingleton()) {  
  82.                 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {  
  83.                     public Object getObject() throws BeansException {  
  84.                         try {  
  85.                             return createBean(beanName, mbd, args);  
  86.                         }  
  87.                         catch (BeansException ex) {  
  88.                             // Explicitly remove instance from singleton cache: It might have been put there  
  89.                             // eagerly by the creation process, to allow for circular reference resolution.  
  90.                             // Also remove any beans that received a temporary reference to the bean.  
  91.                             destroySingleton(beanName);  
  92.                             throw ex;  
  93.                         }  
  94.                     }  
  95.                 });  
  96.                 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);  
  97.             }  
  98.   
  99.   
  100.             else if (mbd.isPrototype()) {  
  101.                 // It's a prototype -> create a new instance.  
  102.                 Object prototypeInstance = null;  
  103.                 try {  
  104.                     beforePrototypeCreation(beanName);  
  105.                     prototypeInstance = createBean(beanName, mbd, args);  
  106.                 }  
  107.                 finally {  
  108.                     afterPrototypeCreation(beanName);  
  109.                 }  
  110.                 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);  
  111.             }  
  112.   
  113.   
  114.             else {  
  115.                 String scopeName = mbd.getScope();  
  116.                 final Scope scope = this.scopes.get(scopeName);  
  117.                 if (scope == null) {  
  118.                     throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");  
  119.                 }  
  120.                 try {  
  121.                     Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {  
  122.                         public Object getObject() throws BeansException {  
  123.                             beforePrototypeCreation(beanName);  
  124.                             try {  
  125.                                 return createBean(beanName, mbd, args);  
  126.                             }  
  127.                             finally {  
  128.                                 afterPrototypeCreation(beanName);  
  129.                             }  
  130.                         }  
  131.                     });  
  132.                     bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);  
  133.                 }  
  134.                 catch (IllegalStateException ex) {  
  135.                     throw new BeanCreationException(beanName,  
  136.                             "Scope '" + scopeName + "' is not active for the current thread; " +  
  137.                             "consider defining a scoped proxy for this bean if you "+
  138. "intend to refer to it from a singleton",  
  139.                             ex);  
  140.                 }  
  141.             }  
  142.         }  
  143.   
  144.   
  145.         // Check if required type matches the type of the actual bean instance.  
  146.         if (requiredType != null && bean != null && 
  147.                 !requiredType.isAssignableFrom(bean.getClass())) {  
  148.             try {  
  149.                 return getTypeConverter().convertIfNecessary(bean, requiredType);  
  150.             }  
  151.             catch (TypeMismatchException ex) {  
  152.                 if (logger.isDebugEnabled()) {  
  153.                     logger.debug("Failed to convert bean '" + name + 
  154.                               "' to required type [" +  
  155.                             ClassUtils.getQualifiedName(requiredType) + "]", ex);  
  156.                 }  
  157.                 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());  
  158.             }  
  159.         }  
  160.         return (T) bean;  
  161.     }  



代码1处,转化有两个步骤,首先处理beanName为&XXX的格式,这里表示要取指定name的factoryBean。在这里先把&符号取消,先获取bean再处理。然后,针对bean的alias机制,这里传入的参数可能是一个bean别名,那么我们先获取这个bean的主要id,只需要根据id值取bean就可以了。



代码2处,就是依次检查缓存。如果缓存里有,就直接拿出来。
    spring的缓存有3种
    之前已经获取过的bean
    手动注入的bean
    手动注入的ObjectFactory
第一种缓存好理解,看一下下面的代码,大家就知道手动注入bean与ObjectFctory是怎么回事了。
[java]  view plain copy
  1. public static  void main(String[] args){  
  2.       
  3.         Resource resource=new ClassPathResource("applicationContext2.xml");  
  4.         BeanFactory factory=new DefaultListableBeanFactory();  
  5.         BeanDefinitionReader bdr=new XmlBeanDefinitionReader(
  6.            (BeanDefinitionRegistry) factory);  
  7.         bdr.loadBeanDefinitions(resource);  
  8.   
  9.   
  10.         FXNewsBean fx=new FXNewsBean();  
  11.         fx.setUrl("Thank glt");  
  12.         //同时还有一个方法叫addSingletonFactory  
  13.         ((DefaultSingletonBeanRegistry) factory).registerSingleton("newsBean2",fx);  
  14.         FXNewsBean news=(FXNewsBean) factory.getBean("newsBean2");  
  15.         System.out.println(news.getUrl());  //打印出Thank glt  
  16.     }  



[java]  view plain copy
  1. final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);  
  2. checkMergedBeanDefinition(mbd, beanName, args);  

代码3处,麻烦的是是getMergedLocalBeanDefinition(beanName)。这个处理的主要是bean的present信息与scope信息。
说实话,这部分我没有看。
下面就是检查bean了。
首先,这个bean不能是abstract的。其次,如果getBean时还传递了要获取bean的参数(这里指构造方法的参)并且这个bean是singleton,那就得报错。
为什么?你想呀
factory.getBean("myBean","aaaa");
factory.getBean("myBean","bbbb");
如果myBean这个对象是singleton,上面的两行代码获得的对象能相等吗?
所以只能报错了。




[java]  view plain copy
  1. String[] dependsOn = mbd.getDependsOn();  
  2.             if (dependsOn != null) {  
  3.                 for (String dependsOnBean : dependsOn) {  
  4.                     getBean(dependsOnBean);  
  5.                     registerDependentBean(dependsOnBean, beanName);  
  6.                 }  
  7.             }  

代码4处,如果BeanA中引用了BeanB,那么再getBean("BeanA")时就会先getBean("BeanB");

之后,注册依赖关系。

这个依赖关系有什么用呢?
似乎是在销毁类时用的,我不是很清楚。







代码5
如果要获取的bean是单例的
[java]  view plain copy
  1. if (mbd.isSingleton()) {  
  2. sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {  
  3.     public Object getObject() throws BeansException {  
  4.         try {  
  5.             return createBean(beanName, mbd, args);  
  6.         }  
  7.         catch (BeansException ex) {  
  8.             // Explicitly remove instance from singleton cache: It might have been put there  
  9.             // eagerly by the creation process, to allow for circular reference resolution.  
  10.             // Also remove any beans that received a temporary reference to the bean.  
  11.             destroySingleton(beanName);  
  12.             throw ex;  
  13.         }  
  14.     }  
  15. });  
  16. }  
注意上面的代码其实只有一行。
即调用getSingleton方法。
只不过getSingleton的第二个参数是一个匿名内部类。
这个内部类有一个getObject方法。,里面调用的是外部类的方法createBean。(外部类是谁?是AbstractBeanFactory)
我们先看getSingleton
[java]  view plain copy
  1. public Object getSingleton(String beanName, ObjectFactory singletonFactory) {  
  2.     singletonObject = singletonFactory.getObject();  
  3.     addSingleton(beanName, singletonObject);//添加到已成功创建列表中 这是缓存  
  4.     return (singletonObject != NULL_OBJECT ? singletonObject : null);  
  5. }  
getSingleton省略了一些代码,主要是验证
getSingleton里面调用getObject就跑到了匿名类里面,最后的是AbstractBeanFactory的createBean方法。
不过AbstractBeanFactory中creatBean是abstract的。
实现在它的子类----AbstractAutowireCapableBeanFactory


[java]  view plain copy
  1. @Override  
  2. protected Object createBean(final String beanName, 
  3.               final RootBeanDefinition mbd, final Object[] args)  
  4.             throws BeanCreationException {  
  5.   
  6.   
  7.         if (logger.isDebugEnabled()) {  
  8.             logger.debug("Creating instance of bean '" + beanName + "'");  
  9.         }  
  10.         // Make sure bean class is actually resolved at this point.  
  11.         //*************************5.1  保证RootBeanDefinition里面有beanclass  
  12.         resolveBeanClass(mbd, beanName);  
  13.   
  14.   
  15.         // Prepare method overrides.  
  16.         try {  
  17.             //*************************5.2  方法注入  
  18.             mbd.prepareMethodOverrides();  
  19.         }  
  20.         catch (BeanDefinitionValidationException ex) {  
  21.             throw new BeanDefinitionStoreException(mbd.getResourceDescription(),  
  22.                     beanName, "Validation of method overrides failed", ex);  
  23.         }  
  24.   
  25.   
  26.         try {  
  27.             // Give BeanPostProcessors a chance to return 
  28.             // a proxy instead of the target bean instance.  
  29.             //*************************5.3    
  30.             Object bean = resolveBeforeInstantiation(beanName, mbd);  
  31.             if (bean != null) {  
  32.                 return bean;  
  33.             }  
  34.         }  
  35.         catch (Throwable ex) {  
  36.             throw new BeanCreationException(
  37.                         mbd.getResourceDescription(), beanName,  
  38.                     "BeanPostProcessor before instantiation of bean failed", ex);  
  39.         }  
  40.         //*************************5.4    
  41.         Object beanInstance = doCreateBean(beanName, mbd, args);  
  42.         if (logger.isDebugEnabled()) {  
  43.             logger.debug("Finished creating instance of bean '" + beanName + "'");  
  44.         }  
  45.         return beanInstance;  
  46.     }  
关于5.2处的代码,它处理的类似这样的bean。 更多信息可查看 http://blog.csdn.net/dlf123321/article/details/47862175
[java]  view plain copy
  1. <bean id="mockPersister" class="..impl.MockNewsPersister">     
  2.   <lookup-method name="getNewsBean" bean="newsBean"/>     
  3. </bean>     


关于5.3处的代码,得提到一个接口InstantiationAwareBeanPostProcessor,它本身也继承了BeanPostProcessor接口。
我们看到了在5.3代码的下面一旦resolveBeforeInstantiation的返回值不是null,那么直接就return。
resolveBeforeInstantiation类似于一个"短路器",执行了resolveBeforeInstantiation后(我是指getBean的对象实现了InstantiationAwareBeanPostProcessor接口,并且postProcessBeforeInstantiation方法的返回值不为null)下面的流程就不走了,直接返回bean。
这个方法一般情况下返回的都是null,通常情况下都是Spring容器内部使用这种特殊类型的BeanPostProcessor做一些动态对象代理等工作,我们使用普通的BeanPostProcessor实现就可以。这里简单提及一下,目的是让大家有所了解。


历尽千辛万苦,我们终于到了5.4了
让我歇会,下一节我们聊doCreatBean。

Spring BeanFacoty doCreateBean方法分析


参考资料

http://michael-softtech.iteye.com/blog/816469 spring源码分析之——spring bean的获取

http://www.iflym.com/index.php/code/201208290001.html Spring中获取一个bean的流程-1

<<spring揭秘>> 第四章 79页

版权声明:本文为博主原创文章,未经博主允许不得转载。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值