Spring 5.x Source trip eighteen Detailed four getBean

instantiateUsingFactoryMethod factory method to instantiate

Last speak provider instance, say an article, this time to continue later, the factory method to instantiate, such as beanannotations are also considered.
Constructor must first obtain a parser, and then instantiate a factory method.

	protected BeanWrapper instantiateUsingFactoryMethod(
			String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

		return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
	}

ConstructorResolver

Which lacks logic, mainly to save beanFactory.

	public ConstructorResolver(AbstractAutowireCapableBeanFactory beanFactory) {
		this.beanFactory = beanFactory;
		this.logger = beanFactory.getLogger();
	}

instantiateUsingFactoryMethod method to create real - Segment 1

This method is very core, he will be based factory is not the only method to create, if unique, directly create, not only words but also for all the methods to obtain and then choose the factory method, reprocessing, we talk about simple case it. Let me talk first paragraph, first create an instance held device, it is actually a wrapper class, and from the RootBeanDefinitionacquisition of factoryBeanName, also factory method, such as beanthe annotated method is that if the next judgment is not to create their own, will get an error exists, create their own equal infinite loop is created. If not, then you get factoryBeanthat is factory instance, obtaining plant type, set the non-static. If you get less than factory instance, that is the static method.

		BeanWrapperImpl bw = new BeanWrapperImpl();//实例持有器
		this.beanFactory.initBeanWrapper(bw);

		Object factoryBean;//工厂实例
		Class<?> factoryClass;//工厂类型
		boolean isStatic;//是否是静态的,存在factoryBeanName表示是实例工厂,非静态方法,否则是静态的
		//factoryBeanName,也就是工厂方法所属的类的简单名字,比如配置类,这里的factoryBean,不是FactoryBean接口
		String factoryBeanName = mbd.getFactoryBeanName();
		if (factoryBeanName != null) {//存在factoryBean
			if (factoryBeanName.equals(beanName)) {//factoryBean创建出来的是工厂自身,会报异常,这样貌似等于无限递归创建了
				throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
						"factory-bean reference points back to the same bean definition");
			}
			factoryBean = this.beanFactory.getBean(factoryBeanName);//获得factoryBean
			if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {//已经创建了
				throw new ImplicitlyAppearedSingletonException();
			}
			factoryClass = factoryBean.getClass();
			isStatic = false;//非静态的
		}
		else {//静态的方法,无factoryBean实例
			// 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;
		}

Methods instantiateUsingFactoryMethod really created - subparagraph 2

Ready argument, try to get the data has been parsed, for the first time are empty.

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);
			}
		}

instantiateUsingFactoryMethod method really created - subparagraph 3

If you do not parsed, you get factoryClassa user-defined type, because at this time factoryClassmay be CGLIBa dynamic proxy types, so get used to the type of the parent class. If the plant is the only method, that is not overloaded factory method to get resolved, if not empty, it is added to an immutable list, if it is empty, then you would go to find factoryClassall of the parent class as well the method further find a way to consistently and modifier name with the same name and is a factory method beanannotated method , and placed in the list.

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> candidateList = null;
			if (mbd.isFactoryMethodUnique) {//如果工厂方法唯一,没重载的
				if (factoryMethodToUse == null) {
					factoryMethodToUse = mbd.getResolvedFactoryMethod();//获取解析的工厂方法
				}
				if (factoryMethodToUse != null) {//存在的话,返回仅包含factoryMethodToUse的不可变列表
					candidateList = Collections.singletonList(factoryMethodToUse);
				}
			}
			if (candidateList == null) {//如果没找到工厂方法,可能有重载
				candidateList = new ArrayList<>();
				Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);//获取factoryClass以及父类的所有方法作为候选的方法
				for (Method candidate : rawCandidates) {//过滤出修饰符一样,工厂方法名一样且是bean注解的方法
					if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
						candidateList.add(candidate);//如果isStatic修饰符一样且名字跟工厂方法名一样就添加
					}
				}
			}

ClassUtils.getUserClass find user-defined types

public static Class<?> getUserClass(Class<?> clazz) {
		if (clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {//如果包含CGLIB的名字符号,尝试获取父类
			Class<?> superclass = clazz.getSuperclass();
			if (superclass != null && superclass != Object.class) {
				return superclass;
			}
		}
		return clazz;
	}

getCandidateMethods acquisition all candidate parent class method comprising

	private Method[] getCandidateMethods(Class<?> factoryClass, RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			return AccessController.doPrivileged((PrivilegedAction<Method[]>) () ->
					(mbd.isNonPublicAccessAllowed() ?
						ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods()));
		}
		else {
			return (mbd.isNonPublicAccessAllowed() ?
					ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
		}
	}

The method of obtaining reflection ReflectionUtils.getAllDeclaredMethods

If the non-permissive Publicapproach, you get all the stated methods, including the parent class, otherwise Public, comprising the parent class, is enabled by default, we can look directly permitted, the same principle.

	public static Method[] getAllDeclaredMethods(Class<?> leafClass) {
		final List<Method> methods = new ArrayList<>(32);
		doWithMethods(leafClass, methods::add);
		return methods.toArray(EMPTY_METHOD_ARRAY);
	}
	public static void doWithMethods(Class<?> clazz, MethodCallback mc) {
		doWithMethods(clazz, mc, null);
	}
doWithMethods acquired recursively

Recursive method, and get all of the parent class, after the implementation of access mc.doWith(method)method, in fact, the above methods::addadded to the list method, and finally into an array to return.

public static void doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf) {
		// Keep backing up the inheritance hierarchy.
		Method[] methods = getDeclaredMethods(clazz, false);
		for (Method method : methods) {
			if (mf != null && !mf.matches(method)) {
				continue;
			}
			try {
				mc.doWith(method);
			}
			catch (IllegalAccessException ex) {
				throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
			}
		}
		if (clazz.getSuperclass() != null && (mf != USER_DECLARED_METHODS || clazz.getSuperclass() != Object.class)) {
			doWithMethods(clazz.getSuperclass(), mc, mf);
		}
		else if (clazz.isInterface()) {
			for (Class<?> superIfc : clazz.getInterfaces()) {
				doWithMethods(superIfc, mc, mf);
			}
		}
	}

The remaining next to speak the language.

Well, here today, we hope to help study and understand, do not spray the Great God see, understand only their own learning, limited capacity, please excuse.

Published 235 original articles · won praise 74 · views 30000 +

Guess you like

Origin blog.csdn.net/wangwei19871103/article/details/105052088