Spring单例模式

Spring单例模式的核心使用注册表实现。如下:


	/** Cache of singleton objects: bean name --> bean instance */
	/** 已经在缓存里的单例对象实例,使用ConcurrentHashMap存储。 */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name --> ObjectFactory */
	/** 已经在缓存里的单例对象工厂 */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name --> bean instance */
	/** 用于解析循环引用 */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

	/** Set of registered singletons, containing the bean names in registration order */
	/** 当前已经注册的单例对象实例的name的集合 */
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
	
	/** Names of beans that are currently in creation */
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	/** Names of beans currently excluded from in creation checks */
	private final Set<String> inCreationCheckExclusions =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	/** List of suppressed Exceptions, available for associating related causes */
	@Nullable
	private Set<Exception> suppressedExceptions;

	/** Flag that indicates whether we're currently within destroySingletons */
	private boolean singletonsCurrentlyInDestruction = false;

	/** Disposable bean instances: bean name --> disposable instance */
	private final Map<String, Object> disposableBeans = new LinkedHashMap<>();

	/** Map between containing bean names: bean name --> Set of bean names that the bean contains */
	/** bean的所有name,key是id,value是别名的集合 */
	private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);

	/** Map between dependent bean names: bean name --> Set of dependent bean names */
	/** bean的依赖关系相关 */
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

	/** Map between depending bean names: bean name --> Set of bean names for the bean's dependencies */
	/** bean的依赖关系相关 */
	private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

注册单例的方法:

	@Override
	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
		Assert.notNull(beanName, "Bean name must not be null");
		Assert.notNull(singletonObject, "Singleton object must not be null");
		synchronized (this.singletonObjects) {
			Object oldObject = this.singletonObjects.get(beanName);
			if (oldObject != null) {
				throw new IllegalStateException("Could not register object [" + singletonObject +
						"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
			}
			addSingleton(beanName, singletonObject);
		}
	}
	
	/**
	 * Add the given singleton factory for building the specified singleton
	 * if necessary.
	 * <p>To be called for eager registration of singletons, e.g. to be able to
	 * resolve circular references.
	 * @param beanName the name of the bean
	 * @param singletonFactory the factory for the singleton object
	 */
	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}

Spring有四种注入Bean的方式,分别是Setter方法注入,构造器方法注入,静态工厂注入,实例工厂注入。

可以看见,Spring使用ConcurrentHashMap来储存注入的单例对象实例,key是bean的id,value是object实例,ConcurrentHashMap使用分段锁来保证并发安全,同时,在注册单例对象的时候还获取了singletonObjects (即整个ConcurrentHashMap对象实例) 的锁,确保不会重复注册同一个bean id的单例对象。同时根据上面的代码我们也可以看出synchronized 获取的锁是可重入锁

详情应该看Spring的DefaultSingletonBeanRegistry.java源代码。

上一篇:5.2 spring5源码--spring AOP源码分析三---切面源码分析


下一篇:【Spring】重复的beanName覆盖原则(九)