spring源码分享之容器系列四(bean的实例化,LookupMethod,ReplaceMethod)

bean的实例化

对bean的实例化主要是从AbstractAutowireBeanFactory的createBeanInstance方法进入的,其主要是三种方式来对bean进行实例化的:

  1. 利用factoryMethod来进行实现
  2. 有参数利用autowireConstructor对参数进行解析实例化
  3. 没有参数则直接用无参构造器进行实例化

对于利用factoryMethod实例化的方式直接只要配置了factoryMethodName参数就会用这种方式,而如果有参数(这里的有参数会是带有@Autowired注解,注入方式是AUTOWIRE_CONSTRUCTOR,配置了构造器参数或外部传入了构造器参数)则会利用autowireConstructor解析对应的参数并找到对应的构造器进行实例化。这两种方式都是需要进行参数的解析,类型转换等操作,而这些操作都是委托给ConstructorResolver这个类来进行操作的。

对于这些参数的解析以及对应的构造器的查找的结果会进行缓存,而其最终的缓存结果则是存储在RootBeanDefinition这个合并了的beanDefinition中。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, 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
	}
	if (mbd.getFactoryMethodName() != null)  {
		//利用factoryMethod进行实现
		return instantiateUsingFactoryMethod(beanName, mbd, args);
	}
	boolean resolved = false;
	boolean autowireNecessary = false;
	//当外部传入的参数为空时才有可能进行缓存,检查mdb中是否有对应的缓存
	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);
		}
	}
	//这里调用的SmartInstantiationAwareBeanPostProcessor中的determineCandidateConstructors获取对应的构造器
	//对于@Autowire对构造器的依赖注入方式则是在AutowiredAnnotationBeanPostProcessor这个处理器中
	//找到对应的带有@Autowired构造器
	Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	//这里需要查询对应的构造器主要是有带有@Autowired的构造器或者注入方式是AUTOWIRE_CONSTRUCTOR 
	//或者配置了参数,或者传入了参数
	if (ctors != null ||
			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
		return autowireConstructor(beanName, mbd, ctors, args);
	}
	// 直接用无参构造器实现
	return instantiateBean(beanName, mbd);
}

ConstructorResolver

这个autowireConstructor方法对bean的实例化主要是确定创建方法和确定参数。

其中参数的来源主要是4个方面,分别为

  1. 外部配置的参数
  2. 外部传来的参数
  3. @Autowired直接解析的参数
  4. AUTOWIRE_CONSTRUCTOR直接利用类型解析出来的依赖作为参数

对于外部传进的参数,不会经过任何的转换,会直接用其类型找到最符合的构造器进行实例化,对于@Autowierd和AUTOWIRE_CONSTRUCTOR这两种方式则需要根据类型从beanFactory中找对应的bean作为依赖的参数(主要还是调用beanFactory的resolveDependency方法找到对应的依赖bean)。而对于配置的参数则需要做三种类型的转换。

  1. RuntimeBeanReference等占位符利用BeanDefinitionValueResolver转换为对应的bean实例
  2. #{1+2}等字符串表达式利用BeanExpressionResolver进行解析
  3. 利用TypeConverter做类型转换

autowireConstructor

autowireConstructor主要是确定对应的bean的构造器以及构造器参数,而确定的方式主要是。

  1. 先从RootBeanDefinition缓存中找对应的缓存的构造器和参数(这里的参数可能有些需要动态解析的参数,如AutowiredArgumentMarker这些占位符则需要进行重新解析)
  2. 对于没有缓存的则是从待选的构造器中找对应的最符合参数的构造器

而不同类型的参数进行了不同方式的操作,在这个方法中主要用了三个方法来对不同参数进行了三种操作。

  1. resolvePreparedArguments:这是对已经缓存了构造器的对应的bean其构造器有需要进行动态解析的参数进行的操作,其进行类型转换,对AutowiredArgumentMarker这种依赖注入的占位对象解析,对RuntimeBeanReference等类型的beanRefrence进行类型转换。
  2. resolveConstructorArguments:这里主要是对配置的参数进行对RuntimeBeanReference,BeanDefinition类型的参数解析器对应的bean
  3. createArgumentArray:这个方法主要是对参数进行类型转换以及对@Autowired,AUTOWIRE_CONSTRUCTOR这些依赖注入解析出其依赖的bean的操作。
public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
			Constructor[] chosenCtors, final Object[] explicitArgs) {
		BeanWrapperImpl bw = new BeanWrapperImpl();
		this.beanFactory.initBeanWrapper(bw);
		Constructor constructorToUse = null;
		ArgumentsHolder argsHolderToUse = null;
		Object[] argsToUse = null;
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
				constructorToUse = (Constructor) mbd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached constructor...
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			if (argsToResolve != null) {
				//解析对应的缓存数据,对AutowiredArgumentMarker,RuntimeBeanReference等这些占位对象从beanFactory中找到对应的依赖
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
			}
		}
		if (constructorToUse == null) {
			// 这里的注入方式是参数依赖的注入方式
			boolean autowiring = (chosenCtors != null ||
					mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
			ConstructorArgumentValues resolvedValues = null;

			int minNrOfArgs;
			if (explicitArgs != null) {
				minNrOfArgs = explicitArgs.length;
			}
			else {
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				resolvedValues = new ConstructorArgumentValues();
				//这里进行参数解析,将cargs的数据解析到resolvedValues中的数据,并且做了将RuntimeBeanReference解析为所需的参数
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
			}
			// 如果有待选的构造器则直接从待选构造器中选,否则从对应的beanCalss中的构造器中找
			Constructor[] candidates = chosenCtors;
			if (candidates == null) {
				Class beanClass = mbd.getBeanClass();
				try {
					candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors());
				}
				catch (Throwable ex) {
					... throw
				}
			}
			//public在前,然后按照参数数量从大到小排序
			AutowireUtils.sortConstructors(candidates);
			int minTypeDiffWeight = Integer.MAX_VALUE;
			Set> ambiguousConstructors = null;
			LinkedList causes = null;
			for (Constructor candidate : candidates) {
				Class[] paramTypes = candidate.getParameterTypes();
				//由于是按照参数数量从大到小排序的,已经找到了参数比当前参数数量多的构造器,后面的参数都比当前参数少,所以可以直接跳出循环
				if (constructorToUse != null && argsToUse.length > paramTypes.length) {
					break;
				}
				//当前构造器的参数的数量大于提供的的参数的数量,则必然不匹配
				if (paramTypes.length < minNrOfArgs) {
					continue;
				}
				ArgumentsHolder argsHolder;
				if (resolvedValues != null) {
					try {
					    //根据ConstructorProperties确定参数名
						String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
						if (paramNames == null) {
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
							    //利用ParameterNameDiscoverer确定参数名,默认就是方法参数名
								paramNames = pnd.getParameterNames(candidate);
							}
						}
						//创建ArgumentsHolder,通过配置的参数,传入的参数,以及@Autowired等形式查找对应的位置的参数
						argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
								getUserDeclaredConstructor(candidate), autowiring);
					}
					catch (UnsatisfiedDependencyException ex) {
					    //对于没有找到对应的匹配的对应的参数的异常忽略
						continue;
					}
				}
				else {
					//显示的传入参数和构造器需要的参数不一致则不匹配
					if (paramTypes.length != explicitArgs.length) {
						continue;
					}
					argsHolder = new ArgumentsHolder(explicitArgs);
				}
				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) :argsHolder.getAssignabilityWeight(paramTypes));
				// Choose this constructor if it represents the closest match.
				if (typeDiffWeight < minTypeDiffWeight) {
					constructorToUse = candidate;
					argsHolderToUse = argsHolder;
					argsToUse = argsHolder.arguments;
					minTypeDiffWeight = typeDiffWeight;
					ambiguousConstructors = null;
				}
				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
					if (ambiguousConstructors == null) {
						ambiguousConstructors = new LinkedHashSet>();
						ambiguousConstructors.add(constructorToUse);
					}
					ambiguousConstructors.add(candidate);
				}
			}
			if (constructorToUse == null) {
				... throw
			}
			else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
				... throw
			}
			//没有外部参数传入的则进行缓存
			if (explicitArgs == null) {
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}
		try {
			Object beanInstance;
			// ...
			beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
						mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
			bw.setBeanInstance(beanInstance);
			return bw;
		}
		catch (Throwable ex) {
			// ...
		}
	}

instantiateUsingFactoryMethod

instantiateUsingFactoryMethod的实现逻辑和autowireConstructor的实现逻辑差不多,主要的差别是候选的构造器还是factoryMethod,对于facoryMethod又根据是否配置了factoryBeanName来区分是否是static的方法。

ArgumentsHolder

这个类主要是维护四个属性:

  1. rawArguments是原生的参数类型,没有进行过类型转换的参数,其主要是用来计算构造器的差异权重
  2. arguments为进行过类型转换后的参数,这个参数是真正传给构造器方法调用的参数,它也用来计算差异权重的
  3. preparedArguments是准备的参数,这个参数是对于需要进行动态解析的参数以及需要进行类型转换的参数缓存时存储在这个属性中,再次进行参数实例化则对这个参数进行解析出对应的真正参数传递给构造器使用
  4. resolveNecessary这个是标识参数需要进行解析,在将缓存存储到RootBeanDefinition中是缓存preparedArguments还是直接缓存arguments的标识
private static class ArgumentsHolder {
	//原生的参数或者依赖解析的参数
	public final Object rawArguments[];
	//经过转化后最终调用构造器传入的参数
	public final Object arguments[];
	//准备参数的字段,主要缓存时的默认参数
	public final Object preparedArguments[];
	//标识其需要进行解析
	public boolean resolveNecessary = false;
}

LookupMethod和ReplaceMethod的实现

lookupMethod和ReplaceMethod是主要是用于一个单例的对象想注入一个prototype的对象。对于lookupMethod主要是可以利用xml配置以及使用@Lookup注解两种形式来实现,而对于replaceMethod则只能用注解的形式来完成。

配置实例

下面的代码清单简要介绍一下这两种method的配置方式。下面的这个例子主要是盘子里面放了水果,不过不确定是放苹果还是放香蕉,则定义了一个getFruit()方法来通过lookupMethod或者replaceMethod的方式配置,lookup的方式可以直接在这个方法加上一个@Lookup注解,注解配置的是获取的bean的推荐名字,如果没有则会通过其返回的类型找对应的bean作为这个方法的返回结果。

public abstract class TestPlate {
//	@Lookup("fruit")
	public abstract Fruit getFruit() ; 
}
public abstract class Fruit {
	private String name ; 
	public Fruit(String name) {
		super();
		this.name = name;
	}
	public  void say() {
		System.out.println("i am " + name + " " + getClass().getName()) ; 
	}
}
public class Apple extends Fruit{
	public Apple() {
		super("apple");
	}
}
public class Bananer extends Fruit{
	public Bananer() {
		super("bananer");
	}
}
   

lookupMethod还可以通过下面的方式来进行配置,即在bean节点下配置一个节点。


	
		
		
	
	
	
	

下面为其对应的测试实现,由于用的是纯DefaultListableBeanFactory,所以解析@Lookup的AutowiredAnnotationBeanPostProcessor需要手动注入。其输出为,表示最终获取的是香蕉。

public class TestLookup {
	public static void main(String[] args) {
		DefaultListableBeanFactory factory = new DefaultListableBeanFactory() ; 
		XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory) ; 
		factory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
		reader.loadBeanDefinitions(new ClassPathResource("bean/spring-lookup.xml")) ;
		factory.registerBeanDefinition("autowireBean", new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class));
		String[] names = factory.getBeanNamesForType(BeanPostProcessor.class) ; 
		for(String name:names) {
			BeanPostProcessor beanPostProcessor = (BeanPostProcessor) factory.getBean(name) ;
			factory.addBeanPostProcessor(beanPostProcessor);
		}
		TestPlate testPlate = factory.getBean(TestPlate.class) ; 
		testPlate.getFruit().say(); 
 	}
}

对于replaceMethod则需要自己实现MethodReplacer接口,并将其注册到beanFactory中来通过reimplement来进行实现。并通过

来进行配置。

public class FruitReplacer implements MethodReplacer ,BeanFactoryAware{
	private BeanFactory beanFactory ; 
	@Override
	public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
		return beanFactory.getBean(Fruit.class) ; 
	}
	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		this.beanFactory = beanFactory ; 
	}
}

实现方式

spring对应LookupMethodReplaceMethod的实现主要是通过cglib代理来完成的,从上面的autowireConstructor等方法中可以看到在进行实例化时最终都交给了InstantiationStrategy去完成。下面图可以看到其实现类有SimpleInstantiationStrategyCglibSubclassingInstantiationStrategy两个,SimpleInstantiationStrategy主要是对FactoryMethod或者Constructor进行调用来获取对应的bean,而CglibSubclassingInstantiationStrategy则对其进行了代理以对LookupMethod和ReplaceMethod来进行实现。

CglibSubclassingInstantiationStrategy主要是利用cglib来进行处理的,而对这两个method的具体处理逻辑则在LookupOverrideMethodInterceptor ReplaceOverrideMethodInterceptor 中进行完成,可以看到对于lookupMethod则直接是从beanFactory获取对应的bean作为这个方法的返回值,而对于replaceMethod则是从beanFactory中找到对应的MethodReplacer,然后调用MethodReplacer的reimplement方法来实现具体逻辑。

private static class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
	private final BeanFactory owner;
	public LookupOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
		super(beanDefinition);
		this.owner = owner;
	}
	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
		// Cast is safe, as CallbackFilter filters are used selectively.
		LookupOverride lo = (LookupOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
		Object[] argsToUse = (args.length > 0 ? args : null);  // if no-arg, don't insist on args at all
		if (StringUtils.hasText(lo.getBeanName())) {
			return this.owner.getBean(lo.getBeanName(), argsToUse);
		}
		else {
			return this.owner.getBean(method.getReturnType(), argsToUse);
		}
	}
}
private static class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {

	private final BeanFactory owner;

	public ReplaceOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
		super(beanDefinition);
		this.owner = owner;
	}

	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
		ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
		// TODO could cache if a singleton for minor performance optimization
		MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
		return mr.reimplement(obj, method, args);
	}
}

 

 

你可能感兴趣的:(spring学习笔记,spring)