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源代码。