springbootbean的实例化过程和属性注⼊过程
了解过springboot的加载流程的都知道springboot初始化bean都在refresh⽅法中。这个⽅法代码如下:
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.新建beanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
/
/ Invoke factory processors registered as beans in the context.
// 加载实现beanFactoryPostProcessor的bean,bean定义的时候执⾏
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 加载实现了beanPostProcessor,在bean实例化前、后执⾏
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//实例化⾮懒加载的bean、bean封装、属性注⼊、注解注⼊(主要使⽤BeanPostProcessor或⼦类实现)等
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
这⾥我们主要看下finishBeanfactoryInitialization⽅法。此⽅法实现了bean的实例和属性注⼊等。进⼊此⽅法的最后⼀⾏。
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
注释写的很清楚,实例化剩余⾮懒加载的bean。此⽅法的实现是核⼼类DefaultLisListableBeanFactory实现。这个⽅法中有个判断:bean是否是beanFactory的实现类。如果是则获取bean的时候会从beanFactory实现类的getObject中获取,我们重点看看getBean这个⽅法。getBean是spring中最重要、最⽜逼的⽅法之⼀, 具体的逻辑是通过doGetBean⽅法处理的。我们看下doGetBean⽅法,⽅法很长。我们分成⼏个部分去看。
1、先判断是否已经存在缓存中,代码如下:
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
2、从⽗beanfactory中获取
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) Bean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
Bean(nameToLookup, requiredType);
}
}
3、直接创建RootBeanDefinition
//mark 给此bean 马克⼀下。防⽌重复创建
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = DependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new ResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
getBean(dep);
}
}
4、是singleton还是prototype类型的,根据不同类型去实例化bean,代码只贴了单例的类型:// Create bean instance.
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;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
5、检查bean的类型是否匹配
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, Class());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
}
throw new BeanNotOfRequiredTypeException(name, requiredType, Class());
}
}
整个doGetBean⽅法改成这5个部分,重点看下第4个部分中的createBean和getObjectForBeanInstance⽅法。
1、createBean⽅法,⾥⾯主要是2个部分,bean直接是通过BeanPostProcessor的postProcessBeforeIntantiation⽅法获取的。注释也是描述的很清楚:Give BeanPostProcessors a chance to return a proxy instead of the bean instance(英语渣渣不敢瞎翻译误导⼤家,理解就好),代码如下:
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 ResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
第⼀个部分⾃⼰实现,那么createBean⽅法第2个部分⽏庸置疑肯定是spring去实例化bean,代码如下:
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
⼜是do开头的⽅法,说明这个也是⼀个创建⽅法,spring中⼀般do开头的都是⽤于创建某个对象。跟着代码⾛,看下doCreateBean⽅法,在查看此⽅法之前,可能需要了解下BeanWarpper这个封装类。bean的封装、属性注⼊等都是⽤BeanWarpper去完成的。看下代码:
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = ve(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
进⼊createBeanInstance⽅法中,就是调⽤构造器去实例化bean,返回beanWrapper。通过构造器获
取实例代码如下:
// Need to determine
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
这⾥实例化我⼀开始以为就是简单的反射,后⾯我点进去时候发现⾥⾯⼀直提策略实例化,我⽬前了
解的是可以解决Override的问题等。如果有兴趣的可以⾃⾏查看。到这⾥为⽌。我们终于实例化bean了。下⾯看下第⼆步bean的属性注⼊等。代码如下:
Object exposedObject = bean;
try {
springboot是啥populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
}
}
populateBean⽅法名称就暴露他是⼲啥的:填充bean。我放⼀段⽐较重要的部分:
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = PropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
这段代码貌似没有什么注⼊、填充什么的,我们看下InstantiationAwareBeanPostProcessor这个接⼝,发现这个接⼝有个很熟悉的实现类是:AutowiredAnnotationBeanPostProcessor。这个类的⽅法中我们看到终于看到了jnject⽅法。但是在inject之前需要调⽤下findAutowiringMatedata⽅法获取⼀下元数据:
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : Name());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = (cacheKey);
if (dsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = (cacheKey);
if (dsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
那么问题⼜来了,这个injectionMetadataCache集合值是从那⾥来的呢?AutowiredAnnotationBeanPostProcessor实现了MergeBeandefinitionPostProcessor,那么就好了,肯定是在bean实例的时候调⽤了postProcessMergedBeanDefintion这个⽅法。果然在doCreateBean⽅法中有这么⼀段:
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
//通过 BeanPostProcessor将需要注解的元数据放到Map中
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new ResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
哎,spring缜密啊。元数据有了,下⾯我们看下element.inject()⽅法是如何操作的:
if (this.isField) {
Field field = (Field) ber;
ReflectionUtils.makeAccessible(field);
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) ber;
ReflectionUtils.makeAccessible(method);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
TargetException();
}
}
⽅法简单明了,直接使⽤反射将值set到属性中,⾄此 bean的实例、属性注⼊基本完成,下⾯我们回头来看doGetBean的另⼀个⽅法getObjectForBeanInstance。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论