Spring 单例模式源码分析

概述

  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 doGetBean(final String name, final Class 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() {
                @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 instantiateClass(Constructor ctor, Object... args) throws BeanInstantiationException {
            ReflectionUtils.makeAccessible(ctor);
            return ctor.newInstance(args);
        }

你可能感兴趣的:(Spring 单例模式源码分析)