Spring中的设计模式-单例模式(转)
来源:互联网 发布:云软件架构 编辑:程序博客网 时间:2024/05/14 07:51
单例模式确保一个类在应用中只有一个实例。
我们以依赖注入创建bean实例为线索分析一下spring中单例模式。
Spring的依赖注入(包括lazy-init方式)都是发生在AbstractBeanFactory的getBean里。getBean的doGetBean方法调用getSingleton进行bean的创建。lazy-init方式,在容器初始化时候进行调用,非lazy-init方式,在用户向容器第一次索要bean时进行调用。
带同步的单例模式
下面是单例模式的核心代码。
- protected Object getSingleton(String beanName, boolean allowEarlyReference) {
- Object singletonObject = this.singletonObjects.get(beanName);
- if (singletonObject == null) {
- 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本身)
见如下代码:
8行创建bean实例返回给BeanWrapper
30行addSingletonFactory增加beanName和ObjectFactory的键值对应关系。
- protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
- // 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) {
- applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
- 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() {
- public Object getObject() throws BeansException {
- return getEarlyBeanReference(beanName, mbd, bean);
- }
- });
- }....
getEarlyBeanReference获取bean的所有后处理器,并进行处理。如果是SmartInstantiationAwareBeanPostProcessor类型,就进行处理,如果没有相关处理内容,就返回默认的实现。
- 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 exposedObject;
- }
- }
- }
- }
- return exposedObject;
- }
另外,在Spring的其他代码中也有使用的单例模式,如AOP的切点定义中。
公有静态成员,私有构造函数的单例模式。
- class TruePointcut implements Pointcut, Serializable {
- private static final TruePointcut INSTANCE = new TruePointcut();
- /**
- * Enforce Singleton pattern.
- */
- private TruePointcut() {
- }
- ....
- public static TruePointcut getInstance(){
- return INSTANCE;
- }
- }
上面的代码可以改成:静态工厂方法的单例模式
- class TruePointcut implements Pointcut, Serializable {
- private static final TruePointcut INSTANCE = new TruePointcut();
- /**
- * Enforce Singleton pattern.
- */
- private TruePointcut() {
- }
- ....
- public static TruePointcut getInstance(){
- return INSTANCE;
- }
- }
或者改成:用枚举实现单例模式
- enum TruePointcut implements Pointcut, Serializable {
- INSTANCE ;
- ...
- }
- Spring中的设计模式-单例模式(转)
- Spring中的设计模式-单例模式
- spring中的设计模式-单例模式
- spring下的bean单例模式与设计模式(GOF)中的单例模式区别
- spring下的bean单例模式与设计模式(GOF)中的单例模式区别
- spring下的bean单例模式与设计模式(GOF)中的单例模式区别
- 设计模式中的单例设计模式
- spring中的单例模式
- JAVA设计模式中的单例模式
- webkit 中的设计模式--单例模式
- 游戏中的设计模式:单例模式
- java 中的设计模式--单例模式
- 设计模式中的单例模式
- Android中的设计模式-单例模式
- 设计模式_C++中的单例模式
- OC中的设计模式-单例模式
- 设计模式中的单例模式&c++
- 设计模式中的单例模式
- 使用R进行逻辑回归 分类
- 如何定义自己的控件
- CSS3媒体查询media
- React Native-6.React Native Text组件,多组件封装实战之凤凰资讯页面
- Cheapest Palindrome
- Spring中的设计模式-单例模式(转)
- 看完这个,css中position的绝对定位相对定位就懂了
- Android Recipes笔记
- Android webview网页里输入框被输入法遮挡问题
- 官方详解/proc/net/tcp
- hibernate 普通字段延迟加载无效的解决办法
- Android 二维码扫码
- Android APP 上架流程
- Http、TCP/IP协议与Socket的区别