由Spring框架中的单例模式想到的
来源:互联网 发布:阿里云备案要多长时间 编辑:程序博客网 时间:2024/05/16 03:53
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例
注:Spring源码的版本4.3.4
Spring
依赖注入Bean
实例默认是单例的,我们由此展开。
Spring
的依赖注入(包括lazy-init方式)都是发生在AbstractBeanFactory
的getBean
里。getBean的doGetBean
方法调用getSingleton
进行bean
的创建。lazy-init方式,在容器初始化时候进行调用,非lazy-init方式,在用户向容器第一次索要bean
时进行调用
同步线程安全的单例核心代码:
/** * Return the (raw) singleton object registered under the given name. * <p>Checks already instantiated singletons and also allows for an early * reference to a currently created singleton (resolving a circular reference). * @param beanName the name of the bean to look for * @param allowEarlyReference whether early references should be created or not * @return the registered singleton object, or {@code null} if none found */ 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); }
从上面代码可以看到,spring依赖注入时,使用了双重判断加锁的单例模式,首先从缓存中获取bean实例,如果为null,对缓存map加锁,然后再从缓存中获取bean,如果继续为null,就创建一个bean。这样双重判断,能够避免在加锁的瞬间,有其他依赖注入引发bean实例的创建,从而造成重复创建的结果。
在这里Spring并没有使用私有构造方法来创建bean,而是通过singletonFactory.getObject()
返回具体beanName
对应的ObjectFactory
来创建bean。我们一路跟踪下去,发现实际上是调用了AbstractAutowireCapableBeanFactory
的doCreateBean
方法,返回了BeanWrapper
包装并创建的bean实例。
(ObjectFactory
主要检查是否有用户定义的BeanPostProcessor
后处理内容,并在创建bean时进行处理,如果没有,就直接返回bean本身)
见如下代码:
534行创建bean实例返回给BeanWrapper
563行addSingletonFactory
增加beanName
和ObjectFactory
的键值对应关系。
/** * Actually create the specified bean. Pre-creation processing has already happened * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks. * <p>Differentiates between default bean instantiation, use of a * factory method, and autowiring a constructor. * @param beanName the name of the bean * @param mbd the merged bean definition for the bean * @param args explicit arguments to use for constructor or factory method invocation * @return a new instance of the bean * @throws BeanCreationException if the bean could not be created * @see #instantiateBean * @see #instantiateUsingFactoryMethod * @see #autowireConstructor */ protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); }
getEarlyBeanReference
获取bean的所有后处理器,并进行处理。如果是SmartInstantiationAwareBeanPostProcessor
类型,就进行处理,如果没有相关处理内容,就返回默认的实现。
/** * Obtain a reference for early access to the specified bean, * typically for the purpose of resolving a circular reference. * @param beanName the name of the bean (for error handling purposes) * @param mbd the merged bean definition for the bean * @param bean the raw bean instance * @return the object to expose as bean reference */ protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); if (exposedObject == null) { return null; } } } } return exposedObject; }
原地址:http://www.cnblogs.com/chengxuyuanzhilu/p/6404991.html
- 由Spring框架中的单例模式想到的
- Spring框架中的单例模式(源码解读)
- 框架中的单例模式
- 由GFS中的一个改进想到的
- 由ActiveX DLL中的全局变量想到的...
- 由chrome源码中的arraysize想到的
- 由chrome源码中的arraysize想到的
- spring中的单例模式
- [Spring]反思spring:由Ruby on Rails想到的
- Spring中的设计模式-单例模式
- spring中的设计模式-单例模式
- spring下的bean单例模式与设计模式(GOF)中的单例模式区别
- spring下的bean单例模式与设计模式(GOF)中的单例模式区别
- spring下的bean单例模式与设计模式(GOF)中的单例模式区别
- 由本子想到的
- 由忧郁想到的
- 由电车男想到的
- 由MBV想到的
- Spark RDD常用的函数
- Spring Cache抽象详解
- SQL查询--列出受雇日期早于直接上级的所有员工
- [论文选读]Google News Personalization: Scalable Online Collaborative Filtering
- 管理Sass项目文件结构
- 由Spring框架中的单例模式想到的
- Linux菜鸟教程(一 :JDK安装和java环境的配置)
- Jsp的入门
- android计算器开发
- jQuery插件之ajaxFileUpload
- JAVA快速排序
- Bean Validation 规范
- eclipse导出Jar包选项
- 谈android组件化之ARouter简单使用