项目中我需要根据登陆用户动态修改Spring的数据源配置,即通过实现ApplicationContextAware接口来获取ApplicationContext,并将用户对应的数据源bean覆盖这个ApplicationContext的数据源bean。在多线程的情况下,是否会发生同步问题?Spring是否做到了每个线程持有独立的一份ApplicationContext,或者说我通过实现ApplicationContextAware而获得的ApplicationContext是否经过了ThreadLocal的封装优化?

解决方案 »

  1.   

    spring-bean-3.06
    AbstractBeanFactory.class@SuppressWarnings("unchecked")
    protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {
        final String beanName = transformedBeanName(name);
        Object bean;    // Eagerly check singleton cache for manually registered singletons.
        Object sharedInstance = getSingleton(beanName);
        // 以下省略}protected Object getSingleton(String beanName, boolean allowEarlyReference) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                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);
        }单例
      

  2.   


        protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {
            if (factory.isSingleton() && containsSingleton(beanName)) {
                synchronized (getSingletonMutex()) {
                    Object object = this.factoryBeanObjectCache.get(beanName);
                    if (object == null) {
                        object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
                        this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
                    }
                    return (object != NULL_OBJECT ? object : null);
                }
            }
            else {
                return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
            }
        }