1. 程式人生 > >Spring原始碼學習之路---深入AOP(終)

Spring原始碼學習之路---深入AOP(終)

原文地址:https://blog.csdn.net/zuoxiaolong8810/article/details/8962353

    上一章和各位一起看了一下springAOP的工作流程,當我們給出AOP相關的配置以後,直接從IOC容器中拿出來的就是已經加強過的bean。這說明spring在這個過程中一定做了什麼。

                本章我們就一起來看一下spring是如何完成對bean的增強的,首先我們來看一下,FactoryBean介面中一個方法的定義。

  1. publicinterface FactoryBean<T> {  
  2.     /** 
  3.      * Return an instance (possibly shared or independent) of the object 
  4.      * managed by this factory.
     
  5.      * <p>As with a {@link BeanFactory}, this allows support for both the 
  6.      * Singleton and Prototype design pattern. 
  7.      * <p>If this FactoryBean is not fully initialized yet at the time of 
  8.      * the call (for example because it is involved in a circular reference), 
  9.      * throw a corresponding {@link FactoryBeanNotInitializedException}.
     
  10.      * <p>As of Spring 2.0, FactoryBeans are allowed to return <code>null</code> 
  11.      * objects. The factory will consider this as normal value to be used; it 
  12.      * will not throw a FactoryBeanNotInitializedException in this case anymore. 
  13.      * FactoryBean implementations are encouraged to throw
     
  14.      * FactoryBeanNotInitializedException themselves now, as appropriate. 
  15.      * @return an instance of the bean (can be <code>null</code>) 
  16.      * @throws Exception in case of creation errors 
  17.      * @see FactoryBeanNotInitializedException 
  18.      */
  19.     T getObject() throws Exception;  

                 getObject這個方法,就是用來獲取被這個factorybean加強後的物件的,上一章測試的過程中,最終就是呼叫了這個方法,來完成了對bean的加強。我們來跟蹤一下上一次測試的程式碼,看看到底是在什麼地方呼叫的。這裡再次貼出來上次測試的程式碼,方便解釋。

  1. publicclass TestAOP {  
  2.     publicstaticvoid main(String[] args) {  
  3.         ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:beans.xml");  
  4.         TestTarget target = (TestTarget) applicationContext.getBean("testAOP");  
  5.         target.test();  
  6.         System.out.println("------無敵分割線-----");  
  7.         target.test2();  
  8.     }  
  9. }  
其實整個過程也就兩行程式碼,第一行程式碼,是我們對IOC容器的初始化,這時其實並沒有發生對bean的增強,原因就是這個時候只是完成了對ProxyFactoryBean的初始化,也就是相當於我們已經new出來了一個ProxyFactoryBean,但是此時並沒有呼叫介面方法,去獲得加強後的bean。

               下面我們去跟進第二行獲取testAOP的程式碼,來看一下究竟。首先我們會找到AbstractApplicationContext中的getBean方法,但是這個類並不負責bean的例項化工作,而是交給了bean工廠,我們跟蹤bean工廠的方法,能找到上述第二行其實是呼叫瞭如下這個方法。

  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.         final String beanName = transformedBeanName(name);  
  6.         Object bean;  
  7.         // Eagerly check singleton cache for manually registered singletons.
  8.         Object sharedInstance = getSingleton(beanName);  
  9.         if (sharedInstance != null && args == null) {  
  10.             if (logger.isDebugEnabled()) {  
  11.                 if (isSingletonCurrentlyInCreation(beanName)) {  
  12.                     logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +  
  13.                             "' that is not fully initialized yet - a consequence of a circular reference");  
  14.                 }  
  15.                 else {  
  16.                     logger.debug("Returning cached instance of singleton bean '" + beanName + "'");  
  17.                 }  
  18.             }  
  19.             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  
  20.         }  
  21.         else {  
  22.             // Fail if we're already creating this bean instance:
  23.             // We're assumably within a circular reference.
  24.             if (isPrototypeCurrentlyInCreation(beanName)) {  
  25.                 thrownew BeanCurrentlyInCreationException(beanName);  
  26.             }  
  27.             // Check if bean definition exists in this factory.
  28.             BeanFactory parentBeanFactory = getParentBeanFactory();  
  29.             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {  
  30.                 // Not found -> check parent.
  31.                 String nameToLookup = originalBeanName(name);  
  32.                 if (args != null) {  
  33.                     // Delegation to parent with explicit args.
  34.                     return (T) parentBeanFactory.getBean(nameToLookup, args);  
  35.                 }  
  36.                 else {  
  37.                     // No args -> delegate to standard getBean method.
  38.                     return parentBeanFactory.getBean(nameToLookup, requiredType);  
  39.                 }  
  40.             }  
  41.             if (!typeCheckOnly) {  
  42.                 markBeanAsCreated(beanName);  
  43.             }  
  44.             final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);  
  45.             checkMergedBeanDefinition(mbd, beanName, args);  
  46.             // Guarantee initialization of beans that the current bean depends on.
  47.             String[] dependsOn = mbd.getDependsOn();  
  48.             if (dependsOn != null) {  
  49.                 for (String dependsOnBean : dependsOn) {  
  50.                     getBean(dependsOnBean);  
  51.                     registerDependentBean(dependsOnBean, beanName);  
  52.                 }  
  53.             }  
  54.             // Create bean instance.
  55.             if (mbd.isSingleton()) {  
  56.                 sharedInstance = getSingleton(beanName, new ObjectFactory() {  
  57.                     public Object getObject() throws BeansException {  
  58.                         try {  
  59.                             return createBean(beanName, mbd, args);  
  60.                         }  
  61.                         catch (BeansException ex) {  
  62.                             // Explicitly remove instance from singleton cache: It might have been put there
  63.                             // eagerly by the creation process, to allow for circular reference resolution.
  64.                             // Also remove any beans that received a temporary reference to the bean.
  65.                             destroySingleton(beanName);  
  66.                             throw ex;  
  67.                         }  
  68.                     }  
  69.                 });  
  70.                 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);  
  71.             }  
  72.             elseif (mbd.isPrototype()) {  
  73.                 // It's a prototype -> create a new instance.
  74.                 Object prototypeInstance = null;  
  75.                 try {  
  76.                     beforePrototypeCreation(beanName);  
  77.                     prototypeInstance = createBean(beanName, mbd, args);  
  78.                 }  
  79.                 finally {  
  80.                     afterPrototypeCreation(beanName);  
  81.                 }  
  82.