Spring源码学习(5)—— bean的加载 part 2
之前归纳了从spring容器的缓存中直接获取bean的情况,接下来就需要从头开始bean的加载过程了。这里着重看单例的bean的加载
if(ex1.isSingleton()) {
sharedInstance = this.getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
return AbstractBeanFactory.this.createBean(beanName, ex1, args);
} catch (BeansException var2) {
AbstractBeanFactory.this.destroySingleton(beanName);
throw var2;
}
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, ex1);
}
单例的加载调用了重载的getSingleton方法,在这个方法的参数中,传入了一个实现ObjectFactory接口的匿名内部类对象,在接口方法中调用了外部类AbstractBeanFactory的createBean方法来创建bean,同时在捕获异常时,调用外部类的destroySingleton方法执行一系列销毁操作。
我们进入到getSingleton方法
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "\'beanName\' must not be null");
Map var3 = this.singletonObjects;
synchronized(this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if(singletonObject == null) {
if(this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
} if(this.logger.isDebugEnabled()) {
this.logger.debug("Creating shared instance of singleton bean \'" + beanName + "\'");
} this.beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = this.suppressedExceptions == null;
if(recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
} try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException var16) {
singletonObject = this.singletonObjects.get(beanName);
if(singletonObject == null) {
throw var16;
}
} catch (BeanCreationException var17) {
BeanCreationException ex = var17;
if(recordSuppressedExceptions) {
Iterator var8 = this.suppressedExceptions.iterator(); while(var8.hasNext()) {
Exception suppressedException = (Exception)var8.next();
ex.addRelatedCause(suppressedException);
}
} throw ex;
} finally {
if(recordSuppressedExceptions) {
this.suppressedExceptions = null;
} this.afterSingletonCreation(beanName);
} if(newSingleton) {
this.addSingleton(beanName, singletonObject);
}
} return singletonObject != NULL_OBJECT?singletonObject:null;
}
}
在这段代码中首先会检查当前bean是否在销毁过程中,一旦销毁过程还未结束,说明当前容器中部分缓存并不准确,因此会抛出异常。
在执行ObjectFactory的getObject方法前,执行了一段创建前的操作代码
protected void beforeSingletonCreation(String beanName) {
if(!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
在这里把beanName放在了singletonsCurrentlyInCreation缓存中,也就是说在这一刻,spring声明正在创建这个bean了。
同样的在调用ObjectFactory的getObject方法后,在finally块里afterSingletonCreation中,spring会在singletonsCurrentlyInCreation将其移除。
protected void afterSingletonCreation(String beanName) {
if(!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton \'" + beanName + "\' isn\'t currently in creation");
}
}
若创建bean成功了,就会调用addSingleton方法,更新一系列容器的缓存。
protected void addSingleton(String beanName, Object singletonObject) {
Map var3 = this.singletonObjects;
synchronized(this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject != null?singletonObject:NULL_OBJECT);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
这样之后再创建这个单例bean的时候只需要从singletonObjects中取就ok了。
接下来我们就来看看真正创建bean的代码段singletonObject = singletonFactory.getObject()
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if(this.logger.isDebugEnabled()) {
this.logger.debug("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 var7) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var7);
} Object beanInstance;
try {
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
if(beanInstance != null) {
return beanInstance;
}
} catch (Throwable var8) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var8);
} beanInstance = this.doCreateBean(beanName, mbdToUse, args);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Finished creating instance of bean \'" + beanName + "\'");
} return beanInstance;
}
在这段中,首先根据设置的class属性或者根据className来解析Class。
然后会对beanDefinition中的methodOverrides属性做一个预处理。在methodOverrides中存放的是先前随笔中提到的lookup-method和replace-method标签的解析。目的是对生成的bean的对应方法中实现一层代理。
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
MethodOverrides methodOverrides = this.getMethodOverrides();
if(!methodOverrides.isEmpty()) {
Set overrides = methodOverrides.getOverrides();
synchronized(overrides) {
Iterator var4 = overrides.iterator(); while(var4.hasNext()) {
MethodOverride mo = (MethodOverride)var4.next();
this.prepareMethodOverride(mo);
}
}
} }
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
int count = ClassUtils.getMethodCountForName(this.getBeanClass(), mo.getMethodName());
if(count == 0) {
throw new BeanDefinitionValidationException("Invalid method override: no method with name \'" + mo.getMethodName() + "\' on class [" + this.getBeanClassName() + "]");
} else {
if(count == 1) {
mo.setOverloaded(false);
} }
}
根据上面两段代码可以看出,这里的预处理就是如果在当前类中没有找到对应要代理的方法时,就抛出异常,如果根据方法名只找到一个对应的方法,说明要代理的方法就是这个方法。那么就设置methodOverrides的overload属性为false。如果有多个重载的方法,那就需要根据参数来确定要代理的方法了,这一步将在之后的代码中实现。
在真正调用doCreate的方法创建bean之前,会通过resolveBeforeInstantiation做一些实例化前的前置处理。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if(!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if(!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Class targetType = this.determineTargetType(beanName, mbd, new Class[0]);
if(targetType != null) {
bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if(bean != null) {
bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
} mbd.beforeInstantiationResolved = Boolean.valueOf(bean != null);
} return bean;
}
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
Iterator var3 = this.getBeanPostProcessors().iterator(); while(var3.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)var3.next();
if(bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if(result != null) {
return result;
}
}
} return null;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Iterator var4 = this.getBeanPostProcessors().iterator(); do {
if(!var4.hasNext()) {
return result;
} BeanPostProcessor beanProcessor = (BeanPostProcessor)var4.next();
result = beanProcessor.postProcessAfterInitialization(result, beanName);
} while(result != null); return result;
}
上面的代码逻辑不复杂,就是:
1、遍历一遍AbstractBeanFactory里的BeanPostProcessors
2、然后在实例化前调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法。
3、一旦postProcessBeforeInstantiation方法返回的对象不为null,再调用BeanPostProcessor的 postProcessAfterInitialization对象
在spring中随处可见这种在做一件事情时,分别在做之前调用前处理器,而在做之后调用后处理器。这样其实就是利用模板方法,抽象出最简单最基本的不变的过程:做之前,做的过程中,做之后。这样做法的好处就是可以很方便扩展。在我们实际设计的时候可以借鉴这种写法。
如果我们想对某个特殊的bean实例化前和实例化后做一些特殊处理,就可以通过AbstractBeanFactory的addBeanPostProcessor来添加后处理器,从而实现自定义的业务逻辑。
接下来就到了常规bean的创建了,这一过程是在doCreateBean方法中实现的
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, 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);
} final Object bean = instanceWrapper != null?instanceWrapper.getWrappedInstance():null;
Class beanType = instanceWrapper != null?instanceWrapper.getWrappedClass():null;
mbd.resolvedTargetType = beanType;
Object earlySingletonExposure = mbd.postProcessingLock;
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 var20 = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if(var20) {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Eagerly caching bean \'" + beanName + "\' to allow for resolving potential circular references");
} this.addSingletonFactory(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
return AbstractAutowireCapableBeanFactory.this.getEarlyBeanReference(beanName, mbd, bean);
}
});
} Object exposedObject = bean; try {
this.populateBean(beanName, mbd, instanceWrapper);
if(exposedObject != null) {
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(var20) {
Object ex = this.getSingleton(beanName, false);
if(ex != null) {
if(exposedObject == bean) {
exposedObject = ex;
} else if(!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
LinkedHashSet 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 \'getBeanNamesOfType\' 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);
}
}
这段代码比较长,阅读起来有些难度,但把这个方法一小段一小段拆分开来,还是可以看懂其中的逻辑的。
首先需要创建这个bean的实例,实例的创建在createBeanInstance方法中。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, 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 if(mbd.getFactoryMethodName() != null) {
return this.instantiateUsingFactoryMethod(beanName, mbd, args);
} else {
boolean resolved = false;
boolean autowireNecessary = false;
if(args == null) {
Object ctors = mbd.constructorArgumentLock;
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[] ctors1 = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
return ctors1 == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args)?this.instantiateBean(beanName, mbd):this.autowireConstructor(beanName, mbd, ctors1, args);
}
}
}
在上面的代码中我们可以看到:
1、如果这个bean有对应的工厂方法的话,调用instantiateUsingFactoryMethod来做实例化操作
2、如果不是工厂方法,则解析构造函数,并根据构造函数来实例化bean。一个bean的构造函数可能会有多个,因此,spring会根据参数类型来确定使用哪一个构造函数进行实例化,这里spring用了一个缓存机制,如果缓存resolvedConstructorOrFactoryMethod中有值,则用这个方法实例化,否则,需要再次解析,并将解析结果添加至缓存中。
我们先来看使用工厂实例化bean的情况。代码比较长,这边就不完整贴过来了,简单截取一些片段来看
if(factoryBeanName != null) {
if(factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "factory-bean reference points back to the same bean definition");
} factoryBean = this.beanFactory.getBean(factoryBeanName);
if(factoryBean == null) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "factory-bean \'" + factoryBeanName + "\' (or a BeanPostProcessor involved) returned null");
} if(mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new IllegalStateException("About-to-be-created singleton instance implicitly appeared through the creation of the factory bean that its bean definition points to");
} factoryClass = factoryBean.getClass();
isStatic = false;
} else {
if(!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "bean definition declares neither a bean class nor a factory-bean reference");
} factoryBean = null;
factoryClass = mbd.getBeanClass();
isStatic = true;
}
这里判断了一下factoryBeanName是否为空,
1、如果不为空,这就说明工厂方法不是静态static的,因此需要先去实例化factoryBean
2、如果为空,则说明工厂方法是静态的。工厂就是当前bean中的class。
接下来spring会根据参数类型找到对应的工厂方法,然后通过反射来实例化bean
Method ex = (Method)currentlyInvokedFactoryMethod.get(); Object msg1;
try {
currentlyInvokedFactoryMethod.set(factoryMethod);
msg1 = factoryMethod.invoke(factoryBean, args);
} finally {
if(ex != null) {
currentlyInvokedFactoryMethod.set(ex);
} else {
currentlyInvokedFactoryMethod.remove();
} } return msg1;
如果没有工厂方法来实例化bean,那么对于实例的创建spring中分成了两种情况,一种是通用的实例化,一种是带参数的实例化。
我们首先来看看参数的实例化过程autowireConstructor。这个方法代码较长,就不完整摘出,直接挑一些片段来解析
首先spring会尝试拿到构造函数的参数
if(explicitArgs != null) {
argsToUse = explicitArgs;
} else {
Object[] ex = null;
Object ctorToUse = mbd.constructorArgumentLock;
synchronized(mbd.constructorArgumentLock) {
constructorToUse = (Constructor)mbd.resolvedConstructorOrFactoryMethod;
if(constructorToUse != null && mbd.constructorArgumentsResolved) {
argsToUse = mbd.resolvedConstructorArguments;
if(argsToUse == null) {
ex = mbd.preparedConstructorArguments;
}
}
} if(ex != null) {
argsToUse = this.resolvePreparedArguments(beanName, mbd, bw, constructorToUse, ex);
}
}
从上面的代码我们可以看到,如果在调用getBean()方法是直接添加了参数,那么就直接使用这些参数,即explicitArgs。
如果没有传参,则需要解析配置文件,在解析前,spring会先从beanDefinition的缓存中尝试获取构造函数的参数。
如果没有,则从配置的构造函数中取。
确定了构造函数的参数类型和个数,就能找到对应的构造方法了
在匹配之前,spring先对构造函数按照public构造函数优先参数数量降序,非public构造函数参数数量降序,然后根据参数来匹配找到对应的构造函数。
找到构造函数之后,就会根据实例化策略以及构造函数和构造函数参数,来实例化bean
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner, final Constructor<?> ctor, Object... args) {
if(bd.getMethodOverrides().isEmpty()) {
if(System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
ReflectionUtils.makeAccessible(ctor);
return null;
}
});
} return BeanUtils.instantiateClass(ctor, args);
} else {
return this.instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}
通过上面的实例化策略可以看到,如果bean的配置中没有methodOverrides属性,也就是lookup-method或者replace-method,那么就可以简单地通过已知的构造函数和入参来实例化对象。如果一旦有需要做代理的方法的话,spring会通过cglib动态代理的方式对这个bean做代理。这部分内容会在AOP的章节再做详细分析。
完成了bean的实例化,接下来
boolean var20 = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if(var20) {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Eagerly caching bean \'" + beanName + "\' to allow for resolving potential circular references");
} this.addSingletonFactory(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
return AbstractAutowireCapableBeanFactory.this.getEarlyBeanReference(beanName, mbd, bean);
}
});
}
spring会记录创建bean的ObjectFactory,这里的singletonFactory是为了处理循环依赖的时候,可以提前使用这个bean的引用。
举个例子:假设有A和B两个bean,在A中有B的属性,B中有A的属性。这就形成了一个属性的循环依赖。spring对于属性的循环依赖是可以解决的。解决的方式就是
1、在实例化A完成后,先暴露出一个A的引用
2、接下来在注入A的属性时,发现了B,spring就会去实例化B
3、实例化B之后,B会暴露一个B的引用
4、接下来就会注入B的属性,这时候发现了A,因为A已经提前暴露了它的引用,因此B可以完成属性的注入
5、完成了B的创建后,B会将自己暴露的引用删除
6、接下来A将创建好的B注入到自己的属性中,完成A的创建,最后将A自己的暴露引用删去。
完成了属性注入populateBean,接下来就到了bean的初始化
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if(System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
AbstractAutowireCapableBeanFactory.this.invokeAwareMethods(beanName, bean);
return null;
}
}, this.getAccessControlContext());
} else {
this.invokeAwareMethods(beanName, bean);
} Object wrappedBean = bean;
if(mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
} try {
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null?mbd.getResourceDescription():null, beanName, "Invocation of init method failed", var6);
} if(mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
} return wrappedBean;
}
首先,spring会激活Aware方法
private void invokeAwareMethods(String beanName, Object bean) {
if(bean instanceof Aware) {
if(bean instanceof BeanNameAware) {
((BeanNameAware)bean).setBeanName(beanName);
} if(bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware)bean).setBeanClassLoader(this.getBeanClassLoader());
} if(bean instanceof BeanFactoryAware) {
((BeanFactoryAware)bean).setBeanFactory(this);
}
} }
如果这个bean继承了Aware接口,那么在这里会调用Aware相应的方法。
接下来,spring会激活当前容器中注册的所有处理器方法。
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Iterator var4 = this.getBeanPostProcessors().iterator(); do {
if(!var4.hasNext()) {
return result;
} BeanPostProcessor beanProcessor = (BeanPostProcessor)var4.next();
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
} while(result != null); return result;
}
通过BeanPostProcessor,使得我们可以自定义一些创建bean的业务逻辑
之后spring会激活自定义的init方法
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
boolean isInitializingBean = bean instanceof InitializingBean;
if(isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Invoking afterPropertiesSet() on bean with name \'" + beanName + "\'");
} if(System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
((InitializingBean)bean).afterPropertiesSet();
return null;
}
}, this.getAccessControlContext());
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
((InitializingBean)bean).afterPropertiesSet();
}
} if(mbd != null) {
String initMethodName = mbd.getInitMethodName();
if(initMethodName != null && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
this.invokeCustomInitMethod(beanName, bean, mbd);
}
} }
这里的init方法除了我们在配置中设定的init-method,还可以是实现了InitializingBean接口的bean,spring会调用接口的afterPropertiesSet方法。
到这里bean的实例化和初始化就都完成了。
Spring源码学习(5)—— bean的加载 part 2的更多相关文章
- spring源码学习之bean的加载(二)
这是接着上篇继续写bean的加载过程,好像是有点太多了,因为bean的加载过程是很复杂的,要处理的情况有很多,继续... 7.创建bean 常规的bean的创建时通过doCreateBean方法来实现 ...
- spring源码学习之bean的加载(一)
对XML文件的解析基本上已经大致的走了一遍,虽然没有能吸收多少,但是脑子中总是有些印象的,接下来看下spring中的bean的加载,这个比xml解析复杂的多.这个加载,在我们使用的时候基本上是:Bea ...
- spring源码学习之bean的加载(三)
接着二中的继续写,那个都超过1000行了,哈,需要重新写一个,要不太长了,我都看不下去了 7.4 初始化bean doCreateBean函数中有这样一行代码:这行代码中initializeBean函 ...
- Spring源码分析之Bean的加载流程
spring版本为4.3.6.RELEASE 不管是xml方式配置bean还是基于注解的形式,最终都会调用AbstractApplicationContext的refresh方法: @Override ...
- 【Spring源码分析】非懒加载的单例Bean初始化过程(下篇)
doCreateBean方法 上文[Spring源码分析]非懒加载的单例Bean初始化过程(上篇),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下 ...
- 【Spring源码分析】非懒加载的单例Bean初始化前后的一些操作
前言 之前两篇文章[Spring源码分析]非懒加载的单例Bean初始化过程(上篇)和[Spring源码分析]非懒加载的单例Bean初始化过程(下篇)比较详细地分析了非懒加载的单例Bean的初始化过程, ...
- Spring源码分析:非懒加载的单例Bean初始化前后的一些操作
之前两篇文章Spring源码分析:非懒加载的单例Bean初始化过程(上)和Spring源码分析:非懒加载的单例Bean初始化过程(下)比较详细地分析了非懒加载的单例Bean的初始化过程,整个流程始于A ...
- Spring源码分析:非懒加载的单例Bean初始化过程(下)
上文Spring源码分析:非懒加载的单例Bean初始化过程(上),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下AbstractAutowireC ...
- 【Spring源码分析】非懒加载的单例Bean初始化过程(上篇)
代码入口 上文[Spring源码分析]Bean加载流程概览,比较详细地分析了Spring上下文加载的代码入口,并且在AbstractApplicationContext的refresh方法中,点出了f ...
- Spring源码分析:非懒加载的单例Bean初始化过程(上)
上文[Spring源码分析]Bean加载流程概览,比较详细地分析了Spring上下文加载的代码入口,并且在AbstractApplicationContext的refresh方法中,点出了finish ...
随机推荐
- js switch 用法
//获取星期 //例子1 var day=new Date().getDay(); switch (day) { : x="Today it's Saturday"; break; ...
- 在linux 上安装ansible
ansible 在线安装:yum install -y epel-releaseyum install -y ansible离线安装:rpm wget https://releases.ansible ...
- 学习笔记71—Python 报错处理集
****************************************************** 如有谬误,请联系指正.转载请注明出处. 联系方式: e-mail: heyi9069@gm ...
- mysq带条件的分页查询数据结果错误
记一次mysql分页条件查询的结果出错: 以一张用户表为例,首先我们看表中的所有数据,注意红色框住的部分: 我们使用不带条件的分页查询来查询,数据显示是OK的: SELECT id,login_nam ...
- PHP json_decode为什么将json字符串转成数组是对象格式?
eg. $a='[{\"img\":\"/uploads/agency/carimgs/5/15515954778091.jpg\"},{\"img\ ...
- python学习之可视化tkinter基础
- C#通过读取Mysql脚本创建数据库
#region script helper private bool ExecuteScriptFile(string pathToScriptFile, out string errorMsg) { ...
- 可迭代对象 TO 迭代器
可迭代对象并不是迭代器,只是支持迭代.可被for循环遍历的对象,比如list,dict ,tuple ,string都是可迭代对象 那既然支持迭代,那要如何用迭代替换for循环呢? 内置函数 iter ...
- 嵌套if-esle语句
C语言自学之嵌套if-esle语句 Dome : 获奖条件为年销售业绩100万以上,并且入职满两年的员工.小明进入公司1年,销售业绩为120万. 在代码编辑器中使用嵌套if-else语句判断小明是否有 ...
- JQuery的常用选择器 转
JQuery的常用选择器 刚开始学JQuery写的如有错误欢迎批评指正 JQuery拥有的选择器可以让我们更快更方便找到想要的元素,然后对相应的元素进行操作 简单介绍一下一些常用的选择器: 1.基本选 ...