package cn.noexception.container.factory.support; import cn.noexception.container.BeansException; import cn.noexception.container.factory.DisposableBean; import cn.noexception.container.factory.ObjectFactory; import cn.noexception.container.factory.config.SingletonBeanRegistry; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** * DefaultSingletonBeanRegistry * * @author 吕滔 * @Date 2021/10/22 17:35 */ public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry { // 一级缓存,存放普通对象 private Map singletonObjects = new ConcurrentHashMap<>(); // 二级缓存,提前暴露对象,即没有完全实例化的对象 protected final Map earlySingletonObjects = new HashMap<>(); // 三级缓存,存放代理对象 private final Map> singletonFactories = new HashMap<>(); /** * Internal marker for a null singleton object: * used as marker value for concurrent Maps (which don't support null values). */ protected static final Object NULL_OBJECT = new Object(); private final Map disposableBeans = new HashMap<>(); @Override public Object getSingleton(String beanName) { Object singletonObject = singletonObjects.get(beanName); if (null == singletonObject) { singletonObject = earlySingletonObjects.get(beanName); // 判断二级缓存中是否有对象,这个对象就是代理对象,因为只有代理对象才会放到三级缓存中 if (null == singletonObject) { ObjectFactory singletonFactory = singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); // 把三级缓存中的代理对象的真是对象获取出来,放入二级缓存中 earlySingletonObjects.put(beanName, singletonObject); singletonFactories.remove(beanName); } } } return singletonObject; } @Override public void registerSingleton(String beanName, Object singletonObject) { singletonObjects.put(beanName, singletonObject); earlySingletonObjects.remove(beanName); singletonFactories.remove(beanName); } protected void addSingletonFactory(String beanName, ObjectFactory singletonFactory) { if (!this.singletonObjects.containsKey(beanName)) { this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); } } public void registerDisposableBean(String beanName, DisposableBean bean) { disposableBeans.put(beanName, bean); } public void destroySingletons() { Set keySet = this.disposableBeans.keySet(); Object[] disposableBeanNames = keySet.toArray(); for (int i = disposableBeanNames.length - 1; i >= 0; i--) { Object beanName = disposableBeanNames[i]; DisposableBean disposableBean = disposableBeans.remove(beanName); try { disposableBean.destroy(); } catch (Exception e) { throw new BeansException("Destroy method on bean with name '" + beanName + "' threw an exception", e); } } } }