美文网首页springboot
Spring 单例模式源码分析

Spring 单例模式源码分析

作者: 黄靠谱 | 来源:发表于2019-02-16 20:09 被阅读64次

    概述

    1. Spring 单例缓存实现原理:synchronized+双重判断。
    2. Spring 真正createBean的2种方式:反射 (未重写父类方法时)、CGLIB(重写了)

    单例模式抽象版

    java实现单例模式有多种方式:饿汉式、懒汉式等等,Spring 传统的BeanFactory采用的是懒汉式。通过双重校验+锁的方式实现单例模式
    实现的代码在AbstractBeanFactory.doGetBean()来实现的,简化后的代码如下

    public Object getSingotonByBeanName(String beanName){
        Object bean=getSingleton(String beanName, boolean allowEarlyReference) ;
        if(bean==null){
            synchronized (this.singletonObjects) {
                    //双重校验
                    Object singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        singletonObject = singletonFactory.createBean();
                        addSingleton(beanName, singletonObject);
                    }
                    return singletonObject;
                }
        }
    }
    

    单例模式源码分析

    核心方法通过AbstractBeanFactory实现的

    1. 最开始会做一个Eagerly check,如果是单例且已经缓存,后面就不用管了,直接返回单例
    2. 做完一些校验之后,再加锁(this.singletonObjects 这个对象),Double Check之后,再创建Bean,创建完之后缓存在singletonObjects里面
    3. 创建Bean的时候加了锁,addSingleton时候也重入了该锁

    AbstractBeanFactory.class

    protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) {
            // Eagerly check singleton cache for manually registered singletons.
            Object sharedInstance = getSingleton(beanName);
            ... 
            //各种检查之后,最后再来一次针对单例模式的getSingleton Check
            //通过加锁的方式,保证只有一个线程成功的创建bean
            if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                    @Override
                    public Object getObject() {return createBean(beanName, mbd, args);}});
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
    

    DefaultSingletonBeanRegistry.class

    //第一次 Eagerly check
    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);
        }
    
    // 保证线程安全的 加锁 -->doubleCheck --> create And buffer
    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) {
                    beforeSingletonCreation(beanName);
                        singletonObject = singletonFactory.getObject();
                        newSingleton = true;
                    
                    if (newSingleton) {
                        addSingleton(beanName, singletonObject);
                    }
                }
                return (singletonObject != NULL_OBJECT ? singletonObject : null);
            }
        }
    
    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
    

    真正创建Bean的两种方式

    org.springframework.beans.factory.support.SimpleInstantiationStrategy.class

    1. 如果未重写父类方法的类,则通过指定的构造器+构造函数的参数值,反射实例化对象, 默认是无参的构造函数反射,也可以在xml指定实例化的构造函数和参数值
    2. 如果重写父类的方法,则只能通过CGLIB的方式创建Bean
    public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
            // Don't override the class with CGLIB if no overrides.
            if (bd.getMethodOverrides().isEmpty()) {
                Constructor<?> constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
                return BeanUtils.instantiateClass(constructorToUse);
            }
            else {
                // Must generate CGLIB subclass.
                return instantiateWithMethodInjection(bd, beanName, owner);
            }
        }
    
    1. 反射的使用
    org.springframework.beans.BeanUtils.class
    public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
                ReflectionUtils.makeAccessible(ctor);
                return ctor.newInstance(args);
            }
    

    相关文章

      网友评论

        本文标题:Spring 单例模式源码分析

        本文链接:https://www.haomeiwen.com/subject/nlvieqtx.html