Spring获取单例getSingleton(1)

标签: spring源码学习



spring获取单例首先是从缓存去找,如果找不到就要从头开始bean的加载过程,spring中主要通过getSingleton的重载方法实现单例bean的加载过程

要创建一个bean的单例,首先了解下单例是什么样子的,

    public static synchronized Singleton getInstance() {
             if (single == null) {
                 single = new Singleton();
             }
            return single;
    }  

spring创建单例bean主要查看 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry类的getSingleton(String beanName, ObjectFactory

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "'beanName' must not be null");
        //同步 开始创建单例
        synchronized (this.singletonObjects) {
            Object singletonObject = this.singletonObjects.get(beanName);
            //判断单例是否被创建 如果已经创建则不在重复创建
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                            "Singleton bean creation not allowed while the singletons of this factory are in destruction " +
                            "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
                //把当前正在创建的bean记录在缓存中,对循环依赖进行检测
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<Exception>();
                }
                try {
                //使用回调方法 创建单例bean
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                catch (IllegalStateException ex) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw ex;
                    }
                }
                catch (BeanCreationException ex) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    //移除缓存中对该bean正在加载的状态
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    //将新创建的bean加入缓存,并且删除加载bean过程中所记录的各种辅助状态
                    //这些辅助状态主要是在回调方法创建bean时候引入的
                    addSingleton(beanName, singletonObject);
                }
            }
            return (singletonObject != NULL_OBJECT ? singletonObject : null);
        }
    }

现在继续去找创建bean的回调方法

sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                            //创建bean的核心实现又调用了createBean方法
                                return createBean(beanName, mbd, args);
                            }
                            catch (BeansException ex) {
                                destroySingleton(beanName);
                                throw ex;
                            }
                        }
                    });
                //创建完的beanInstance还不一定不是我们最终需要的bean 还需要加工验证正确性
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

createBean方法里面还是在做一些准备工作,真正的创建bean交给了doCreateBean

@Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;

        //根据指定的BeanDefinition信息 解析bean class 并且存储在BeanDefinition中
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        //对已有的bean definition进行克隆 以防一动态解析的class不能存储在合并的bean definition中
        //这里说的动态解析的class是指在bean class的定义中使用EL表达式或者自己定义的beanExpressionResolver
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null){
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }
        try {
        //验证及准备覆盖的方法
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }
        try {
        //给beanPostProcessors一个机会返回代理来替代真正的实例
        //这里的beanPostProcessors是指InstantiationAwareBeanPostProcessor类型
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }
        //创建bean的过程又交给了doCreateBean,spring中以doxxx开头的方法就是真正干活的方法
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isDebugEnabled()) {
            logger.debug("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }

在这里首先关注下AbstractBeanDefinition类的prepareMethodOverrides方法

    public void prepareMethodOverrides() throws BeanDefinitionValidationException {
        // Check that lookup methods exists.
        MethodOverrides methodOverrides = getMethodOverrides();
        if (!methodOverrides.isEmpty()) {
            for (MethodOverride mo : methodOverrides.getOverrides()) {
                prepareMethodOverride(mo);
            }
        }
    }
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
        int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
        if (count == 0) {
            throw new BeanDefinitionValidationException(
                    "Invalid method override: no method with name '" + mo.getMethodName() +
                    "' on class [" + getBeanClassName() + "]");
        }
        else if (count == 1) {
            // Mark override as not overloaded, to avoid the overhead of arg type checking.
            mo.setOverloaded(false);
        }
    }

spring配置中存在lookup-method和replace-method两个配置功能,这两个配置的加载就是将配置存储在BeanDefinition中的methodOverrides属性里面。功能的实现原理是在bean的实例化的时候如果检测到存在methodOverrides属性,会动态的为当前bean生成代理并使用对应的拦截器为bean做增强处理。

下一篇继续从doCreateBean说起。

时间: 2024-10-23 16:21:52

Spring获取单例getSingleton(1)的相关文章

java的单例、static修饰符及static的继承

单例设计模型: static修饰符: ①:static静态只有一份(同一个虚拟机中) (节省资源),类代码被装载内存时,静态代码分配内存,并执行,并且常驻内存. 可参考:类加载顺序 ②:Static修饰成员变量,成为"类变量",属于整个类,类的共享变量.注:不能修饰局部变量.          static是一块为整个类共有一块存储区域,静态变量只有一份,值变化后,所有访问值变化生效.          java中用类名调用static变量和方法(对象调用也可以):类名.变量(方法名)

【秒懂设计模式】单例设计模式

 秒懂设计模式--单例设计模式 (三)单例设计模式 1.先解释一下,什么是单例模式呢? 在Java中是这样定义的:"一个类有且仅有一个实例,并且自行实例化向整个系统提供." 显然从单例模式的定义中,我们可以发现它有三个要点: ①某个类只能有一个实例: ②它必须自行创建这个实例: ③它必须自行向整个系统提供这个实例. 2.要满足这三个要点,应该如何实现呢?下面让我们来逐条分析: ①如何保证某个类只能有一个实例? 让我先来想一下,一个类的对象是如何创建的呢?答案是:一个类的对象的产生是由类

ios中的线程安全单例实现

我们这里重点讨论的是线程安全,而不是单例的严格实现(若需要严格实现还需要复写一些方法,更改一些实现代码): gcd实现:   static AccountManager *sharedAccountManagerInstance = nil;  + (AccountManager *)sharedManager {      static dispatch_once_t predicate; dispatch_once(&predicate, ^{                  shared

JavaScript编程的单例设计模讲解_基础知识

在Javascript中,单例模式是一种最基本又经常用到的设计模式,可能在不经意间就用到了单例模式. 本文将从最基础的理论开始,讲述单例模式的基本概念和实现,最后用一个例子来讲述单例模式的应用. 理论基础 概念 单例模式,顾名思义就是只有一个实例存在.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源.如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案. 基本结构 最简单的单例模式起始就是一个对象字面量,它将有关联的属性和方

【Spring实战】—— 3 使用facotry-method创建单例Bean总结

如果有这样的需求: 1 不想再bean.xml加载的时候实例化bean,而是想把加载bean.xml与实例化对象分离. 2 实现单例的bean 以上的情况,都可以通过工厂方法factory-method来创建bean. 这样再加载bean.xml时,不会直接实例化bean,而是当调用factory-method所指的方法时,才开始真正的实例化. 首先看一下传统的单例模式的实现方式: 1 最原始的实现单例模式的方法(存在线程不安全): public class SingletonOne { pri

Spring中单例bean访问非单例bean的第一种方式:方法注入

方法注入在Spring中是很少用的,主要应用是, 对象中可能定义了一个受保 护的抽象方法,而容器可能在运行时实现他以返回由容器查询得到的对象. 方法注入的最好用途之一就是处理单态.无状态对象需要调用非单态.有状 态或者非线程安全对象的情况. 以前刚接触Spring时,如果在单例bean中调用非单例bean,只要把那个非单 例bean 的singleton设置为false就可以了.其实不然,大家想,我们创建了一 个单例对象,在此单例对象中所用到的其它bean也只会创建一次--(大多数情 况是这样的

spring-请教Spring如何清楚单例bean的缓存

问题描述 请教Spring如何清楚单例bean的缓存 我有两个WEB工程使用了同一个名字的bean,在运行第二个工程的时候报错,错误是在第一个工程里的同名bean的函数里,控制台里有下面这句话 :- Returning cached instance of singleton bean 'itemController' 请问这个缓存怎么才能删除!! 我在把tomcat下的work目录里的localhost删掉又重启了服务器,但是这个缓存还是存在,请高手指点以下吧,谢谢了!! 解决方案 Sprin

spring管理struts2对象,管理成单例对象纠结的问题

问题描述 需求:1>为了满足性能测试需求,不能用struts2原有的多例对象,必须单例对象2>用spring管理struts2对象,而且要单例我就纠结了,不管spring 怎么管理struts2对象都行,非要单例.单例对象怎么能满足大并发量请求的问题?难道spring容器会造struts2对象的副本,有spring容易自动管理内存?从性能测试角度,是单例的好,很省内存.但从大并发请求考虑,我还是觉得struts2原有的方式不错. 解决方案 Spring 自动默认并且推荐也是单例!引用难道spr

请求-spring mvc service单例问题

问题描述 spring mvc service单例问题 spring mvc 的项目,controller的注解@Scope("session"),是会话级别的.对于每一个用户请求都会产生实例,这没有问题.那我controller中通过@Autowired注入的service,它现在也是会话级别的?还是仍然是单例的?即:每个用户的请求都会产生一个controller实例,那service的实例是产生一个还是多个呢?谢谢. 解决方案 service的实例在项目启动进行初始的时候已经生成了