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中,解析流程:
-
首先获取id属性的值,将作为beanName。
-
获取name属性的值,可以多值(",; "隔开),将作为别名,但别名会在BeanDefinition解析完成后,单独注册各别名到beanNamed的映射关系;BeanDefinition本身不会记录别名。
-
校验beanName和别名,不能已经被使用,否则报错
-
获取class和parent属性的值,并构造GenericBeanDefinition实例,这里class允许为空
-
解析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
-
description
-
<meta>子元素:BeanMetadataAttribute
-
<lookup-method>子元素:存在两个属性name和bean,记录为LookupOverride,是MethodOverride的子类
-
<replaced-method>子元素:存在两个属性name和replacer,其下还有子元素arg-type; 记录为ReplaceOverride,是MethodOverride的子类
-
<constructor-arg>子元素的解析结果记录在BeanDefinition的属性ConstructorArgumentValues 上
根据<constructor-arg>的ref属性或者value属性,构造RuntimeBeanReference对象或者TypedStringValue对象,作为ValueHolder的value属性。
-
<property>子元素的解析结果将记录在BeanDefinition的属性MutablePropertyValues上
<property>的元素必须要有name属性,ref或value的属性处理同构造参数
-
<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的实例化过程大致如下:
- 由原来的GenericBeanDefinition对象,构造RootBeanDefinition,同时如果当前是个Child bean会合并parent的一些配置
- 如果dependsOn不为空,会先调用getBean来初始化这些依赖的bean
- 然后根据scope是singleton、prototype、其他自定义Scope执行三种不同的实例化方法
真正创建对象的代码在 createBean(beanName, mbd, args);方法中,三类不同的Scope都会执行相同的部分来实例化Bean,它们不同的地方在于: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); } }
- 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; }
- singleton,会在实例化bean之后,将bean记录到容器的singletonObjects上
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 创建代理对象:
- 获取容器所有的BeanPostProcessor 实例
- 遍历BeanPostProcessor 实例,如果也实现了InstantiationAwareBeanPostProcessor,那么执行InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation创建代理
- 在第一个代理创建成功后,后续InstantiationAwareBeanPostProcessor不再执行
- 代理对象创建成功后,获取所有BeanPostProcessor 实例,并执行org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
- 默认情况下,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;
}
属性的名称也是要处理一下的,比如通常需要首字符小写,从下面的代码可以看到:
- 当“set”之后的名称长度大于1,且前两个字符都是大写的时候,保留这个字符串
- 否则的话,将首字母小写
/**
* 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);
主要包括四部分内容:
- 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); } } }
- 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; }
- 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); } } }
- 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的实例化总结
- 获取到GenericBeanDefinition对象,构造RootBeanDefinition,同时如果当前是个Child bean会合并parent的一些配置
- 提供由InstantiationAwareBeanPostProcessor 提前创建代理的机会
- 根据InstanceSupplier、FactoryMethodName、构造方法来创建Bean对象
- 如果是单例的话,提供EarlyBeanReference 对应的工厂方法,用以解决循环依赖
- populateBean 设置属性
- initializeBean
- 根据Aware初始化不同的属性 ,如beanName、beanFacory
- BeanPostProcessor#applyBeanPostProcessorsBeforeInitialization
- 主要是执行afterPropertiesSet或者用户自定义的初始化方法
- BeanPostProcessor#applyBeanPostProcessorsAfterInitialization
- 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;
}
大致过程是
- 先根据类型从所有的beanDefinition中找到类型匹配的beanNames
- 如果匹配的只有一个,那么还是通过名称来获取bean
- 如果匹配的有多个,那么找一个Primary Bean
- 如果没有的话,则找一个Priority最高的一个的Bean
- 如果都找不到的话,报错找不到唯一的bean