zoukankan      html  css  js  c++  java
  • spring(四):DI流程

    在IoC容器初始化过程中,一般不包含Bean依赖注入的实现。

    依赖注入一般发生在应用第一次向容器获取Bean时(getBean),但是有一个例外。

    在使用IoC容器时有一个预实例化的配置,即通过lazy-init属性控制Bean的实例化(依赖注入)时机。

    一般情况

    // <<AbstractBeanFactory>>    
    	public Object getBean(String name) throws BeansException {
            return this.doGetBean(name, (Class)null, (Object[])null, false);
        }
    
        protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
            String beanName = this.transformedBeanName(name);
            // 首先检查是否存在缓存的singleton bean,对于已经存在的不需要重复创建
            Object sharedInstance = this.getSingleton(beanName);
            Object bean;
            if (sharedInstance != null && args == null) {
                ...
                bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
            } else {
                // 如果bean正在创建中则获取失败
                if (this.isPrototypeCurrentlyInCreation(beanName)) {
                    throw new BeanCurrentlyInCreationException(beanName);
                }
    			// 检查当前BeanFactory中是否存在以beanName为名的BeanDefinition
                // 如果当前BeanFactory中没有,则会顺着其父BeanFactory查找
                BeanFactory parentBeanFactory = this.getParentBeanFactory();
                // 这里的containsBeanDefinition是一个模板方法,由DefaultListableBeanFactory实现
                // 即在存储BeanDefinition的Map中查找是否存在
                if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
                    String nameToLookup = this.originalBeanName(name);
                    if (parentBeanFactory instanceof AbstractBeanFactory) {
                        return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                    }
                    if (args != null) {
                        return parentBeanFactory.getBean(nameToLookup, args);
                    }
                    if (requiredType != null) {
                        return parentBeanFactory.getBean(nameToLookup, requiredType);
                    }
                    return parentBeanFactory.getBean(nameToLookup);
                }
    			// 父BeanFactory为null,或者当前存在以beanName为名的BeanDefinition时
                ...
                try {
                    // 根据beanName获取BeanFactory中的BeanDefinition
                    // 这里的RootBeanDefinition代表着在继承关系下创建的BeanDefinition
                    RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                    this.checkMergedBeanDefinition(mbd, beanName, args);
                    // 获得当前Bean依赖的所有Bean,通过 depends-on="xxx" 属性指定
                    // 表示初始化当前Bean需要先初始化其依赖的xxx
                    String[] dependsOn = mbd.getDependsOn();
                    String[] var11;
                    if (dependsOn != null) {
                        var11 = dependsOn;
                        int var12 = dependsOn.length;
    
                        for(int var13 = 0; var13 < var12; ++var13) {
                            String dep = var11[var13];
                            if (this.isDependent(beanName, dep)) {
                                ...	// throws "Circular depends-on relationship "
                            }
                            this.registerDependentBean(dep, beanName);
                            try {
                                // 递归,直到取到没有depends-on的Bean
                                this.getBean(dep);
                            } catch (NoSuchBeanDefinitionException var24) {
                                ...
                            }
                        }
                    }
    
                    // 创建bean实例
                    if (mbd.isSingleton()) {	// 创建singleton作用域Bean实例
                        sharedInstance = this.getSingleton(beanName, () -> {
                            try {
                                // 进行 doCreateBean 方法,★
                                return this.createBean(beanName, mbd, args);
                            } catch (BeansException var5) {
                                this.destroySingleton(beanName);
                                throw var5;
                            }
                        });
                        bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                    } else if (mbd.isPrototype()) {	// 创建prototype作用域Bean实例
                        var11 = null;
                        Object prototypeInstance;
                        try {
                            this.beforePrototypeCreation(beanName);
                            prototypeInstance = this.createBean(beanName, mbd, args);
                        } finally {
                            this.afterPrototypeCreation(beanName);
                        }
                        bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                    } else {	// 创建其他作用域Bean:request、session、global session
                        String scopeName = mbd.getScope();
                        Scope scope = (Scope)this.scopes.get(scopeName);
                        if (scope == null) {
                            ...
                        }
                        try {
                            Object scopedInstance = scope.get(beanName, () -> {
                                this.beforePrototypeCreation(beanName);
                                Object var4;
                                try {
                                    var4 = this.createBean(beanName, mbd, args);
                                } finally {
                                    this.afterPrototypeCreation(beanName);
                                }
                                return var4;
                            });
                            bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                        }...
                    }
                }...
            }
    
            // 类型检查
            if (requiredType != null && !requiredType.isInstance(bean)) {
                try {
                    // 类型转换
                    T convertedBean = this.getTypeConverter().convertIfNecessary(bean, requiredType);
                    if (convertedBean == null) {
                        ...
                    } else {
                        // 返回类型转换后的bean实例
                        return convertedBean;
                    }
                }...
            } else {
                return bean;
            }
        }
    
    // <AbstractAutowireCapableBeanFactory>
    	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
            ...logger
            // 根据class属性或className解析beanClass
            RootBeanDefinition mbdToUse = mbd;
            Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
            if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
                mbdToUse = new RootBeanDefinition(mbd);
                mbdToUse.setBeanClass(resolvedClass);
            }
    
            // 对override属性(lookup-method、replace-method)进行处理
            // 会检测当前beanDefinition的class中是否是否包含相应方法,
            // 并将override方法标记为覆盖,防止进行重载参数检查
            try {
                mbdToUse.prepareMethodOverrides();
            }...
    
            Object beanInstance;
            try {
                // 调用InstantiationAwareBeanPostProcessor
                // 允许在实例化前后进行处理
                // 如果返回值不为空,表示配置了InstantiationAwareBeanPostProcessor,并且修改了bean
                // 则返回一个代理,而不是bean实例
                beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
                if (beanInstance != null) {
                    return beanInstance;
                }
            }...
    
            try {
                // ★
                beanInstance = this.doCreateBean(beanName, mbdToUse, args);
                ...
                return beanInstance;
            }...
        }
    
    	// 真正开始创建bean
        protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
            BeanWrapper instanceWrapper = null;
            // 如果是单例bean,则先清除缓存同名缓存
            if (mbd.isSingleton()) {
                instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
            }
    		// 创建bean实例★
            if (instanceWrapper == null) {
                instanceWrapper = this.createBeanInstance(beanName, mbd, args);
            }
    
            Object bean = instanceWrapper.getWrappedInstance();
            Class<?> beanType = instanceWrapper.getWrappedClass();
            if (beanType != NullBean.class) {
                mbd.resolvedTargetType = beanType;
            }
    		// 通过post-processors合并继承关系下的beanDefinition
            synchronized(mbd.postProcessingLock) {
                if (!mbd.postProcessed) {
                    try {
                        this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                    }...
                    mbd.postProcessed = true;
                }
            }
    		// 提前曝光bean(利用缓存),用于支持循环bean的循环依赖
            boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
            if (earlySingletonExposure) {
                ...
                // 通过匿名内部类添加单例工厂到缓存
                this.addSingletonFactory(beanName, () -> {
                    return this.getEarlyBeanReference(beanName, mbd, bean);
                });
            }
    		// 初始化bean
            Object exposedObject = bean;
    
            try {
                // 这里开始进行依赖注入★
                this.populateBean(beanName, mbd, instanceWrapper);
                // 【初始化bean】:
                // applyBeanPostProcessorsBeforeInitialization【后置处理器】
                // invokeInitMethods:执行init-method
                // applyBeanPostProcessorsAfterInitialization【后置处理器】
                exposedObject = this.initializeBean(beanName, exposedObject, mbd);
            } catch (Throwable var18) {
                if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                    throw (BeanCreationException)var18;
                }...
    		 // 检查在提前曝光时,注入的bean是否为最终版本
            if (earlySingletonExposure) {
                Object earlySingletonReference = this.getSingleton(beanName, false);
                if (earlySingletonReference != null) {
                    if (exposedObject == bean) {
                        exposedObject = earlySingletonReference;
                    } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                        String[] dependentBeans = this.getDependentBeans(beanName);
                        Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                        String[] var12 = dependentBeans;
                        int var13 = dependentBeans.length;
    
                        for(int var14 = 0; var14 < var13; ++var14) {
                            String dependentBean = var12[var14];
                            if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                                actualDependentBeans.add(dependentBean);
                            }
                        }
    
                        if (!actualDependentBeans.isEmpty()) {
                            ...
                        }
                    }
                }
            }
    		// 给Bean注册一些必要的销毁操作,当容器shutdown时执行
            try {
                this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
                // 返回Bean实例,这里已经完成了依赖注入
                return exposedObject;
            }...
        }
         
    ---开始bean的实例化---
    
        protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
            // 确保Bean类可以实例化
            Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
            if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
                ...
            } else {
                // 5.0的新特性
            	// doc注释:用作创建Bean的回调,设置该回调后会覆盖掉创建Bean的工厂方法和构造函数,
            	// 但不影响依赖注入过程
                Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
                if (instanceSupplier != null) {
                    return this.obtainFromSupplier(instanceSupplier, beanName);
                } else if (mbd.getFactoryMethodName() != null) {	// 使用工厂方法实例化Bean
                    return this.instantiateUsingFactoryMethod(beanName, mbd, args);
                } else {
                    // 创建Bean时需要根据beanClass解析构造方法,并缓存在RootBeanDefinition中
            	    // 这里通过缓存直接进行处理,在创建相同Bean时不需要重复解析构造方法
                    boolean resolved = false;
                    boolean autowireNecessary = false;
                    if (args == null) {
                        synchronized(mbd.constructorArgumentLock) {
                            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                                resolved = true;
                                autowireNecessary = mbd.constructorArgumentsResolved;
                            }
                        }
                    }
    			   // 已解析构造方法
                    if (resolved) {
                        return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd);
                    } else {
                        // 使用构造函数实例化Bean
                        Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
                        if (ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args)) {
                            ctors = mbd.getPreferredConstructors();
                            // 1 有参构造函数
                            // 2 默认构造函数:instantiateBean()通过getInstantiationStrategy().instantiate(mbd, beanName, this)
                            // 这里的策略是SimpleInstantiationStrategy
                            return ctors != null ? this.autowireConstructor(beanName, mbd, ctors, (Object[])null) : this.instantiateBean(beanName, mbd);
                        } else {
                            return this.autowireConstructor(beanName, mbd, ctors, args);
                        }
                    }
                }
            }
        }
    
    // SimpleInstantiationStrategy
        // 这里共有两种方式创建Bean:
        // 其一,通过JVM反射;BeanUtils.instantiateClass(constructorToUse, new Object[0]);
        // 其二,通过cgLib的动态代理机制;this.instantiateWithMethodInjection(bd, beanName, owner);<<CglibSubclassingInstantiationStrategy>>
    
    ---结束bean的实例化---
    
        // 对bean属性包括依赖关系的处理,依据是BeanDefinition
        protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
            if (bw == null) {
                if (mbd.hasPropertyValues()) {
                    ...
                }
            } else {
                // 交由InstantiationAwareBeanPostProcessors处理是否对Bean实例进行依赖注入
                boolean continueWithPropertyPopulation = true;
                if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
                    Iterator var5 = this.getBeanPostProcessors().iterator();
    
                    while(var5.hasNext()) {
                        BeanPostProcessor bp = (BeanPostProcessor)var5.next();
                        if (bp instanceof InstantiationAwareBeanPostProcessor) {
                            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                                continueWithPropertyPopulation = false;
                                break;
                            }
                        }
                    }
                }
    
                if (continueWithPropertyPopulation) {
                    PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;
                    // 首先处理autowire依赖注入,根据Bean的名字或类型进行注入
                    // 我们可以在配置文件中指定注入方式:autowire="byName"
                    if (mbd.getResolvedAutowireMode() == 1 || mbd.getResolvedAutowireMode() == 2) {
                        MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
                        if (mbd.getResolvedAutowireMode() == 1) {
                            // 按变量名注入
                            this.autowireByName(beanName, mbd, bw, newPvs);
                        }
                        if (mbd.getResolvedAutowireMode() == 2) {
                            // 按类型注入
                            this.autowireByType(beanName, mbd, bw, newPvs);
                        }
                        pvs = newPvs;
                    }
    
                    boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
                    boolean needsDepCheck = mbd.getDependencyCheck() != 0;
                    PropertyDescriptor[] filteredPds = null;
                    // 在为Bean注入依赖前进行后置处理,比如检查@Required是否满足,添加或移除Property
                    if (hasInstAwareBpps) {
                        if (pvs == null) {
                            pvs = mbd.getPropertyValues();
                        }
    
                        Iterator var9 = this.getBeanPostProcessors().iterator();
    
                        while(var9.hasNext()) {
                            BeanPostProcessor bp = (BeanPostProcessor)var9.next();
                            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                                PropertyValues pvsToUse = ibp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
                                if (pvsToUse == null) {
                                    if (filteredPds == null) {
                                        filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                                    }
    
                                    pvsToUse = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                                    if (pvsToUse == null) {
                                        return;
                                    }
                                }
    
                                pvs = pvsToUse;
                            }
                        }
                    }
    			    // 进行依赖检查
                    if (needsDepCheck) {
                        if (filteredPds == null) {
                            filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                        }
    
                        this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
                    }
    
                    if (pvs != null) {
                        // 对属性进行注入★
                        this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
                    }
    
                }
            }
        }
            
        protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
            if (!pvs.isEmpty()) {
                if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
                    ((BeanWrapperImpl)bw).setSecurityContext(this.getAccessControlContext());
                }
    		   // 注入的Property
                MutablePropertyValues mpvs = null;
                List original;
                // pvs是MutablePropertyValues实例,且可强制类型转换,则可以直接设置为注入的Property
                if (pvs instanceof MutablePropertyValues) {
                    mpvs = (MutablePropertyValues)pvs;
                    if (mpvs.isConverted()) {
                        try {
                            bw.setPropertyValues(mpvs);
                            return;
                        } catch (BeansException var18) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", var18);
                        }
                    }
    
                    original = mpvs.getPropertyValueList();
                } else {
                    original = Arrays.asList(pvs.getPropertyValues());
                }
    
                TypeConverter converter = this.getCustomTypeConverter();
                if (converter == null) {
                    converter = bw;
                }
    		   // BeanDefinitionValueResolver用于解析BeanDefinition中的Property
                BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, (TypeConverter)converter);
                // 创建一个深拷贝副本,这个副本持有的Property会被注入到Bean中
                List<PropertyValue> deepCopy = new ArrayList(original.size());
                boolean resolveNecessary = false;
                Iterator var11 = original.iterator();
    
                while(true) {
                    while(var11.hasNext()) {
                        PropertyValue pv = (PropertyValue)var11.next();
                        if (pv.isConverted()) {
                            deepCopy.add(pv);
                        } else {
                            String propertyName = pv.getName();
                            Object originalValue = pv.getValue();
                            // 利用valueResolver解析PropertyValue
                            // 对value的类型进行判断,然后解析,如果是依赖bean ref的话,会调用getBean方法
                            Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
                            Object convertedValue = resolvedValue;
                            boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
                            if (convertible) {
                                convertedValue = this.convertForProperty(resolvedValue, propertyName, bw, (TypeConverter)converter);
                            }
    
                            if (resolvedValue == originalValue) {
                                if (convertible) {
                                    pv.setConvertedValue(convertedValue);
                                }
    
                                deepCopy.add(pv);
                            } else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue)originalValue).isDynamic() && !(convertedValue instanceof Collection) && !ObjectUtils.isArray(convertedValue)) {
                                pv.setConvertedValue(convertedValue);
                                deepCopy.add(pv);
                            } else {
                                resolveNecessary = true;
                                deepCopy.add(new PropertyValue(pv, convertedValue));
                            }
                        }
                    }
    
                    if (mpvs != null && !resolveNecessary) {
                        mpvs.setConverted();
                    }
    
                    try {
                        // BeanWrapper的setPropertyValues
                        // 将拷贝副本中的PropertyValues注入到Bean中<<PropertyAccessor>>
                        // 具体实现通过AbstractNestablePropertyAccessor.PropertyTokenHolder
                        // 然后根据tokens.keys处理本地值或键值
                        bw.setPropertyValues(new MutablePropertyValues(deepCopy));
                        return;
                    } catch (BeansException var19) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", var19);
                    }
                }
            }
        }
    
    

    lazy-init=false

    会在容器初始化的过程中将所有的singleton bean提前进行实例化和依赖注入,因此singleton bean的依赖注入是容器初始化过程的一部分,这也是我们常用的ApplicationContext的默认配置。

    对于非延迟单例bean的初始化在refresh()方法中的finishBeanFactoryInitialization(beanFactory)中完成。

        protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
            ...
            beanFactory.preInstantiateSingletons();	// <<ConfigurableListableBeanFactory>>
        }
    
    // 具体实现:DefaultListableBeanFactory
        public void preInstantiateSingletons() throws BeansException {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Pre-instantiating singletons in " + this);
            }
    		// 这里的beanDefinitionNames上一章有提过~
            List<String> beanNames = new ArrayList(this.beanDefinitionNames);
            Iterator var2 = beanNames.iterator();
    
            while(true) {
                String beanName;
                Object bean;
                do {
                    while(true) {
                        RootBeanDefinition bd;
                        do {
                            do {
                                do {
                                    if (!var2.hasNext()) {
                                        var2 = beanNames.iterator();
    
                                        while(var2.hasNext()) {
                                            beanName = (String)var2.next();
                                            // ★
                                            Object singletonInstance = this.getSingleton(beanName);
                                            if (singletonInstance instanceof SmartInitializingSingleton) {
                                                SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
                                                if (System.getSecurityManager() != null) {
                                                    AccessController.doPrivileged(() -> {
                                                        smartSingleton.afterSingletonsInstantiated();
                                                        return null;
                                                    }, this.getAccessControlContext());
                                                } else {
                                                    smartSingleton.afterSingletonsInstantiated();
                                                }
                                            }
                                        }
    
                                        return;
                                    }
    
                                    beanName = (String)var2.next();
                                    bd = this.getMergedLocalBeanDefinition(beanName);
                                } while(bd.isAbstract());
                            } while(!bd.isSingleton());
                        } while(bd.isLazyInit());	// 只会对非延迟单例bean进行初始化
    
                        if (this.isFactoryBean(beanName)) {
                            bean = this.getBean("&" + beanName);
                            break;
                        }
    
                        this.getBean(beanName);
                    }
                } while(!(bean instanceof FactoryBean));
    
                FactoryBean<?> factory = (FactoryBean)bean;
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                    SmartFactoryBean var10000 = (SmartFactoryBean)factory;
                    ((SmartFactoryBean)factory).getClass();
                    isEagerInit = (Boolean)AccessController.doPrivileged(var10000::isEagerInit, this.getAccessControlContext());
                } else {
                    isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
                }
    
                if (isEagerInit) {
                    // 触发依赖注入
                    this.getBean(beanName);
                }
            }
        }
    
    // DefaultSingletonBeanRegistry
        @Nullable
        protected Object getSingleton(String beanName, boolean allowEarlyReference) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
                synchronized(this.singletonObjects) {
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null && allowEarlyReference) {
                        ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            singletonObject = singletonFactory.getObject();
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
    
            return singletonObject;
        }
    
  • 相关阅读:
    java 变量的初始化顺序
    Asp.net MVC3.0 入门指南 1.简介
    使用EnterpriseLibrary5实现数据的缓存(附完整代码下载)
    js showModalDialog 取得(访问)父窗体的语法
    Asp.net MVC3.0 入门指南 2.控制器Controller
    linq 之入门(一) O/R设计器的使用
    sql2000 示例数据库Northwind的 ER图、字段说明及使用Powerdesigner反向工程方法
    局域网共享文件win7系统
    远程桌面 不能粘贴文本 的解决办法
    解决vs2005控件事件为空白
  • 原文地址:https://www.cnblogs.com/angelica-duhurica/p/11186405.html
Copyright © 2011-2022 走看看