zoukankan      html  css  js  c++  java
  • 【spring源码系列】之【Bean的实例化】

    人生需要探索的热情、坚持的勇气以及热爱生活热爱自己的力量。

    1. Bean的实例化

    上一篇讲述了bean的生命周期,其中第一步就涉及到了bean的实例化,本文重点分析bean实例化,先进入源码中的AbstractAutowireCapableBeanFactory类中的createBeanInstance方法。

    2. 流程概览

    上述图描述了bean的实例化过程中的主要步骤:

    1. 如果存在 Supplier 回调,则调用 obtainFromSupplier() 进行初始化;
    2. 如果存在工厂方法,则使用工厂方法进行初始化;
    3. 如果构造函数参数不为空,则先获取autowired注解的构造函数,再获取构造函数里面的参数,参数是引用类型的话,再次循环调用容器去获取,最后通过反射完成实例化;
    4. 如果构造函数无参,则使用默认无参构造函数实例化;
    5. 最后将bean添加到一级缓存,并清除二级三级缓存里的bean。

    3. 源码分析

    3.1 createBeanInstance概览

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    		// Make sure bean class is actually resolved at this point.
    		Class<?> beanClass = resolveBeanClass(mbd, beanName);
    
    		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
    			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    		}
    
    		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    		// 使用Supplier接口获取
    		if (instanceSupplier != null) {
    			return obtainFromSupplier(instanceSupplier, beanName);
    		}
    
    		// 使用FactoryMethod方法实例化
    		if (mbd.getFactoryMethodName() != null) {
    			return instantiateUsingFactoryMethod(beanName, mbd, args);
    		}
    
    		// Shortcut when re-creating the same bean...
    		boolean resolved = false;
    		boolean autowireNecessary = false;
    		if (args == null) {
    			synchronized (mbd.constructorArgumentLock) {
    				if (mbd.resolvedConstructorOrFactoryMethod != null) {
    					resolved = true;
    					autowireNecessary = mbd.constructorArgumentsResolved;
    				}
    			}
    		}
    		if (resolved) {
    			if (autowireNecessary) {
    				return autowireConstructor(beanName, mbd, null, null);
    			}
    			else {
    				return instantiateBean(beanName, mbd);
    			}
    		}
    
    		// Candidate constructors for autowiring?
    		// 构造函数有参autowired修饰
    		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
    				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
    			return autowireConstructor(beanName, mbd, ctors, args);
    		}
    
    		// Preferred constructors for default construction?
    		ctors = mbd.getPreferredConstructors();
    		if (ctors != null) {
    			return autowireConstructor(beanName, mbd, ctors, null);
    		}
    
    		// No special handling: simply use no-arg constructor.
    		// 默认实例化
    		return instantiateBean(beanName, mbd);
    }
    

    3.1 使用Supplier接口

    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    		// 使用Supplier接口获取
    		if (instanceSupplier != null) {
    			return obtainFromSupplier(instanceSupplier, beanName);
    		}
    

    进入obtainFromSupplier方法

    protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
    		Object instance;
    
    		String outerBean = this.currentlyCreatedBean.get();
    		this.currentlyCreatedBean.set(beanName);
    		try {
                            // 从instanceSupplier获取
    			instance = instanceSupplier.get();
    		}
    		finally {
    			if (outerBean != null) {
    				this.currentlyCreatedBean.set(outerBean);
    			}
    			else {
    				this.currentlyCreatedBean.remove();
    			}
    		}
    
    		if (instance == null) {
    			instance = new NullBean();
    		}
                    // 包装成BeanWrapper
    		BeanWrapper bw = new BeanWrapperImpl(instance);
                    // 初始化BeanWrapper
    		initBeanWrapper(bw);
    		return bw;
    	}
    

    上述源码显示从从instanceSupplier获取,而instanceSupplier是一个函数式接口:

    @FunctionalInterface
    public interface Supplier<T> {
    
        /**
         * Gets a result.
         *
         * @return a result
         */
        T get();
    }
    

    那在何时对该instanceSupplier进行设值的呢?不妨来看一下RootBeanDefinition:

    protected BeanWrapper instantiateUsingFactoryMethod(
    	String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    
    	return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
    }
    
    

    由此可见,在初始化BeanDefinition的时候,就已经将instanceSupplier设值, 随后从instanceSupplier.get()获取,最后包装成BeanWrapper对象后,对其初始化。

    3.2 使用FactoryMethod方法实例化

    如果工厂方法不为空,则使用工厂方法实例化:

    // 使用FactoryMethod方法实例化
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
    

    下面进入instantiateUsingFactoryMethod方法:

    protected BeanWrapper instantiateUsingFactoryMethod(
    			String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    
        return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
    }
    

    先创建一个ConstructorResolver对象,然后调用其instantiateUsingFactoryMethod方法,该方法细节很多,看如下主要步骤:

    	public BeanWrapper instantiateUsingFactoryMethod(
    			String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    
    		BeanWrapperImpl bw = new BeanWrapperImpl();
    		this.beanFactory.initBeanWrapper(bw);
    
    		Object factoryBean;
    		Class<?> factoryClass;
    		boolean isStatic;
    		// 获取工厂bean
    		String factoryBeanName = mbd.getFactoryBeanName();
    		// RootBeanDefinition的factory-bean属性不为空
    		if (factoryBeanName != null) {
    			if (factoryBeanName.equals(beanName)) {
    				throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
    						"factory-bean reference points back to the same bean definition");
    			}
    			factoryBean = this.beanFactory.getBean(factoryBeanName);
    			if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
    				throw new ImplicitlyAppearedSingletonException();
    			}
    			factoryClass = factoryBean.getClass();
    			isStatic = false;
    		}
    		// RootBeanDefinition的factory-bean属性为空,需要静态方法初始化
    		else {
    			// It's a static factory method on the bean class.
    			if (!mbd.hasBeanClass()) {
    				throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
    						"bean definition declares neither a bean class nor a factory-bean reference");
    			}
    			factoryBean = null;
    			factoryClass = mbd.getBeanClass();
    			isStatic = true;
    		}
    		// 工厂方法与参数
    		Method factoryMethodToUse = null;
    		ArgumentsHolder argsHolderToUse = null;
    		Object[] argsToUse = null;
    
    		if (explicitArgs != null) {
    			argsToUse = explicitArgs;
    		}
    		else {
    			// 首先尝试从缓存中获取参数
    			Object[] argsToResolve = null;
    			synchronized (mbd.constructorArgumentLock) {
    				factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
    				if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
    					// Found a cached factory method...
    					argsToUse = mbd.resolvedConstructorArguments;
    					if (argsToUse == null) {
    						argsToResolve = mbd.preparedConstructorArguments;
    					}
    				}
    			}
    			if (argsToResolve != null) {
    				argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
    			}
    		}
    
    		if (factoryMethodToUse == null || argsToUse == null) {
    			// Need to determine the factory method...
    			// Try all methods with this name to see if they match the given arguments.
    			// 获取工厂类全名
    			factoryClass = ClassUtils.getUserClass(factoryClass);
    
    			List<Method> candidates = null;
    			if (mbd.isFactoryMethodUnique) {
    				if (factoryMethodToUse == null) {
    					factoryMethodToUse = mbd.getResolvedFactoryMethod();
    				}
    				if (factoryMethodToUse != null) {
    					candidates = Collections.singletonList(factoryMethodToUse);
    				}
    			}
    			if (candidates == null) {
    				candidates = new ArrayList<>();
    				Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
    				for (Method candidate : rawCandidates) {
    					// 如果有static 且为工厂方法,则添加到 candidates 中
    					if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
    						candidates.add(candidate);
    					}
    				}
    			}
    
    			// 工厂类只有一个工厂方法
    			if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
    				Method uniqueCandidate = candidates.get(0);
    				if (uniqueCandidate.getParameterCount() == 0) {
    					mbd.factoryMethodToIntrospect = uniqueCandidate;
    					synchronized (mbd.constructorArgumentLock) {
    						mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
    						mbd.constructorArgumentsResolved = true;
    						mbd.resolvedConstructorArguments = EMPTY_ARGS;
    					}
                                            // 初始化bean
    					bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
    					return bw;
    				}
    			}
    
    			// 工厂类有多个工厂方法,按照参数数量降序排列
    			if (candidates.size() > 1) {  // explicitly skip immutable singletonList
    				candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR);
    			}
    
    			ConstructorArgumentValues resolvedValues = null;
    			boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
    			int minTypeDiffWeight = Integer.MAX_VALUE;
    			Set<Method> ambiguousFactoryMethods = null;
    
    			int minNrOfArgs;
    			if (explicitArgs != null) {
    				minNrOfArgs = explicitArgs.length;
    			}
    			else {
    				// We don't have arguments passed in programmatically, so we need to resolve the
    				// arguments specified in the constructor arguments held in the bean definition.
    				if (mbd.hasConstructorArgumentValues()) {
    					ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
    					resolvedValues = new ConstructorArgumentValues();
    					minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
    				}
    				else {
    					minNrOfArgs = 0;
    				}
    			}
    
    			LinkedList<UnsatisfiedDependencyException> causes = null;
    			// 遍历工厂方法
    			for (Method candidate : candidates) {
    				int parameterCount = candidate.getParameterCount();
    
    				if (parameterCount >= minNrOfArgs) {
    					ArgumentsHolder argsHolder;
    
    					Class<?>[] paramTypes = candidate.getParameterTypes();
    					if (explicitArgs != null) {
    						// Explicit arguments given -> arguments length must match exactly.
    						if (paramTypes.length != explicitArgs.length) {
    							continue;
    						}
    						argsHolder = new ArgumentsHolder(explicitArgs);
    					}
    					else {
    						// Resolved constructor arguments: type conversion and/or autowiring necessary.
    						try {
    							String[] paramNames = null;
    							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
    							if (pnd != null) {
    								paramNames = pnd.getParameterNames(candidate);
    							}
    							argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
    									paramTypes, paramNames, candidate, autowiring, candidates.size() == 1);
    						}
    						catch (UnsatisfiedDependencyException ex) {
    							if (logger.isTraceEnabled()) {
    								logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
    							}
    							// Swallow and try next overloaded factory method.
    							if (causes == null) {
    								causes = new LinkedList<>();
    							}
    							causes.add(ex);
    							continue;
    						}
    					}
    
    					int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
    							argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
    					// Choose this factory method if it represents the closest match.
    					if (typeDiffWeight < minTypeDiffWeight) {
    						factoryMethodToUse = candidate;
    						argsHolderToUse = argsHolder;
    						argsToUse = argsHolder.arguments;
    						minTypeDiffWeight = typeDiffWeight;
    						ambiguousFactoryMethods = null;
    					}
    					// Find out about ambiguity: In case of the same type difference weight
    					// for methods with the same number of parameters, collect such candidates
    					// and eventually raise an ambiguity exception.
    					// However, only perform that check in non-lenient constructor resolution mode,
    					// and explicitly ignore overridden methods (with the same parameter signature).
    					else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
    							!mbd.isLenientConstructorResolution() &&
    							paramTypes.length == factoryMethodToUse.getParameterCount() &&
    							!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
    						if (ambiguousFactoryMethods == null) {
    							ambiguousFactoryMethods = new LinkedHashSet<>();
    							ambiguousFactoryMethods.add(factoryMethodToUse);
    						}
    						ambiguousFactoryMethods.add(candidate);
    					}
    				}
    			}
    
    			if (factoryMethodToUse == null || argsToUse == null) {
    				if (causes != null) {
    					UnsatisfiedDependencyException ex = causes.removeLast();
    					for (Exception cause : causes) {
    						this.beanFactory.onSuppressedException(cause);
    					}
    					throw ex;
    				}
    				List<String> argTypes = new ArrayList<>(minNrOfArgs);
    				if (explicitArgs != null) {
    					for (Object arg : explicitArgs) {
    						argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
    					}
    				}
    				else if (resolvedValues != null) {
    					Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
    					valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
    					valueHolders.addAll(resolvedValues.getGenericArgumentValues());
    					for (ValueHolder value : valueHolders) {
    						String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
    								(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
    						argTypes.add(argType);
    					}
    				}
    				String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
    				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    						"No matching factory method found: " +
    						(mbd.getFactoryBeanName() != null ?
    							"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
    						"factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
    						"Check that a method with the specified name " +
    						(minNrOfArgs > 0 ? "and arguments " : "") +
    						"exists and that it is " +
    						(isStatic ? "static" : "non-static") + ".");
    			}
    			else if (void.class == factoryMethodToUse.getReturnType()) {
    				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    						"Invalid factory method '" + mbd.getFactoryMethodName() +
    						"': needs to have a non-void return type!");
    			}
    			else if (ambiguousFactoryMethods != null) {
    				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    						"Ambiguous factory method matches found in bean '" + beanName + "' " +
    						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
    						ambiguousFactoryMethods);
    			}
    
    			if (explicitArgs == null && argsHolderToUse != null) {
    				mbd.factoryMethodToIntrospect = factoryMethodToUse;
    				argsHolderToUse.storeCache(mbd, factoryMethodToUse);
    			}
    		}
                    // 初始化bean
    		bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
    		return bw;
    	}
    

    这个方法体太多if条件,通过拆解主要流程可以归纳为以下步骤:
    step1:获取工厂bean的名字;
    step2:判断工厂bean名字是否为空,如果不为空,从容器中获取工厂bean,并将非静态方法设为false;
    step3:如果工厂bean的名字为空,则使用静态方法实例化。
    上述其他代码都是初始化前工厂方法的遍历,工厂方法的排序、以及参数的获取,最终再调用instantiate方法完成初始化;而instantiate的核心代码就一句话

    return this.beanFactory.getInstantiationStrategy().instantiate(
    						mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
    

    getInstantiationStrategy()获取实例化的策略,这里是使用工厂方法来实例化bean,进入instantiate方法:

    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
    			@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
    
    		try {
    			if (System.getSecurityManager() != null) {
    				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    					ReflectionUtils.makeAccessible(factoryMethod);
    					return null;
    				});
    			}
    			else {
    				ReflectionUtils.makeAccessible(factoryMethod);
    			}
    
    			Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
    			try {
    				currentlyInvokedFactoryMethod.set(factoryMethod);
                                    // 核心代码就是通过反射完成实例化
    				Object result = factoryMethod.invoke(factoryBean, args);
    ...
    
    

    最终是通过反射完成bean的实例化。

    3.3 有参构造函数实例化

    如果没有通过工厂方法完成实例化,那么继续玩下走如下代码:

                    // 寻找实例化的bean中有@Autowired注解的构造函数
    		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
    				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
    			// 如果ctors不为空,就说明构造函数中有@Autowired注解
    			return autowireConstructor(beanName, mbd, ctors, args);
    		}
    

    有参构造函数的实例化过程,通过determineConstructorsFromBeanPostProcessors这个方法完成,同时也是BeanPostProcessor接口类的应用,最终会调到 AutowiredAnnotationBeanPostProcessor类的方法,在方法中会扫描有注解的构造函数然后完成装配过程。然后把有@Autowired 注解的构造函数返回。

    上面已经拿到了构造函数,autowireConstructor就是获取参数的过程,其方法比较复杂,跟之前的instantiateUsingFactoryMethod类似,不再细究,把主要核心代码拿出来分析:

    // 获取构造函数参数的值
    argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
    

    createArgumentArray方法,获取构造函数参数的值,进入方法,找到核心代码:

    // 解析所有构造函数的参数值
    Object autowiredArgument = resolveAutowiredArgument(methodParam, beanName, autowiredBeanNames, converter, fallback);
    

    resolveAutowiredArgument方法解析构造函数参数的值,再进入:

    // 解析依赖
    return this.beanFactory.resolveDependency(new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
    

    再次进入:

    // 执行解析依赖
    result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
    
    // 解析candidate
    instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
    
    beanFactory.getBean(beanName)
    

    最终会感觉眼前一亮,通过非常熟悉的getBean获取实例,然后会走到普通情况下的getBean方法,通过上面得到一个结论,不管是 Field、Method、还是构造函数中有@Autowired 注解引入的类,都是通过getBean方法进行实例化获取bean的实例的。

    3.4 无参构造函数实例化

    无参构造函数的实例化过程 instantiateBean(beanName, mbd)这就是简单的反射实例化。大部分类的实例化都会走这个逻辑。进入实现类的方法:

    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    		// Don't override the class with CGLIB if no overrides.
                    // 如果没有方法覆盖
    		if (!bd.hasMethodOverrides()) {
    			Constructor<?> constructorToUse;
    			synchronized (bd.constructorArgumentLock) {
    				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
    				if (constructorToUse == null) {
    					final Class<?> clazz = bd.getBeanClass();
    					if (clazz.isInterface()) {
    						throw new BeanInstantiationException(clazz, "Specified class is an interface");
    					}
    					try {
    						if (System.getSecurityManager() != null) {
    							constructorToUse = AccessController.doPrivileged(
    									(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
    						}
    						else {
    							constructorToUse = clazz.getDeclaredConstructor();
    						}
    						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
    					}
    					catch (Throwable ex) {
    						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
    					}
    				}
    			}
                            // 反射调用
    			return BeanUtils.instantiateClass(constructorToUse);
    		}
    		else {
    			// Must generate CGLIB subclass.
                            // 创建cglib子类后在实例化
    			return instantiateWithMethodInjection(bd, beanName, owner);
    		}
    	}
    

    3.5 bean实例化后的收尾工作

    当创建完后,回到上一篇讲的getSingleton方法:

    // 创建bean实例
    				if (mbd.isSingleton()) {
    					sharedInstance = getSingleton(beanName, () -> {
    						try {
    							return createBean(beanName, mbd, args);
    						}
    						catch (BeansException ex) {
    							// Explicitly remove instance from singleton cache: It might have been put there
    							// eagerly by the creation process, to allow for circular reference resolution.
    							// Also remove any beans that received a temporary reference to the bean.
    							destroySingleton(beanName);
    							throw ex;
    						}
    					});
    					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    				}
    

    再来回顾一下该方法:

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    		Assert.notNull(beanName, "Bean name must not be null");
    		synchronized (this.singletonObjects) {
    			Object singletonObject = this.singletonObjects.get(beanName);
    			if (singletonObject == null) {
    				if (this.singletonsCurrentlyInDestruction) {
    					throw new BeanCreationNotAllowedException(beanName,
    							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
    							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
    				}
    				if (logger.isDebugEnabled()) {
    					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
    				}
    				// bean单例创建前
    				beforeSingletonCreation(beanName);
    				boolean newSingleton = false;
    				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
    				if (recordSuppressedExceptions) {
    					this.suppressedExceptions = new LinkedHashSet<>();
    				}
    				try {
    					// 调用createBean方法创建bean
    					singletonObject = singletonFactory.getObject();
    					newSingleton = true;
    				}
    				catch (IllegalStateException ex) {
    					// Has the singleton object implicitly appeared in the meantime ->
    					// if yes, proceed with it since the exception indicates that state.
    					singletonObject = this.singletonObjects.get(beanName);
    					if (singletonObject == null) {
    						throw ex;
    					}
    				}
    				catch (BeanCreationException ex) {
    					if (recordSuppressedExceptions) {
    						for (Exception suppressedException : this.suppressedExceptions) {
    							ex.addRelatedCause(suppressedException);
    						}
    					}
    					throw ex;
    				}
    				finally {
    					if (recordSuppressedExceptions) {
    						this.suppressedExceptions = null;
    					}
    					// 创建完成后要从正在实例化的bean集合singletonsCurrentlyInCreation中删除该bean
    					afterSingletonCreation(beanName);
    				}
    				if (newSingleton) {
    					// bean加入缓存
    					addSingleton(beanName, singletonObject);
    				}
    			}
    			return singletonObject;
    		}
    	}
    

    以及addSingleton相关代码如下:

    	protected void addSingleton(String beanName, Object singletonObject) {
    		synchronized (this.singletonObjects) {
    			// 一级缓存存放bean
    			this.singletonObjects.put(beanName, singletonObject);
    			// 三级缓存移除bean
    			this.singletonFactories.remove(beanName);
    			// 二级缓存移除bean
    			this.earlySingletonObjects.remove(beanName);
    			//
    			this.registeredSingletons.add(beanName);
    		}
    	}
    

    可以看出getSingleton方法总共做了如下几件事:

    1. bean创建前,将正在创建的bean放入singletonsCurrentlyInCreation集合;
    2. bean创建过程中,就是上一篇写的bean的创建整个过程,本篇只是涉及建实例这一个环节;
    3. bean创建后,从集合singletonsCurrentlyInCreation中移除正在创建的bean;
    4. bean加入一级缓存,同时移除三级缓存与二级缓存中的bean。

    4. 案例

    4.1 使用工厂方法创建bean

    使用如下配置文件spring.xml,第一种是使用factory-bean属性,bean后面不带class属性;第二种是bean使用class属性,factory-method属性后面是静态工厂方法:

            <context:component-scan base-package="com.wzj"/>
    	<bean id="factoryMethodbean" class="com.wzj.bean.FactoryMethodBean"/>
    	<bean id="wzj" factory-bean="factoryMethodbean" factory-method="factoryMethod"/>
    
    	<bean id="wzj2"  class="com.wzj.bean.Wzj" factory-method="factoryMethod"/>
    

    FactoryMethodBean类如下,

    public class FactoryMethodBean {
    
        public Object factoryMethod() {
            return new Wzj();
        }
    
    
        public Object factoryMethod(SC sc, CQ cq) {
            return new Wzj(sc,cq);
        }
    
    }
    

    实例化类如下:

    public class Wzj {
        public static Wzj factoryMethod() {
            return new Wzj();
        }
    
        SC sc;
    
        public Wzj() {
    
        }
    
        public Wzj(SC sc, CQ cq) {
            this.sc = sc;
            this.cq = cq;
        }
    
        CQ cq;
    
    }
    

    依赖的属性值分别代表四川、重庆,实现了Province接口:

    @Component
    public class CQ implements Province{
    
        private static String flag = "CQ";
    
        @Override
        public boolean support(String flag) {
            return CQ.flag.equalsIgnoreCase(flag);
        }
    
        @Override
        public String handler() {
            System.out.println("======CQ处理类处理");
            return null;
        }
    }
    
    @Component
    public class SC implements Province{
    
        private static String flag = "SC";
    
        @Override
        public boolean support(String flag) {
            return SC.flag.equalsIgnoreCase(flag);
        }
    
        @Override
        public String handler() {
            System.out.println("======SC处理类处理");
            return null;
        }
    }
    
    public interface Province {
    
        public boolean support(String flag);
    
        public String handler();
    }
    

    测试类:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:spring.xml"})
    public class TestSpring {
        @Test
        public void testCreateBeanInstance() {
            ClassPathXmlApplicationContext applicationContext =
                    new ClassPathXmlApplicationContext("spring.xml");
            Wzj wzj = (Wzj) applicationContext.getBean("wzj");
            Wzj wzj2 = (Wzj) applicationContext.getBean("wzj2");
            System.out.println(wzj.getClass().getName());
            System.out.println(wzj2.getClass().getName());
        }
    
    

    最后结果:

    com.wzj.bean.Wzj
    com.wzj.bean.Wzj
    

    4.2 带有autowired的有参构造函数

    测试示例代码:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:spring.xml"})
    public class TestSpring {
        @Test
        public void testCreateBeanInstance() {
            ClassPathXmlApplicationContext applicationContext =
                    new ClassPathXmlApplicationContext("spring.xml");
            AutowiredConstructorBean fmc = (AutowiredConstructorBean)applicationContext.getBean("autowiredConstructorBean");
            System.out.println(fmc.getClass().getName());
        }
    

    实例化AutowiredConstructorBean的代码:

    @Component
    public class AutowiredConstructorBean {
    
        @Autowired
        private SC sc;
    
        @Resource
        private CQ cq;
    
        @Autowired
        public AutowiredConstructorBean(SC sc,CQ cq) {
            System.out.println(sc);
            System.out.println(cq);
        }
    }
    

    结果会打印如下:

    com.wzj.bean.AutowiredConstructorBean
    

    如果再加一个带@Autowired参数的构造函数:

    @Component
    public class AutowiredConstructorBean {
    
        @Autowired
        private SC sc;
    
        @Resource
        private CQ cq;
    
        @Autowired
        public AutowiredConstructorBean(SC sc,CQ cq) {
            System.out.println(sc);
            System.out.println(cq);
        }
    
        @Autowired(required = false)
        public AutowiredConstructorBean(SC sc) {
            System.out.println(sc);
        }
    }
    
    

    结果就会报错:

    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'autowiredConstructorBean': Invalid autowire-marked constructor: public com.wzj.bean.AutowiredConstructorBean(com.wzj.strategy.SC). Found constructor with 'required' Autowired annotation already: public com.wzj.bean.AutowiredConstructorBean(com.wzj.strategy.SC,com.wzj.strategy.CQ)
    	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:339)
    

    通过调试,发现报错的根源是在第二次拿构造函数的参数时,执行了AutowiredAnnotationBeanPostProcessor中determineCandidateConstructors方法的如下代码:

    						if (ann != null) {
    							if (requiredConstructor != null) {
    								throw new BeanCreationException(beanName,
    										"Invalid autowire-marked constructor: " + candidate +
    										". Found constructor with 'required' Autowired annotation already: " +
    										requiredConstructor);
    							}
    

    提示已经有required修饰的构造函数存在,解决上述问题,如果有两个@Autowired注解的有参构造函数,需要将两个构造函数@Autowired都加上required = false)。只不过构造函数会根据参数个数的多少降序排序,参数多的构造函数会优先执行,后面的那个构造函数不会被执行。

    4.3 不带有autowired的有参构造函数

    public class AutowiredConstructorBean {
        public AutowiredConstructorBean(SC sc,CQ cq) {
            System.out.println(sc);
            System.out.println(cq);
        }
    }
    

    最后也能完成初始化。

    4.4 无参构造函数

    public class AutowiredConstructorBean {
        
    }
    

    通过上面测试案例最后也能完成实例化。

    5. 总结

    本篇讲述了bean实例化的多种方式,可以学到spring为用户提供多种创建方式,从而看出spring创建bean方式的灵活性,在我们写代码时候,也可以考虑多种策略,来完成某种功能,提高可扩展性与灵活性。

  • 相关阅读:
    Java生产环境线上栈故障排查问题(COPY)
    Java集合HashMap,List底层
    图算法--染色法判定二图
    图算法--kruskal
    图算法--最小生成树prim
    图算法--判负环
    图算法--floyd
    图算法--spfa
    图算法--bellman-ford (nm)
    图算法--堆优化版dijkstra
  • 原文地址:https://www.cnblogs.com/father-of-little-pig/p/14958523.html
Copyright © 2011-2022 走看看