Spring源码之IoC容器的Bean创建和依赖注入,DefaultListableBeanFactory容器为例
接上篇Spring源码之IoC容器初始化过程,以FileSystemXmlApplicationContext容器为例
因为FileSystemXmlApplicationContext使用的容器为DefaultListableBeanFactory,所以该篇基于DefaultListableBeanFactory的实现分析依赖注入过程。
目录
- 获取Bean的总体流程
- Bean对象的实例化
- Bean对象依赖关系的注入
- 总结:
- 源码
- doGetBean方法源码
- createBean方法
- doCreateBean方法
- createBeanInstance方法创建对象
- instantiateBean方法
- 通过反射创建对象
- 通过CGLIB创建对象
- createEnhancedSubclass方法
- populateBean方法设置依赖关系
- populateBean方法
- applyPropertyValues方法
- resolveValueIfNecessary方法
- resolveReference方法
获取Bean的总体流程
getBean流程:
依赖注入通过BeanFactory的getBean方法触发。
DefaultListableBeanFactory的getBean方法通过继承AbstractAutowireCapableBeanFactory,AbstractAutowireCapableBeanFactory继承AbstractBeanFactory获得,具体的实现在AbstractBeanFactory中。
1、通过getBean方法触发依赖注入
2、getBean方法调用doGetBean方法,这是实际触发依赖注入的方法
3、先从缓存中取得Bean,处理那些已经被创建过的单件模式的Bean,对这种Bean的请求不需要重复的创建
4、如果从缓存中获得Bean,通过getObjectForBeanInstance方法完成FactoryBean的相关处理,取得FactoryBean的处理结果。
5、如果从缓存中未获得Bean,并且双亲BeanFactory不为null。检查当前IoC容器中是否存在对应的BeanDefinition,也就是检查是否能在当前的BeanFactory的Map中取得需要的Bean。
6、如果在当前的BeanFactory工厂中取不到BeanDefinition,则到双亲BeanFactory中取,也就是调用双亲BeanFactory的getBean方法。如果在当前的双亲工厂中还取不到,则递归顺着双亲BeanFactory链一直向上查找。
7、如果双亲BeanFactory为null,或者当前IoC容器中存在对应的BeanDefinition,根据Bean的名称获取BeanDefinition。
8、获取当前Bean的所有依赖的Bean名称,把依赖的Bean注册到dependentBeanMap中。并调用getBean方法注册每个依赖Bean的依赖Bean。调用getBean方法传入依赖Bean名称,这样会触发getBean的递归调用,直到取到一个没有任何依赖的Bean为止。
9、判断Bean是Singleton还是Prototype,通过调用createBean方法创建Bean实例,通过getObjectForBeanInstance方法完成FactoryBean的相关处理。
10、最后对Bean进行类型检查,如果没问题,则返回这个新创建的Bean,这个Bean是包含了依赖关系的Bean。
Bean对象的实例化
createBean方法流程:
该方法在AbstractAutowireCapableBeanFactory中实现
1、判断需要创建的Bean是否可以实例化,这个类是否可以通过类装载器来载入
2、如果Bean配置了PostProcessor,则获取一个proxy代理对象。
3、createBean调用doCreateBean创建Bean。doCreateBean中,用一个BeanWrapper持有创建出来的Bean对象。
4、如果是Singleton,先把缓存中的同名Bean清除。如果缓存找那个存在对应的Bean,则返回对应的Bean并作为即将获取的Bean,如果缓存中不存在,则调用createBeanInstance创建Bean对象。
5、调用populateBean方法对Bean进行初始化,以及依赖关系的注入。
createBeanInstance方法:
1、确认需要创建的Bean实例的类可以实例化。
2、如果instanceSupplier不为空,则通过instanceSupplier直接获取实例。
3、如果有工厂方法,则通过工厂方法对Bean进行实例化。
4、以上两种情况都不满足,则使用构造函数进行实例化。
5、通过构造函数后置处理器determineConstructorsFromBeanPostProcessors, 来选择使用哪个构造函数来实例化Bean。
6、如果构造函数后置处理器返回的构造函数为空,则用默认的构造函数对Bean进行实例化。通过instantiateBean(beanName, mbd)方法进行实例化。
instantiateBean方法:
1、使用默认的实例化策略对Bean进行实例化,默认的策略是使用CGLIB来对Bean进行实例化。
2、调用instantiate实例化Bean
SimpleInstantiationStrategy中的instantiate方法:
MethodOverrides的作用是在spring配置中存在lookup-mehtod和rreplace-method的,而这两个配置在加载xml的时候就会统一存放在BeanDefinition中的methodOverrides属性里
1、判断MethodOverrides是否为空,不为空时,使用CGLIB来实例化对象。
2、MethodOverrides为空时,取得指定的构造器或者生成对象的工厂方法来对Bean进行实例化,通过BeanUtils进行实例化,BeanUtils通过Constructor来实例化Bean,使用的是JVM的反射功能。
Bean对象依赖关系的注入
populateBean方法:
1、在创建Bean后,执行Bean的后置处理BeanPostProcessor
2、获取Bean的所有属性PropertyValues
3、开始进行依赖注入,先处理autowire的注入
4、根据Bean的名字或者类型,调用autowireByName或autowireByType方法,来完成Bean的autowire注入
5、调用applyPropertyValues对属性进行注入
6、applyPropertyValues中,通过BeanDefinitionValueResolver对BeanDefinition进行解析,applyPropertyValues方法调用了resolveValueIfNecessary方法,resolveValueIfNecessary方法调用了resolveReference方法,resolveValueIfNecessary包含了所有对注入类型的处理。
7、通过bw.setPropertyValues(new MutablePropertyValues(deepCopy));进行依赖注入
resolveReference方法:
1、根据RuntimeBeanReference判断每个PropertyValue,也就是依赖对象,是否在双亲IoC容器中
2、如果是在双亲IoC容器中,Bean的类型不为空,根据类型从双亲IoC容器中获取Bean,否则根据名字从双亲IoC容器中获取Bean
3、如果不在双亲IoC容器中,从当前容器获取Bean的实例和名字,调用当前容器的getBean获取
4、完成以上步骤后,已经为依赖注入准备好了条件,接下来就是真正注入的方法,在BeanWrapper的setPropertyValues中实现的,具体是在BeanWrapperImpl中实现的。
5、通过bw.setPropertyValues方法,遍历所有的PropertyValue,挨个进行设置
6、最终在BeanWrapperImpl中的setValue方法中,通过反射进行注入
总结:
在Bean的创建爱你和对象依赖注入的过程中,需要依据BeanDefinition中的信息来递归地完成依赖注入。从上面的几个递归过程中可以看到,这些递归都是以getBean为入口的。
一个递归是在上下文体系中查找需要的Bean和创建Bean的递归调用;另一个递归是在依赖注入时,通过递归调用容器的getBean方法,得到当前Bean的依赖Bean,同时也触发对依赖Bean的创建和注入。
在对Bean的属性进行依赖注入时,解析的过程也是一个递归的过程。这样,根据依赖关系,一层一层地完成Bean的创建和注入,直到最后完成当前Bean的创建。有了这个顶层Bean的创建和对它的属性依赖注入的完成,意味着和当前Bean相关的整个依赖链的注入也完成了。
源码
BeanFactory中定义了getBean方法,依赖注入正是通过getBean方法触发
public interface BeanFactory {String FACTORY_BEAN_PREFIX = "&";Object getBean(String var1) throws BeansException;<T> T getBean(String var1, Class<T> var2) throws BeansException;Object getBean(String var1, Object... var2) throws BeansException;<T> T getBean(Class<T> var1) throws BeansException;<T> T getBean(Class<T> var1, Object... var2) throws BeansException;<T> ObjectProvider<T> getBeanProvider(Class<T> var1);<T> ObjectProvider<T> getBeanProvider(ResolvableType var1);boolean containsBean(String var1);boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;@NullableClass<?> getType(String var1) throws NoSuchBeanDefinitionException;@NullableClass<?> getType(String var1, boolean var2) throws NoSuchBeanDefinitionException;String[] getAliases(String var1);
}
doGetBean方法源码
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {String beanName = this.transformedBeanName(name);// 先从缓存中取得Bean,处理那些已经被创建过的单件模式的Bean,对这种Bean的请求不需要重复的创建Object sharedInstance = this.getSingleton(beanName);Object bean;if (sharedInstance != null && args == null) {if (this.logger.isTraceEnabled()) {if (this.isSingletonCurrentlyInCreation(beanName)) {this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");} else {this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");}}// 如果从缓存中获得Bean,通过getObjectForBeanInstance方法完成FactoryBean的相关处理,// 取得FactoryBean的处理结果。bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);} else {if (this.isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// 如果从缓存中未获得Bean,并且双亲BeanFactory不为null。// 检查当前IoC容器中是否存在对应的BeanDefinition,也就是检查是否能在当前的BeanFactory的Map中取得需要的Bean。BeanFactory parentBeanFactory = this.getParentBeanFactory();if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {// 如果在当前的BeanFactory工厂中取不到BeanDefinition,则到双亲BeanFactory中取,// 也就是调用双亲BeanFactory的getBean方法。如果在当前的双亲工厂中还取不到,// 则递归顺着双亲BeanFactory链一直向上查找。String nameToLookup = this.originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}if (args != null) {return parentBeanFactory.getBean(nameToLookup, args);}if (requiredType != null) {return parentBeanFactory.getBean(nameToLookup, requiredType);}return parentBeanFactory.getBean(nameToLookup);}if (!typeCheckOnly) {this.markBeanAsCreated(beanName);}// 如果双亲BeanFactory为null,或者当前IoC容器中存在对应的BeanDefinition,// 根据Bean的名称获取BeanDefinition。try {RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);this.checkMergedBeanDefinition(mbd, beanName, args);String[] dependsOn = mbd.getDependsOn();String[] var11;if (dependsOn != null) {var11 = dependsOn;int var12 = dependsOn.length;// 获取当前Bean的所有依赖的Bean名称,把依赖的Bean注册到dependentBeanMap中。// 并调用getBean方法注册每个依赖Bean的依赖Bean。for(int var13 = 0; var13 < var12; ++var13) {String dep = var11[var13];if (this.isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}this.registerDependentBean(dep, beanName);try {this.getBean(dep);} catch (NoSuchBeanDefinitionException var24) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);}}}// 判断Bean是Singleton还是Prototype,通过调用createBean方法创建Bean实例,// 通过getObjectForBeanInstance方法完成FactoryBean的相关处理。if (mbd.isSingleton()) {sharedInstance = this.getSingleton(beanName, () -> {try {return this.createBean(beanName, mbd, args);} catch (BeansException var5) {this.destroySingleton(beanName);throw var5;}});bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);} else if (mbd.isPrototype()) {var11 = null;Object prototypeInstance;try {this.beforePrototypeCreation(beanName);prototypeInstance = this.createBean(beanName, mbd, args);} finally {this.afterPrototypeCreation(beanName);}bean = this.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 = (Scope)this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, () -> {this.beforePrototypeCreation(beanName);Object var4;try {var4 = this.createBean(beanName, mbd, args);} finally {this.afterPrototypeCreation(beanName);}return var4;});bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);} catch (IllegalStateException var23) {throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var23);}}} catch (BeansException var26) {this.cleanupAfterBeanCreationFailure(beanName);throw var26;}}// 最后对Bean进行类型检查,如果没问题,// 则返回这个新创建的Bean,这个Bean是包含了依赖关系的Bean。if (requiredType != null && !requiredType.isInstance(bean)) {try {T convertedBean = this.getTypeConverter().convertIfNecessary(bean, requiredType);if (convertedBean == null) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());} else {return convertedBean;}} catch (TypeMismatchException var25) {if (this.logger.isTraceEnabled()) {this.logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var25);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}} else {return bean;}}
createBean方法
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {if (this.logger.isTraceEnabled()) {this.logger.trace("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}try {mbdToUse.prepareMethodOverrides();} catch (BeanDefinitionValidationException var9) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9);}Object beanInstance;try {beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);if (beanInstance != null) {return beanInstance;}} catch (Throwable var10) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);}try {beanInstance = this.doCreateBean(beanName, mbdToUse, args);if (this.logger.isTraceEnabled()) {this.logger.trace("Finished creating instance of bean '" + beanName + "'");}return beanInstance;} catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {throw var7;} catch (Throwable var8) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);}}
doCreateBean方法
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {instanceWrapper = this.createBeanInstance(beanName, mbd, args);}Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}synchronized(mbd.postProcessingLock) {if (!mbd.postProcessed) {try {this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);} catch (Throwable var17) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);}mbd.postProcessed = true;}}boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);if (earlySingletonExposure) {if (this.logger.isTraceEnabled()) {this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");}this.addSingletonFactory(beanName, () -> {return this.getEarlyBeanReference(beanName, mbd, bean);});}Object exposedObject = bean;try {this.populateBean(beanName, mbd, instanceWrapper);exposedObject = this.initializeBean(beanName, exposedObject, mbd);} catch (Throwable var18) {if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {throw (BeanCreationException)var18;}throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);}if (earlySingletonExposure) {Object earlySingletonReference = this.getSingleton(beanName, false);if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {String[] dependentBeans = this.getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);String[] var12 = dependentBeans;int var13 = dependentBeans.length;for(int var14 = 0; var14 < var13; ++var14) {String dependentBean = var12[var14];if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");}}}}try {this.registerDisposableBeanIfNecessary(beanName, bean, mbd);return exposedObject;} catch (BeanDefinitionValidationException var16) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);}}
createBeanInstance方法创建对象
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());} else {Supplier<?> instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {return this.obtainFromSupplier(instanceSupplier, beanName);} else if (mbd.getFactoryMethodName() != null) {return this.instantiateUsingFactoryMethod(beanName, mbd, args);} else {boolean resolved = false;boolean autowireNecessary = false;if (args == null) {synchronized(mbd.constructorArgumentLock) {if (mbd.resolvedConstructorOrFactoryMethod != null) {resolved = true;autowireNecessary = mbd.constructorArgumentsResolved;}}}if (resolved) {return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd);} else {Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args)) {ctors = mbd.getPreferredConstructors();return ctors != null ? this.autowireConstructor(beanName, mbd, ctors, (Object[])null) : this.instantiateBean(beanName, mbd);} else {return this.autowireConstructor(beanName, mbd, ctors, args);}}}}}
instantiateBean方法
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {try {Object beanInstance;if (System.getSecurityManager() != null) {beanInstance = AccessController.doPrivileged(() -> {return this.getInstantiationStrategy().instantiate(mbd, beanName, this);}, this.getAccessControlContext());} else {beanInstance = this.getInstantiationStrategy().instantiate(mbd, beanName, this);}BeanWrapper bw = new BeanWrapperImpl(beanInstance);this.initBeanWrapper(bw);return bw;} catch (Throwable var5) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", var5);}}
通过反射创建对象
BeanUtils.instantiateClass(constructorToUse, new Object[0])
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {Assert.notNull(ctor, "Constructor must not be null");try {ReflectionUtils.makeAccessible(ctor);if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {return BeanUtils.KotlinDelegate.instantiateClass(ctor, args);} else {Class<?>[] parameterTypes = ctor.getParameterTypes();Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");Object[] argsWithDefaultValues = new Object[args.length];for(int i = 0; i < args.length; ++i) {if (args[i] == null) {Class<?> parameterType = parameterTypes[i];argsWithDefaultValues[i] = parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null;} else {argsWithDefaultValues[i] = args[i];}}return ctor.newInstance(argsWithDefaultValues);}} catch (InstantiationException var6) {throw new BeanInstantiationException(ctor, "Is it an abstract class?", var6);} catch (IllegalAccessException var7) {throw new BeanInstantiationException(ctor, "Is the constructor accessible?", var7);} catch (IllegalArgumentException var8) {throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", var8);} catch (InvocationTargetException var9) {throw new BeanInstantiationException(ctor, "Constructor threw exception", var9.getTargetException());}}
通过CGLIB创建对象
this.instantiateWithMethodInjection(bd, beanName, owner)
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {return this.instantiateWithMethodInjection(bd, beanName, owner, (Constructor)null);}protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, @Nullable Constructor<?> ctor, Object... args) {return (new CglibSubclassingInstantiationStrategy.CglibSubclassCreator(bd, owner)).instantiate(ctor, args);}
public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {Class<?> subclass = this.createEnhancedSubclass(this.beanDefinition);Object instance;if (ctor == null) {instance = BeanUtils.instantiateClass(subclass);} else {try {Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());instance = enhancedSubclassConstructor.newInstance(args);} catch (Exception var6) {throw new BeanInstantiationException(this.beanDefinition.getBeanClass(), "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", var6);}}Factory factory = (Factory)instance;factory.setCallbacks(new Callback[]{NoOp.INSTANCE, new CglibSubclassingInstantiationStrategy.LookupOverrideMethodInterceptor(this.beanDefinition, this.owner), new CglibSubclassingInstantiationStrategy.ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});return instance;}
createEnhancedSubclass方法
private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(beanDefinition.getBeanClass());enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);if (this.owner instanceof ConfigurableBeanFactory) {ClassLoader cl = ((ConfigurableBeanFactory)this.owner).getBeanClassLoader();enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));}enhancer.setCallbackFilter(new CglibSubclassingInstantiationStrategy.MethodOverrideCallbackFilter(beanDefinition));enhancer.setCallbackTypes(CALLBACK_TYPES);return enhancer.createClass();}
populateBean方法设置依赖关系
populateBean方法
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {if (bw == null) {if (mbd.hasPropertyValues()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");}} else {if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {Iterator var4 = this.getBeanPostProcessors().iterator();while(var4.hasNext()) {BeanPostProcessor bp = (BeanPostProcessor)var4.next();if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return;}}}}PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;int resolvedAutowireMode = mbd.getResolvedAutowireMode();if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) {MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);if (resolvedAutowireMode == 1) {this.autowireByName(beanName, mbd, bw, newPvs);}if (resolvedAutowireMode == 2) {this.autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck = mbd.getDependencyCheck() != 0;PropertyDescriptor[] filteredPds = null;if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}Iterator var9 = this.getBeanPostProcessors().iterator();while(var9.hasNext()) {BeanPostProcessor bp = (BeanPostProcessor)var9.next();if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;PropertyValues pvsToUse = ibp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}}if (needsDepCheck) {if (filteredPds == null) {filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);}if (pvs != null) {this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);}}}
applyPropertyValues方法
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {if (!pvs.isEmpty()) {if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {((BeanWrapperImpl)bw).setSecurityContext(this.getAccessControlContext());}MutablePropertyValues mpvs = null;List original;if (pvs instanceof MutablePropertyValues) {mpvs = (MutablePropertyValues)pvs;if (mpvs.isConverted()) {try {bw.setPropertyValues(mpvs);return;} catch (BeansException var18) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", var18);}}original = mpvs.getPropertyValueList();} else {original = Arrays.asList(pvs.getPropertyValues());}TypeConverter converter = this.getCustomTypeConverter();if (converter == null) {converter = bw;}BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, (TypeConverter)converter);List<PropertyValue> deepCopy = new ArrayList(original.size());boolean resolveNecessary = false;Iterator var11 = original.iterator();while(true) {while(var11.hasNext()) {PropertyValue pv = (PropertyValue)var11.next();if (pv.isConverted()) {deepCopy.add(pv);} else {String propertyName = pv.getName();Object originalValue = pv.getValue();if (originalValue == AutowiredPropertyMarker.INSTANCE) {Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();if (writeMethod == null) {throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);}originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);}Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);Object convertedValue = resolvedValue;boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);if (convertible) {convertedValue = this.convertForProperty(resolvedValue, propertyName, bw, (TypeConverter)converter);}if (resolvedValue == originalValue) {if (convertible) {pv.setConvertedValue(convertedValue);}deepCopy.add(pv);} else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue)originalValue).isDynamic() && !(convertedValue instanceof Collection) && !ObjectUtils.isArray(convertedValue)) {pv.setConvertedValue(convertedValue);deepCopy.add(pv);} else {resolveNecessary = true;deepCopy.add(new PropertyValue(pv, convertedValue));}}}if (mpvs != null && !resolveNecessary) {mpvs.setConverted();}try {bw.setPropertyValues(new MutablePropertyValues(deepCopy));return;} catch (BeansException var19) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", var19);}}}}
resolveValueIfNecessary方法
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {if (value instanceof RuntimeBeanReference) {RuntimeBeanReference ref = (RuntimeBeanReference)value;return this.resolveReference(argName, ref);} else if (value instanceof RuntimeBeanNameReference) {String refName = ((RuntimeBeanNameReference)value).getBeanName();refName = String.valueOf(this.doEvaluate(refName));if (!this.beanFactory.containsBean(refName)) {throw new BeanDefinitionStoreException("Invalid bean name '" + refName + "' in bean reference for " + argName);} else {return refName;}} else if (value instanceof BeanDefinitionHolder) {BeanDefinitionHolder bdHolder = (BeanDefinitionHolder)value;return this.resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());} else if (value instanceof BeanDefinition) {BeanDefinition bd = (BeanDefinition)value;String innerBeanName = "(inner bean)#" + ObjectUtils.getIdentityHexString(bd);return this.resolveInnerBean(argName, innerBeanName, bd);} else {Object valueObject;if (value instanceof DependencyDescriptor) {Set<String> autowiredBeanNames = new LinkedHashSet(4);valueObject = this.beanFactory.resolveDependency((DependencyDescriptor)value, this.beanName, autowiredBeanNames, this.typeConverter);Iterator var19 = autowiredBeanNames.iterator();while(var19.hasNext()) {String autowiredBeanName = (String)var19.next();if (this.beanFactory.containsBean(autowiredBeanName)) {this.beanFactory.registerDependentBean(autowiredBeanName, this.beanName);}}return valueObject;} else if (value instanceof ManagedArray) {ManagedArray array = (ManagedArray)value;Class<?> elementType = array.resolvedElementType;if (elementType == null) {String elementTypeName = array.getElementTypeName();if (StringUtils.hasText(elementTypeName)) {try {elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());array.resolvedElementType = elementType;} catch (Throwable var7) {throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Error resolving array type for " + argName, var7);}} else {elementType = Object.class;}}return this.resolveManagedArray(argName, (List)value, elementType);} else if (value instanceof ManagedList) {return this.resolveManagedList(argName, (List)value);} else if (value instanceof ManagedSet) {return this.resolveManagedSet(argName, (Set)value);} else if (value instanceof ManagedMap) {return this.resolveManagedMap(argName, (Map)value);} else if (value instanceof ManagedProperties) {Properties original = (Properties)value;Properties copy = new Properties();original.forEach((propKey, propValue) -> {if (propKey instanceof TypedStringValue) {propKey = this.evaluate((TypedStringValue)propKey);}if (propValue instanceof TypedStringValue) {propValue = this.evaluate((TypedStringValue)propValue);}if (propKey != null && propValue != null) {copy.put(propKey, propValue);} else {throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Error converting Properties key/value pair for " + argName + ": resolved to null");}});return copy;} else if (value instanceof TypedStringValue) {TypedStringValue typedStringValue = (TypedStringValue)value;valueObject = this.evaluate(typedStringValue);try {Class<?> resolvedTargetType = this.resolveTargetType(typedStringValue);return resolvedTargetType != null ? this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType) : valueObject;} catch (Throwable var8) {throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Error converting typed String value for " + argName, var8);}} else {return value instanceof NullBean ? null : this.evaluate(value);}}}
resolveReference方法
applyPropertyValues方法调用了resolveValueIfNecessary方法,resolveValueIfNecessary方法调用了resolveReference方法
private Object resolveReference(Object argName, RuntimeBeanReference ref) {try {Class<?> beanType = ref.getBeanType();Object bean;if (ref.isToParent()) {BeanFactory parent = this.beanFactory.getParentBeanFactory();if (parent == null) {throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean " + ref + " in parent factory: no parent factory available");}if (beanType != null) {bean = parent.getBean(beanType);} else {bean = parent.getBean(String.valueOf(this.doEvaluate(ref.getBeanName())));}} else {String resolvedName;if (beanType != null) {NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);bean = namedBean.getBeanInstance();resolvedName = namedBean.getBeanName();} else {resolvedName = String.valueOf(this.doEvaluate(ref.getBeanName()));bean = this.beanFactory.getBean(resolvedName);}this.beanFactory.registerDependentBean(resolvedName, this.beanName);}if (bean instanceof NullBean) {bean = null;}return bean;} catch (BeansException var7) {throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, var7);}}
相关文章:
Spring源码之IoC容器的Bean创建和依赖注入,DefaultListableBeanFactory容器为例
接上篇Spring源码之IoC容器初始化过程,以FileSystemXmlApplicationContext容器为例 因为FileSystemXmlApplicationContext使用的容器为DefaultListableBeanFactory,所以该篇基于DefaultListableBeanFactory的实现分析依赖注入过程。 目录获取Bean的总体流…...
解决小程序页面scroll-view块自身滑动问题
修改scroll-view的style样式 本来通过函数限制高度 style"margin-top:200rpx;"height: calc(100vh - 200rpx - env(safe-area-inset-bottom));会出现整个scroll-view块位置不固定滑动里面的内容后,自己本身在整个页面内上移,将样式改为&#…...

PowerCommand康明斯发电机控制屏维修HMI211
康明斯柴油发电机的监控系统分为普通机组控制屏和智能化机组控制界面。普通操作界面实用于普通的康明斯柴油发电机的控制,康明斯柴油发电机的起动与停止、供电与断电、状态调整等均由手动操作;自动化康明斯柴油发电机控制系统适合于智能化康明斯柴油发电…...

ELK + Kafka 测试
配置file beat输出到 Kafkalogstash服务器从kafka获取数据并输出到es集群在es集群上查看索引kibana界面添加索引查看数据1.配置file beat输出到 Kafka 1.1 Filebeat机器配置数据采集和输出目标 做好域名解析 # vim /usr/local/filebeat/filebeat.yml # 修改输出目标为kafka…...

迁移系统:换电脑或者硬盘转移磁盘文件的方法!
为什么要将操作系统迁移到新驱动? “将操作系统转移到新驱动您好,我刚刚为我的台式机订购了一个新的2TB希捷Barracuda硬盘,我想知道如何将我的Windows 10操作系统与我下载的其他一些软件一起转移过来。我使用新的/大的硬盘,然…...

职场性别报告,男女薪酬仍有差距,男性平均薪酬比女性高29.7%
性别是否影响职业?女性求职比男性更加困难?男性薪酬比女性更有优势?人们一说到警察、建筑师通常会想到高大魁梧的男性形象,一说到幼师、护士往往想到的都是温柔的女性形象,职业好似与性别挂钩;女性求职通常…...

5-Azidopentanoic acid,79583-98-5,5-Azidopentanoic COOH具有高效稳定,高特异性
5-Azidopentanoic acid,5-Azidopentanoic COOH,5-叠氮基戊酸产品规格:1.CAS号:79583-98-52.分子式:C5H9N3O23.分子量:143.074.包装规格:1g,5g,10g,包装灵活&a…...
滴滴前端高频react面试题汇总
说说 React组件开发中关于作用域的常见问题。 在 EMAScript5语法规范中,关于作用域的常见问题如下。 (1)在map等方法的回调函数中,要绑定作用域this(通过bind方法)。 (2)父组件传递…...

能在软路由docker给部署搭建teamsperk服务器么?并且设置好ddns
参考链接(4条消息) 【个人学习总结】使用docker搭建Teamspeak服务器_blcurtain的博客-CSDN博客_teamspeak3 docker(⊙﹏⊙)哎呀,崩溃啦! (tdeh.top)TeamSpeak服务器搭建与使用 - 缘梦の镇 (cmsboy.cn)Openwrt X86 docker运行甜糖-软路由,x86系统,openwrt…...
应用统计学实验1-蒙特卡罗方法求解定积分
目录 1. 用蒙特卡罗方法计算定积分(随机投点法) 2. 用蒙特卡罗方法计算定积分(平均值法)...
用Pyhon编写一个属于自己的nmap
用Pyhon编写一个属于自己的nmap 文章目录用Pyhon编写一个属于自己的nmap导入 socket 模块,确定目标主机 IP 或域名以及需要扫描的端口列表开始扫描、扫描每个端口创建一个 socket 对象,用于建立 TCP 连接尝试连接目标主机的指定端口如果连接成功…...

电信网上用户资管理系统的设计与实现
技术:Java、JSP等摘要:在对目前市面上已经拥有的营业厅功能分析和整理后,为了保证营业厅中多种功能的分层次处理设计了一个的电信网上用户自管理系统,以web页面方式实现了与用户的交互,同时保证了移动电话计费管理系统…...
js函数柯里化-面试手写版
概念 用我自己的话来总结一下,函数柯里化的意思就是你可以一次传很多参数给curry函数,也可以分多次传递,curry函数每次都会返回一个函数去处理剩下的参数,一直到返回最后的结果。 实例 这里还是举几个例子来说明一下࿱…...

【学习笔记】深入理解JVM之类加载机制
【学习笔记】深入理解JVM之类加载机制 以后基本上都在语雀上面更新,大家有兴趣可以看看嗷! 首发地址: 知识库 文章流程图: 1、概述 首先我们先来看看一个 Class 文件所需要经过的一个流程图: 而我们今天要重点需讲的…...

驾驭云端之风1——Spring Cloud微服务架构实践指南
本博客纯属个人总结,非原创。喜欢技术交流的,可关注博主,武汉有后端开发群,可支持内推,了解武汉行情等。 前沿 优惠卷平台项目的整体功能和模块,以及每个功能点的技术选型和背后的依据。 搭建一个简化版的…...

【计算机网络基础】
计算机网络基础网络的基本概念网络互联网IP地址MAC地址网络协议网络分层模型网络应用程序的通信流程网络的基本概念 网络 网络是由若干结点和链接这些结点的链路组成,网络中的结点可以是计算机,交换机,路由器等设备 网络设备:交…...
grep与nm命令的应用
相关知识拓展 Linux中grep的命令使用 在Linux中,grep可用于shell脚本,因为grep通过返回一个状态值来说明搜索状态,如果模板搜索成功,则返回0,如果搜索不成功,则返回1,如果搜索的文件不存在&…...

【linux】软硬链接
在linux中在磁盘中定位文件并不是根据文件名而是根据文件的inode,一个文件对应一个inode但是一个inode可以对应多个文件。硬链接硬链接是通过索引节点进行的链接。在Linux中,多个文件指向同一个索引节点是允许的,像这样的链接就是硬链接。硬链…...

骨传导蓝牙耳机排行,盘点几款性能不错的骨传导耳机
随着蓝牙耳机的普及,骨传导耳机也越来越受到欢迎,很多人也都开始在了解并尝试骨传导耳机。相比于其他类型耳机,在舒适度、安全方面有一定优势。尤其是在户外运动时,或者长时间佩戴运动时,使用骨传导耳机可以避免耳朵因…...

ARM中的寄存器
ARM工作模式 ARM有8个基本的工作模式 User 非特权模式,一般在执行上层的应用程序时ARM处于该模式FIQ 当一个高优先级中断产生后ARM将进入这种模式IRQ 当一个低优先级中断产生后ARM将进入这种模式SVC 当复位或执行软中断指令后ARM将进入这种模式Abort 当产生存取异常…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...