对bean的实例化主要是从AbstractAutowireBeanFactory的createBeanInstance方法进入的,其主要是三种方式来对bean进行实例化的:
对于利用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);
}
这个autowireConstructor方法对bean的实例化主要是确定创建方法和确定参数。
其中参数的来源主要是4个方面,分别为
对于外部传进的参数,不会经过任何的转换,会直接用其类型找到最符合的构造器进行实例化,对于@Autowierd和AUTOWIRE_CONSTRUCTOR这两种方式则需要根据类型从beanFactory中找对应的bean作为依赖的参数(主要还是调用beanFactory的resolveDependency方法找到对应的依赖bean)。而对于配置的参数则需要做三种类型的转换。
autowireConstructor主要是确定对应的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的实现逻辑和autowireConstructor的实现逻辑差不多,主要的差别是候选的构造器还是factoryMethod,对于facoryMethod又根据是否配置了factoryBeanName来区分是否是static的方法。
这个类主要是维护四个属性:
private static class ArgumentsHolder {
//原生的参数或者依赖解析的参数
public final Object rawArguments[];
//经过转化后最终调用构造器传入的参数
public final Object arguments[];
//准备参数的字段,主要缓存时的默认参数
public final Object preparedArguments[];
//标识其需要进行解析
public boolean resolveNecessary = false;
}
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对应LookupMethod和ReplaceMethod的实现主要是通过cglib代理来完成的,从上面的autowireConstructor等方法中可以看到在进行实例化时最终都交给了InstantiationStrategy去完成。下面图可以看到其实现类有SimpleInstantiationStrategy和CglibSubclassingInstantiationStrategy两个,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);
}
}