Spring IoC 中的(Singleton)單例物件建立過程探索

丶Pz發表於2018-05-03

前言

  之前將spring framework 原始碼匯入了idea,後來折騰除錯了一下,於是研究了一下最簡單的singleton物件在spring中是如何建立的。這裡所謂的簡單,就是指無屬性注入,無複雜建構函式的物件。

測試程式碼

  spring配置:

  <bean id="userService" class="UserService" scope="singleton"></bean>
  測試類:
public class UserService {

   private final Log logger = LogFactory.getLog(getClass());

    public UserService(){
        logger.info("UserService created");
        id = UUID.randomUUID().toString();
    }

    private String id;
    public String getId(){
        return id;
    }
    public String getUserName(){
        return "xiaopanzi";
    }
}

  

 public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        context.start();
        testNormalSingleton(context);
    }

    private static void testCircleSingleton(ClassPathXmlApplicationContext context){
        SingletonAService aService = context.getBean("aService",SingletonAService.class);
        SingletonBService bService = context.getBean("bService",SingletonBService.class);

        aService.getbService().print();

        bService.getaService().print();
    }

除錯詳情

  首先在ApplicationContext 初始化過程,在 refresh 方法中會呼叫  finishBeanFactoryInitialization 方法,註釋上也寫的很明白:Instantiate all remaining (not-lazy-init) signletons。(初始化剩餘的非懶載入的單例物件)。那麼這裡就是入口點。

  然後在呼叫 beanFactory.preInstantiateSingletons().

  後續呼叫鏈如下:

  DefaultListBeanFactory.getBean(beanName)

  AbstractBeanFactory.doGetBean(name,requiredType,args,typeCheckOnly)

  AbstractAutowireCapableBeanFactory.createBean(String beanName,RootBeanDefinition mbd,Object[] args)

       AbstractAutowireCapableBeanFactory.doCreateBean(String beanName,RootBeanDefinition mbd,Object[] args)

       AbstractAutowireCapableBeanFactory.instantiateBean(final String beanName, final RootBeanDefinition mbd)

       getInstantiationStrategy().instantiate(mbd, beanName, parent); (this.instantiationStrategy=CglibSubclassingInstantiationStrategy)

 

    SimpleInstantiationStrategy.instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) 

  BeanUtils.instantiateClass(Constructor<T> ctor, Object... args)

 

  通過上述程式碼呼叫鏈我們可以看出,最終的示例建立是由 BeanUtils.instantiateClass 方法完成的,也就是這個方法:

   

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
		Assert.notNull(ctor, "Constructor must not be null");
		try {
			ReflectionUtils.makeAccessible(ctor);
			return ctor.newInstance(args);
		}
		catch (InstantiationException ex) {
			throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
		}
		catch (IllegalAccessException ex) {
			throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
		}
		catch (IllegalArgumentException ex) {
			throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
		}
		catch (InvocationTargetException ex) {
			throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
		}
	}

  到此為止單例就建立完畢了。但是建立完成之後,還有後續的處理。

   DefaultSingletonBeanRegistry.addSingletonFactory(String beanName,ObjectFactory<?> singletonFactory);

  也就是將該示例放入到  singletonObjects 中,作為快取方便後續取值。

  this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));

  當我們在次呼叫getBean的時候,那麼在 DefaultSingletonBeanRegistry.getSingleton 方法中直接從 singletonObjects 中獲取即可。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return (singletonObject != NULL_OBJECT ? singletonObject : null);
	}

  

總結

  上述內容記錄的很少,基本就是一個輪廓的記錄,要真正理解詳情內容,還得自己去慢慢除錯啊!!!

  

 

  


  

相關文章