2023-09-16
原文作者:王伟王胖胖 原文地址: https://blog.csdn.net/wangwei19871103/article/details/105052088

instantiateUsingFactoryMethod工厂方法实例化

上次讲实例提供器,讲了一篇,这次继续后面的,工厂方法实例化,比如bean注解的也算。
先要获取构造器解析器,然后用工厂方法进行实例化。

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

ConstructorResolver

里面没啥逻辑,主要是保存beanFactory

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

instantiateUsingFactoryMethod真正创建的方法-分段1

这个方法很核心,他会根据工厂方法的是不是唯一来进行创建,如果唯一,就直接创建,不唯一的话还要进行所有方法获取,然后选出工厂方法,再处理,我们先讲简单的情况吧。先说第一段,先创建一个实例持有器,其实就是个包装类,然后从RootBeanDefinition中获取factoryBeanName,也就工厂方法,比如说bean注解的方法就是,如果存在判断下是不是要创建自身,会报错,创建自身等于无限循环创建了。如果不是的话就获取factoryBean即工厂实例,获取工厂类型,设置非静态的。如果获取不到工厂实例,说明是静态方法。

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

instantiateUsingFactoryMethod真正创建的方法-分段2

准备好参数,尝试获取已经解析的数据,第一次都是空的。

    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真正创建的方法-分段3

如果没解析过,就获取factoryClass的用户定义类型,因为此时factoryClass可能是CGLIB动态代理类型,所以要获取用父类的类型。如果工厂方法是唯一的,就是没重载的,就获取解析的工厂方法,如果不为空,就添加到一个不可变列表里,如果为空的话,就要去 找出factoryClass的以及父类的所有的方法 进一步 找出方法修饰符一致且名字跟工厂方法名字相同的且是bean注解的方法 ,并放入列表里。

    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找出用户定义的类型

    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获取所有候选方法包括父类的

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

ReflectionUtils.getAllDeclaredMethods用反射获取方法

如果允许非Public的方法,就获取所有申明的方法,包括父类的,否则就是Public的方法,包括父类的,默认是允许的,我们直接看允许的就可以,原理一样的。

    	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递归获取

递归获取所有的方法以及父类的,获取后执行mc.doWith(method)方法,其实就是上面的methods::add把方法添加到列表里,最后转换成数组返回。

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

剩下的下次讲吧。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

阅读全文