Spring获取单例getSingleton(1)

简介: 标签: spring源码学习spring获取单例首先是从缓存去找,如果找不到就要从头开始bean的加载过程,spring中主要通过getSingleton的重载方法实现单例bean的加载过程要创建一个bean的单例,首先了解下单例是什么样子的, public static synchronized Singleton getInstance() {

标签: 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说起。

目录
相关文章
|
6月前
|
缓存 算法 安全
Spring 为啥默认把bean设计成单例的?这篇讲的明明白白的
Spring 为啥默认把bean设计成单例的?这篇讲的明明白白的
92 0
|
XML Java 数据格式
Spring之bean单例与多例
Spring之bean单例与多例
143 0
|
XML Java 数据格式
【Spring】Bean的生命周期与单例实现(二)
【Spring】Bean的生命周期与单例实现(二)
88 1
|
XML Java 数据格式
【Spring】Bean的生命周期与单例实现(一)
【Spring】Bean的生命周期与单例实现
81 1
|
XML Java 数据格式
Spring系列(三)之Bean的生命周期以及Bean的单例与多例模式
Spring系列(三)之Bean的生命周期以及Bean的单例与多例模式
|
XML 安全 Java
Spring框架中的单例bean是线程安全的吗?阿里一面
在 Spring 框架中,Bean 是指由 Spring IoC(Inversion of Control)容器管理的组件或对象。Bean 是 Spring 中最基本的构建块,它们由 Spring 容器实例化、组装和管理。
104 0
|
6月前
|
安全 Java Spring
Spring框架中的单例Bean是线程安全的吗?
Spring框架中的单例Bean是线程安全的吗?
79 1
|
3月前
|
安全 Java C#
Spring创建的单例对象,存在线程安全问题吗?
Spring框架提供了多种Bean作用域,包括单例(Singleton)、原型(Prototype)、请求(Request)、会话(Session)、全局会话(GlobalSession)等。单例是默认作用域,保证每个Spring容器中只有一个Bean实例;原型作用域则每次请求都会创建一个新的Bean实例;请求和会话作用域分别与HTTP请求和会话绑定,在Web应用中有效。 单例Bean在多线程环境中可能面临线程安全问题,Spring容器虽然确保Bean的创建过程是线程安全的,但Bean的使用安全性需开发者自行保证。保持Bean无状态是最简单的线程安全策略;
|
5月前
|
Java Spring 容器
解读spring5源码中实例化单例bean的调用链
解读spring5源码中实例化单例bean的调用链
|
5月前
|
安全 Java Spring
spring的controller是单例还是多例,怎么保证并发的安全
spring的controller是单例还是多例,怎么保证并发的安全
44 0