Spring源码学习篇2 - XML配置看简单Bean的创建过程

0. 准备

有两个简单类,书架Bookshelf 和书Book

public class Bookshelf {
    private String category;
    private List<Book> books;

    public Bookshelf() {

    }

    public Bookshelf(String category) {
        this.category = category;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public List<Book> getBooks() {
        return books;
    }

    public void setBooks(List<Book> books) {
        this.books = books;
    }
}
public class Book {
    private String name;

    public Book(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

简单Bean的创建过程

    <bean id="bookShelf0" class="beans.dependency.Bookshelf">
        <property name="category" value="算法"/>
    </bean>

    <bean id="bookShelf1" class="beans.dependency.Bookshelf">
        <constructor-arg name="category" value="架构"/>
    </bean>

XmlBeanDefinitionReader先将XML配置文件加载为Document对象,然后通过BeanDefinitionDocumentReader的实现类DefaultBeanDefinitionDocumentReader依次对<beans>中的各子元素进行处理,默认命令空间将会处理的元素有:import、alias、bean、beans。

其中<beans>和<bean>元素的处理都离不开BeanDefinitionParserDelegate。

<beans>元素的属性初始化

<beans>元素可以配置一些属性,所以在解析子元素之前,会先对这些属性进行初始化, 初始化结果记录在DocumentDefaultsDefinition对象上,它是BeanDefinitionParserDelegate一个属性defaults。

从默认处理可以看到几个属性的处理结果:

  • default-lazy-init:默认值是"false",或从父元素继承
  • default-merge:默认值是"false",或从父元素继承
  • default-autowire:默认值是"no",或从父元素继承
  • default-autowire-candidates:默认null,或从父元素继承
  • default-init-method:默认null,或从父元素继承
  • default-destroy-method:默认null,或从父元素继承

<bean>元素的解析

<bean>元素的解析工作主要在BeanDefinitionParserDelegate#parseBeanDefinitionElement中,解析流程:

  1. 首先获取id属性的值,将作为beanName。

  2. 获取name属性的值,可以多值(",; "隔开),将作为别名,但别名会在BeanDefinition解析完成后,单独注册各别名到beanNamed的映射关系;BeanDefinition本身不会记录别名。

  3. 校验beanName和别名,不能已经被使用,否则报错

  4. 获取classparent属性的值,并构造GenericBeanDefinition实例,这里class允许为空

  5. 解析BeanDefinitionAttributes:

    • scope:默认""
    • abstract: 仅当配置为"true"时为true
    • lazy-init:默认值的话,会读取<beans>元素default-lazy-init属性
    • autowire:默认读取<beans>元素default-autowire属性
    • depends-on:允许多指
    • autowire-candidate:如果default-autowire-candidates匹配到beanName为true,或者设置为true,否则为false
    • primary: 仅当配置为"true"时为true
    • init-method:如果为空的话,读取default-init-method且enforceInitMethod置为false
    • destroy-method:如果为空的话,读取default-destroy-method且enforceDestroyMethod置为false
    • factory-method :静态方法,或者factory-bean的方法
    • factory-bean:factory-method所属的bean
  6. description

  7. <meta>子元素:BeanMetadataAttribute

  8. <lookup-method>子元素:存在两个属性name和bean,记录为LookupOverride,是MethodOverride的子类

  9. <replaced-method>子元素:存在两个属性name和replacer,其下还有子元素arg-type; 记录为ReplaceOverride,是MethodOverride的子类

  10. <constructor-arg>子元素的解析结果记录在BeanDefinition的属性ConstructorArgumentValues 上

    «interface» BeanMetadataElement TypedStringValue String value Object targetType Object source String specifiedTypeName boolean dynamic «interface» BeanReference RuntimeBeanReference String beanName Class<?> beanType boolean toParent Object source ValueHolder Object value String type String name Object source boolean converted Object convertedValue ConstructorArgumentValues Map<Integer, ValueHolder> indexedArgumentValues List<ValueHolder> genericArgumentValues implements Inheritance implements value value

    根据<constructor-arg>的ref属性或者value属性,构造RuntimeBeanReference对象或者TypedStringValue对象,作为ValueHolder的value属性。

  11. <property>子元素的解析结果将记录在BeanDefinition的属性MutablePropertyValues上

    «interface» PropertyValues MutablePropertyValues List<PropertyValue> propertyValueList Set<String> processedProperties boolean converted PropertyValue String name Object value Object convertedValue boolean optional boolean converted Object convertedValue Boolean conversionNecessary Object resolvedTokens ValueHolder Object value String type String name Object source boolean converted Object convertedValue Inheritance value

    <property>的元素必须要有name属性,ref或value的属性处理同构造参数

  12. <qualifier>子元素解析为AutowireCandidateQualifier,并记录在BeanDefinition的属性Map<String, AutowireCandidateQualifier> qualifiers上

    public class AutowireCandidateQualifier extends BeanMetadataAttributeAccessor {
    /**
     * The name of the key used to store the value.
     */
    public static final String VALUE_KEY = "value";
    
    private final String typeName;
    

至此,<bean>元素解析成为GenericBeanDefinition对象,并通过BeanDefinitionRegistry接口注册到对应的容器上:

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

Bean的实例化

DefaultListableBeanFactory 实例化

Bean的实例化会在第一个get的时候,如果通过XmlBeanFactory或者下面的方式来实例化Bean,那么loadBeanDefinitions执行之后,容器中只有BeanDefinition,没有实例化的bean。

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
xmlBeanDefinitionReader.loadBeanDefinitions(new ClassPathResource("testa_bean_config.xml", Bookshelf.class));

Bookshelf bookShelf0 = beanFactory.getBean("bookShelf0", Bookshelf.class);
Bookshelf bookShelf1 = beanFactory.getBean("bookShelf1", Bookshelf.class);
assertNotNull(bookShelf0);
assertNotNull(bookShelf1);

Bean的实例化过程大致如下:

  1. 由原来的GenericBeanDefinition对象,构造RootBeanDefinition,同时如果当前是个Child bean会合并parent的一些配置
  2. 如果dependsOn不为空,会先调用getBean来初始化这些依赖的bean
  3. 然后根据scope是singletonprototype、其他自定义Scope执行三种不同的实例化方法
    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;
    		}
    	});
    	beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }
    
    else if (mbd.isPrototype()) {
    	// It's a prototype -> create a new instance.
    	Object prototypeInstance = null;
    	try {
    		beforePrototypeCreation(beanName);
    		prototypeInstance = createBean(beanName, mbd, args);
    	}
    	finally {
    		afterPrototypeCreation(beanName);
    	}
    	beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    }
    
    else {
    	String scopeName = mbd.getScope();
    	if (!StringUtils.hasLength(scopeName)) {
    		throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
    	}
    	Scope scope = this.scopes.get(scopeName);
    	if (scope == null) {
    		throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
    	}
    	try {
    		Object scopedInstance = scope.get(beanName, () -> {
    			beforePrototypeCreation(beanName);
    			try {
    				return createBean(beanName, mbd, args);
    			}
    			finally {
    				afterPrototypeCreation(beanName);
    			}
    		});
    		beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    	}
    	catch (IllegalStateException ex) {
    		throw new ScopeNotActiveException(beanName, scopeName, ex);
    	}
    }
    
    真正创建对象的代码在 createBean(beanName, mbd, args);方法中,三类不同的Scope都会执行相同的部分来实例化Bean,它们不同的地方在于:
    • singleton,会在实例化bean之后,将bean记录到容器的singletonObjects上
      protected void addSingleton(String beanName, Object singletonObject) {
      	synchronized (this.singletonObjects) {
      		this.singletonObjects.put(beanName, singletonObject);
      		this.singletonFactories.remove(beanName);
      		this.earlySingletonObjects.remove(beanName);
      		this.registeredSingletons.add(beanName);
      	}
      }
      
    • prototype ,创建之后容器没有记录下来,所以每次都会创建新的实例
    • 其他scope,交给Scope接口的get方法来管理创建的bean。比如request scope对Bean的管理逻辑如下:
    public Object get(String name, ObjectFactory<?> objectFactory) {
    	RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
    	Object scopedObject = attributes.getAttribute(name, getScope());
    	if (scopedObject == null) {
    		scopedObject = objectFactory.getObject();
    		attributes.setAttribute(name, scopedObject, getScope());
    		// Retrieve object again, registering it for implicit session attribute updates.
    		// As a bonus, we also allow for potential decoration at the getAttribute level.
    		Object retrievedObject = attributes.getAttribute(name, getScope());
    		if (retrievedObject != null) {
    			// Only proceed with retrieved object if still present (the expected case).
    			// If it disappeared concurrently, we return our locally created instance.
    			scopedObject = retrievedObject;
    		}
    	}
    	return scopedObject;
    }
    

createBean方法的实现目前只有一处:AbstractAutowireCapableBeanFactory#createBean,其实现如下:

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

	if (logger.isTraceEnabled()) {
		logger.trace("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;

	// Make sure bean class is actually resolved at this point, and
	// clone the bean definition in case of a dynamically resolved Class
	// which cannot be stored in the shared merged bean definition.
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	// Prepare method overrides.
	try {
		mbdToUse.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}

	try {
		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
				"BeanPostProcessor before instantiation of bean failed", ex);
	}

	try {
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isTraceEnabled()) {
			logger.trace("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
		// A previously detected exception with proper bean creation context already,
		// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
	}
}
提前创建代理的机会 - InstantiationAwareBeanPostProcessor

上面resolveBeforeInstantiation是一个比较重要的过程,它提供了一个机会,在真正实例化之前,允许通过BeanPostProcessor 创建代理对象:

  1. 获取容器所有的BeanPostProcessor 实例
  2. 遍历BeanPostProcessor 实例,如果也实现了InstantiationAwareBeanPostProcessor,那么执行InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation创建代理
  3. 在第一个代理创建成功后,后续InstantiationAwareBeanPostProcessor不再执行
  4. 代理对象创建成功后,获取所有BeanPostProcessor 实例,并执行org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
  5. 默认情况下,postProcessAfterInitialization直接返回对象本身或者一个wrapped对象
AbstractAutowireCapableBeanFactory#doCreateBean
doCreateBean - bean的初始化
1. AbstractBeanDefinition#getInstanceSupplier

Spring 5.0 之后提供的方法,没看到对应的配置,下面是一种可行的使用方式:

GenericApplicationContext ctx = new GenericApplicationContext();
String bookName = "javaBook";
ctx.registerBean(bookName, Book.class, () -> new Book(bookName));
ctx.refresh();

Book javaBook = ctx.getBean(bookName, Book.class);
assertNotNull(javaBook);
assertEquals(javaBook.getName(), bookName);

在Spring测试中,可以看到方法的作者提供的另一种使用方式:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
RootBeanDefinition bd = new RootBeanDefinition();
bd.setInstanceSupplier(NonInstantiatedFactoryBean::new);
bd.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class, String.class));
bd.setLazyInit(true);
context.registerBeanDefinition("fb", bd);
context.refresh();

assertThat(context.getType("fb")).isEqualTo(String.class);
assertThat(context.getType("&fb")).isEqualTo(FactoryBean.class);
assertThat(context.getBeanNamesForType(FactoryBean.class)).hasSize(1);
assertThat(context.getBeanNamesForType(NonInstantiatedFactoryBean.class)).isEmpty();
2. FactoryMethodName

<factory-method/>有两种使用方法,初始化Bean的逻辑都在ConstructorResolver#instantiateUsingFactoryMethod中。

第一种,不指定factory-bean, 那必须是静态方法

<bean name="test" class="beans.Config" factory-method="getInstance">
    <constructor-arg name="name" value="类别"/>
</bean>
public class Config {
    public static Bookshelf getInstance(String name) {
        return new Bookshelf(name);
    }
}

第二种,指定factory-bean
那么会先通过getBean方法,创建factory-bean对应的bean。

初始化bean通过反射来实现,实现在SimpleInstantiationStrategy#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);
			if (result == null) {
				result = new NullBean();
			}
			return result;
		}
3. 如果存在构造参数

如果存在构造参数,那么将使用ConstructorResolver#autowireConstructor来初始化Bean。

再决定好使用哪个构造参数,已经处理好参数之后,将通过ConstructorResolver#instantiate来初始化

private Object instantiate(
		String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {

	try {
		InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
		if (System.getSecurityManager() != null) {
			return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
					strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
					this.beanFactory.getAccessControlContext());
		}
		else {
			return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
		}
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
				"Bean instantiation via constructor failed", ex);
	}
}

继续调用SimpleInstantiationStrategy#instantiate,通过反射来创建并初始化bean

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
		final Constructor<?> ctor, Object... args) {

	if (!bd.hasMethodOverrides()) {
		if (System.getSecurityManager() != null) {
			// use own privileged to change accessibility (when security is on)
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				ReflectionUtils.makeAccessible(ctor);
				return null;
			});
		}
		return BeanUtils.instantiateClass(ctor, args);
	}
	else {
		return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
	}
}

如果构造参数依赖其他bean,比如像下面的配置:

<bean id="javaBook" class="beans.dependency.Book">
    <constructor-arg name="name" value="Java"/>
</bean>

<bean id="pythonBook" class="beans.dependency.Book">
    <constructor-arg name="name" value="Python"/>
</bean>

<bean id="bookShelf2" class="beans.dependency.Bookshelf">
    <constructor-arg name="books">
        <list>
            <ref bean="javaBook"/>
            <ref bean="pythonBook"/>
        </list>
    </constructor-arg>
</bean>

那么在创建bookShelf2之前,在ConstructorResolver#resolveConstructorArguments中先一步构造参数中的bean, 具体处理交给BeanDefinitionValueResolver#resolveValueIfNecessary:

public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
	// We must check each value to see whether it requires a runtime reference
	// to another bean to be resolved.
	if (value instanceof RuntimeBeanReference) {
		RuntimeBeanReference ref = (RuntimeBeanReference) value;
		return resolveReference(argName, ref);
	}
	else if (value instanceof RuntimeBeanNameReference) {
		String refName = ((RuntimeBeanNameReference) value).getBeanName();
		refName = String.valueOf(doEvaluate(refName));
		if (!this.beanFactory.containsBean(refName)) {
			throw new BeanDefinitionStoreException(
					"Invalid bean name '" + refName + "' in bean reference for " + argName);
		}
		return refName;
	}
	... 省略
4. 默认构造方法

如果上面都没有将使用默认构造方法来初始化Bean, AbstractAutowireCapableBeanFactory#instantiateBean

protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
		try {
			Object beanInstance;
			if (System.getSecurityManager() != null) {
				beanInstance = AccessController.doPrivileged(
						(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
						getAccessControlContext());
			}
			else {
				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
			}
			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
			initBeanWrapper(bw);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
		}
	}

可以看到初始化还是交由,org.springframework.beans.factory.support.SimpleInstantiationStrategy#instantiate来初始化

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<?>>)z 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.
		return instantiateWithMethodInjection(bd, beanName, owner);
	}
}
doCreateBean - EarlyBeanReference

在初始之后,属性设置之前,会先将beanName以及对应的singletonFactory记录下来,这样做的主要原因是为了解决循环依赖(属性设置才可以,构造方法循环依赖无法解决)。

可以看成,通过这个singletonFactory可以得到一个bean的不完整版本,即EarlyBean。

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
		isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
	if (logger.isTraceEnabled()) {
		logger.trace("Eagerly caching bean '" + beanName +
				"' to allow for resolving potential circular references");
	}
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

/**
 * Obtain a reference for early access to the specified bean,
 * typically for the purpose of resolving a circular reference.
 * @param beanName the name of the bean (for error handling purposes)
 * @param mbd the merged bean definition for the bean
 * @param bean the raw bean instance
 * @return the object to expose as bean reference
 */
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
	Object exposedObject = bean;
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
			exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
		}
	}
	return exposedObject;
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(singletonFactory, "Singleton factory must not be null");
	synchronized (this.singletonObjects) {
		if (!this.singletonObjects.containsKey(beanName)) {
			this.singletonFactories.put(beanName, singletonFactory);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}
}
doCreateBean - 属性设置
// AbstractAutowireCapableBeanFactory#populateBean
populateBean(beanName, mbd, instanceWrapper);

首先,对所有需要设置的属性的value进行处理,比如属性是依赖的bean, 那么需要先初始化这些Bean;

value处理好之后,交给org.springframework.beans.AbstractPropertyAccessor#setPropertyValues》

BeanWrapperImpl继承了AbstractPropertyAccessor,所以实际上是BeanWrapperImpl在处理

// Set our (possibly massaged) deep copy.
try {
	bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}

现在比较好奇的是,知道配置的属性名称以及对应的value, 那么spring是如何找到对应的方法来设置的呢?继续跟踪下去,可以在AbstractNestablePropertyAccessor#processLocalProperty找到下面的代码

(BeanWrapperImpl继承了AbstractNestablePropertyAccessor,所以实际上是BeanWrapperImpl在处理)

private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
	PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
	if (ph == null || !ph.isWritable()) {
		if (pv.isOptional()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Ignoring optional value for property '" + tokens.actualName +
						"' - property not found on bean class [" + getRootClass().getName() + "]");
			}
			return;
		}
		if (this.suppressNotWritablePropertyException) {
			// Optimization for common ignoreUnknown=true scenario since the
			// exception would be caught and swallowed higher up anyway...
			return;
		}
		throw createNotWritablePropertyException(tokens.canonicalName);
	}

	Object oldValue = null;
	try {
		Object originalValue = pv.getValue();
		Object valueToApply = originalValue;
		if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
			if (pv.isConverted()) {
				valueToApply = pv.getConvertedValue();
			}
			else {
				if (isExtractOldValueForEditor() && ph.isReadable()) {
					try {
						oldValue = ph.getValue();
					}
					catch (Exception ex) {
						if (ex instanceof PrivilegedActionException) {
							ex = ((PrivilegedActionException) ex).getException();
						}
						if (logger.isDebugEnabled()) {
							logger.debug("Could not read previous value of property '" +
									this.nestedPath + tokens.canonicalName + "'", ex);
						}
					}
				}
				valueToApply = convertForProperty(
						tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor());
			}
			pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
		}
		ph.setValue(valueToApply);
	}

第一句就是 getLocalPropertyHandler(tokens.actualName) , 就是通过它找到对应的set方法的:

protected BeanPropertyHandler getLocalPropertyHandler(String propertyName) {
	PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(propertyName);
	return (pd != null ? new BeanPropertyHandler(pd) : null);
}

其中,CachedIntrospectionResults#getPropertyDescriptor本身很简单,就是根据属性名获取PropertyDescriptor ;

PropertyDescriptor getPropertyDescriptor(String name) {
	PropertyDescriptor pd = this.propertyDescriptors.get(name);
	if (pd == null && StringUtils.hasLength(name)) {
		// Same lenient fallback checking as in Property...
		pd = this.propertyDescriptors.get(StringUtils.uncapitalize(name));
		if (pd == null) {
			pd = this.propertyDescriptors.get(StringUtils.capitalize(name));
		}
	}
	return pd;
}

那么propertyDescriptors必然是再getPropertyDescriptor之前初始化的,再getCachedIntrospectionResults可以找到CachedIntrospectionResults 的创建:

	private CachedIntrospectionResults getCachedIntrospectionResults() {
		if (this.cachedIntrospectionResults == null) {
			this.cachedIntrospectionResults = CachedIntrospectionResults.forClass(getWrappedClass());
		}
		return this.cachedIntrospectionResults;
	}

跟踪进去可以发现beanInfo这个属性起着比较重要的作用,正是它提供了获取所有PropertyDescriptor的接口

PropertyDescriptor[] getPropertyDescriptors();

而BeanInfo的构建有java.beans.Introspector#getBeanInfo(java.lang.Class<?>)来完成:

public static BeanInfo getBeanInfo(Class<?> beanClass)
    throws IntrospectionException
{
    if (!ReflectUtil.isPackageAccessible(beanClass)) {
        return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo();
    }
    ThreadGroupContext context = ThreadGroupContext.getContext();
    BeanInfo beanInfo;
    synchronized (declaredMethodCache) {
        beanInfo = context.getBeanInfo(beanClass);
    }
    if (beanInfo == null) {
        beanInfo = new Introspector(beanClass, null, USE_ALL_BEANINFO).getBeanInfo();
        synchronized (declaredMethodCache) {
            context.putBeanInfo(beanClass, beanInfo);
        }
    }
    return beanInfo;
}

private BeanInfo getBeanInfo() throws IntrospectionException {

    // the evaluation order here is import, as we evaluate the
    // event sets and locate PropertyChangeListeners before we
    // look for properties.
    BeanDescriptor bd = getTargetBeanDescriptor();
    MethodDescriptor mds[] = getTargetMethodInfo();
    EventSetDescriptor esds[] = getTargetEventInfo();
    PropertyDescriptor pds[] = getTargetPropertyInfo();

    int defaultEvent = getTargetDefaultEventIndex();
    int defaultProperty = getTargetDefaultPropertyIndex();

    return new GenericBeanInfo(bd, esds, defaultEvent, pds,
                    defaultProperty, mds, explicitBeanInfo);

}

在这里终于找了PropertyDescriptor的创建,可以看到setter和getter对应的属性名称,就是去掉"get"和"set"之后的名称:

private PropertyDescriptor[] getTargetPropertyInfo() {

       // Check if the bean has its own BeanInfo that will provide
       // explicit information.
       PropertyDescriptor[] explicitProperties = null;
       if (explicitBeanInfo != null) {
           explicitProperties = getPropertyDescriptors(this.explicitBeanInfo);
       }

       if (explicitProperties == null && superBeanInfo != null) {
           // We have no explicit BeanInfo properties.  Check with our parent.
           addPropertyDescriptors(getPropertyDescriptors(this.superBeanInfo));
       }

       for (int i = 0; i < additionalBeanInfo.length; i++) {
           addPropertyDescriptors(additionalBeanInfo[i].getPropertyDescriptors());
       }

       if (explicitProperties != null) {
           // Add the explicit BeanInfo data to our results.
           addPropertyDescriptors(explicitProperties);

       } else {

           // Apply some reflection to the current class.

           // First get an array of all the public methods at this level
           Method methodList[] = getPublicDeclaredMethods(beanClass);

           // Now analyze each method.
           for (int i = 0; i < methodList.length; i++) {
               Method method = methodList[i];
               if (method == null) {
                   continue;
               }
               // skip static methods.
               int mods = method.getModifiers();
               if (Modifier.isStatic(mods)) {
                   continue;
               }
               String name = method.getName();
               Class<?>[] argTypes = method.getParameterTypes();
               Class<?> resultType = method.getReturnType();
               int argCount = argTypes.length;
               PropertyDescriptor pd = null;

               if (name.length() <= 3 && !name.startsWith(IS_PREFIX)) {
                   // Optimization. Don't bother with invalid propertyNames.
                   continue;
               }

               try {

                   if (argCount == 0) {
                       if (name.startsWith(GET_PREFIX)) {
                           // Simple getter
                           pd = new PropertyDescriptor(this.beanClass, name.substring(3), method, null);
                       } else if (resultType == boolean.class && name.startsWith(IS_PREFIX)) {
                           // Boolean getter
                           pd = new PropertyDescriptor(this.beanClass, name.substring(2), method, null);
                       }
                   } else if (argCount == 1) {
                       if (int.class.equals(argTypes[0]) && name.startsWith(GET_PREFIX)) {
                           pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, method, null);
                       } else if (void.class.equals(resultType) && name.startsWith(SET_PREFIX)) {
                           // Simple setter
                           pd = new PropertyDescriptor(this.beanClass, name.substring(3), null, method);
                           if (throwsException(method, PropertyVetoException.class)) {
                               pd.setConstrained(true);
                           }
                       }
                   } else if (argCount == 2) {
                           if (void.class.equals(resultType) && int.class.equals(argTypes[0]) && name.startsWith(SET_PREFIX)) {
                           pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, null, method);
                           if (throwsException(method, PropertyVetoException.class)) {
                               pd.setConstrained(true);
                           }
                       }
                   }
               } catch (IntrospectionException ex) {
                   // This happens if a PropertyDescriptor or IndexedPropertyDescriptor
                   // constructor fins that the method violates details of the deisgn
                   // pattern, e.g. by having an empty name, or a getter returning
                   // void , or whatever.
                   pd = null;
               }

               if (pd != null) {
                   // If this class or one of its base classes is a PropertyChange
                   // source, then we assume that any properties we discover are "bound".
                   if (propertyChangeSource) {
                       pd.setBound(true);
                   }
                   addPropertyDescriptor(pd);
               }
           }
       }
       processPropertyDescriptors();

       // Allocate and populate the result array.
       PropertyDescriptor result[] =
               properties.values().toArray(new PropertyDescriptor[properties.size()]);

       // Set the default index.
       if (defaultPropertyName != null) {
           for (int i = 0; i < result.length; i++) {
               if (defaultPropertyName.equals(result[i].getName())) {
                   defaultPropertyIndex = i;
               }
           }
       }

       return result;
   }

属性的名称也是要处理一下的,比如通常需要首字符小写,从下面的代码可以看到:

  1. 当“set”之后的名称长度大于1,且前两个字符都是大写的时候,保留这个字符串
  2. 否则的话,将首字母小写

/**
 * Utility method to take a string and convert it to normal Java variable
 * name capitalization.  This normally means converting the first
 * character from upper case to lower case, but in the (unusual) special
 * case when there is more than one character and both the first and
 * second characters are upper case, we leave it alone.
 * <p>
 * Thus "FooBah" becomes "fooBah" and "X" becomes "x", but "URL" stays
 * as "URL".
 *
 * @param  name The string to be decapitalized.
 * @return  The decapitalized version of the string.
 */
public static String decapitalize(String name) {
    if (name == null || name.length() == 0) {
        return name;
    }
    if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
                    Character.isUpperCase(name.charAt(0))){
        return name;
    }
    char chars[] = name.toCharArray();
    chars[0] = Character.toLowerCase(chars[0]);
    return new String(chars);
}
doCreateBean - 属性设置好之后的initializeBean
//AbstractAutowireCapableBeanFactory#initializeBean
exposedObject = initializeBean(beanName, exposedObject, mbd);

主要包括四部分内容:

  1. invokeAwareMethods,处理三个Aware:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
    private void invokeAwareMethods(String beanName, Object bean) {
    	if (bean instanceof Aware) {
    		if (bean instanceof BeanNameAware) {
    			((BeanNameAware) bean).setBeanName(beanName);
    		}
    		if (bean instanceof BeanClassLoaderAware) {
    			ClassLoader bcl = getBeanClassLoader();
    			if (bcl != null) {
    				((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
    			}
    		}
    		if (bean instanceof BeanFactoryAware) {
    			((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    		}
    	}
    }
    
  2. applyBeanPostProcessorsBeforeInitialization
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
    		throws BeansException {
    
    	Object result = existingBean;
    	for (BeanPostProcessor processor : getBeanPostProcessors()) {
    		Object current = processor.postProcessBeforeInitialization(result, beanName);
    		if (current == null) {
    			return result;
    		}
    		result = current;
    	}
    	return result;
    }
    
  3. invokeInitMethods, 主要是执行afterPropertiesSet或者用户自定义的初始化方法
    protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
    		throws Throwable {
    
    	boolean isInitializingBean = (bean instanceof InitializingBean);
    	if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
    		if (logger.isTraceEnabled()) {
    			logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
    		}
    		if (System.getSecurityManager() != null) {
    			try {
    				AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
    					((InitializingBean) bean).afterPropertiesSet();
    					return null;
    				}, getAccessControlContext());
    			}
    			catch (PrivilegedActionException pae) {
    				throw pae.getException();
    			}
    		}
    		else {
    			((InitializingBean) bean).afterPropertiesSet();
    		}
    	}
    
    	if (mbd != null && bean.getClass() != NullBean.class) {
    		String initMethodName = mbd.getInitMethodName();
    		if (StringUtils.hasLength(initMethodName) &&
    				!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
    				!mbd.isExternallyManagedInitMethod(initMethodName)) {
    			invokeCustomInitMethod(beanName, bean, mbd);
    		}
    	}
    }
    
  4. applyBeanPostProcessorsAfterInitialization
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    		throws BeansException {
    
    	Object result = existingBean;
    	for (BeanPostProcessor processor : getBeanPostProcessors()) {
    		Object current = processor.postProcessAfterInitialization(result, beanName);
    		if (current == null) {
    			return result;
    		}
    		result = current;
    	}
    	return result;
    }
    
doCreateBean - registerDisposableBeanIfNecessary

/**
 * Add the given bean to the list of disposable beans in this factory,
 * registering its DisposableBean interface and/or the given destroy method
 * to be called on factory shutdown (if applicable). Only applies to singletons.
 * @param beanName the name of the bean
 * @param bean the bean instance
 * @param mbd the bean definition for the bean
 * @see RootBeanDefinition#isSingleton
 * @see RootBeanDefinition#getDependsOn
 * @see #registerDisposableBean
 * @see #registerDependentBean
 */
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
	AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
	if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
		if (mbd.isSingleton()) {
			// Register a DisposableBean implementation that performs all destruction
			// work for the given bean: DestructionAwareBeanPostProcessors,
			// DisposableBean interface, custom destroy method.
			registerDisposableBean(beanName, new DisposableBeanAdapter(
					bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
		}
		else {
			// A bean with a custom scope...
			Scope scope = this.scopes.get(mbd.getScope());
			if (scope == null) {
				throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
			}
			scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(
					bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
		}
	}
}

根据名称获取Bean的实例化总结

  1. 获取到GenericBeanDefinition对象,构造RootBeanDefinition,同时如果当前是个Child bean会合并parent的一些配置
  2. 提供由InstantiationAwareBeanPostProcessor 提前创建代理的机会
  3. 根据InstanceSupplier、FactoryMethodName、构造方法来创建Bean对象
  4. 如果是单例的话,提供EarlyBeanReference 对应的工厂方法,用以解决循环依赖
  5. populateBean 设置属性
  6. initializeBean
    • 根据Aware初始化不同的属性 ,如beanName、beanFacory
    • BeanPostProcessor#applyBeanPostProcessorsBeforeInitialization
    • 主要是执行afterPropertiesSet或者用户自定义的初始化方法
    • BeanPostProcessor#applyBeanPostProcessorsAfterInitialization
  7. registerDisposableBeanIfNecessary

补充

Aware

我们知道,如果对应的bean实现了ApplicationContextAware,那么会将applicationContext设置到当前bean。但是,上面的Aware部分并没有ApplicationContextAware,所以它是在其他地方初始化。

可以在ApplicationContextAwareProcessor找到相应的代码,它是BeanPostProcessor的一类实现:

	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
				bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
				bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
				bean instanceof ApplicationStartupAware)) {
			return bean;
		}

		AccessControlContext acc = null;

		if (System.getSecurityManager() != null) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}
	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof EnvironmentAware) {
			((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
		}
		if (bean instanceof EmbeddedValueResolverAware) {
			((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
		}
		if (bean instanceof ResourceLoaderAware) {
			((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
		}
		if (bean instanceof ApplicationEventPublisherAware) {
			((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
		}
		if (bean instanceof MessageSourceAware) {
			((MessageSourceAware) bean).setMessageSource(this.applicationContext);
		}
		if (bean instanceof ApplicationStartupAware) {
			((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
		}
		if (bean instanceof ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		}
	}

通过类型获取Bean

	private <T> NamedBeanHolder<T> resolveNamedBean(
			ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {

		Assert.notNull(requiredType, "Required type must not be null");
		String[] candidateNames = getBeanNamesForType(requiredType);

		if (candidateNames.length > 1) {
			List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
			for (String beanName : candidateNames) {
				if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
					autowireCandidates.add(beanName);
				}
			}
			if (!autowireCandidates.isEmpty()) {
				candidateNames = StringUtils.toStringArray(autowireCandidates);
			}
		}

		if (candidateNames.length == 1) {
			String beanName = candidateNames[0];
			return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
		}
		else if (candidateNames.length > 1) {
			Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length);
			for (String beanName : candidateNames) {
				if (containsSingleton(beanName) && args == null) {
					Object beanInstance = getBean(beanName);
					candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
				}
				else {
					candidates.put(beanName, getType(beanName));
				}
			}
			String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
			if (candidateName == null) {
				candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
			}
			if (candidateName != null) {
				Object beanInstance = candidates.get(candidateName);
				if (beanInstance == null || beanInstance instanceof Class) {
					beanInstance = getBean(candidateName, requiredType.toClass(), args);
				}
				return new NamedBeanHolder<>(candidateName, (T) beanInstance);
			}
			if (!nonUniqueAsNull) {
				throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
			}
		}

		return null;
	}

大致过程是

  1. 先根据类型从所有的beanDefinition中找到类型匹配的beanNames
  2. 如果匹配的只有一个,那么还是通过名称来获取bean
  3. 如果匹配的有多个,那么找一个Primary Bean
  4. 如果没有的话,则找一个Priority最高的一个的Bean
  5. 如果都找不到的话,报错找不到唯一的bean
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值