booleanresolved = false;
booleanautowireNecessary = false;
if(args == null) {
synchronized(mbd.constructorArgumentLock) {
if(mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if(resolved) {
if(autowireNecessary) {
returnautowireConstructor(beanName, mbd, null, null);
}
else{
returninstantiateBean(beanName, mbd);
}
}
根据前面的介绍,我们现在已经获取到 Class 对象了,接下来直接调用相应的构造方法就可以获取到 Bean 实例了 。但是这个 Class 对象可能存在多个构造方法,所以还需要一堆流程去确定到底调用哪个构造方法 。
所以这里会先去判断 resolvedConstructorOrFactoryMethod 是否不为空,不为空的话,说明这个 Bean 之前已经创建过了,该用什么方法创建等等问题都已经确定了,所以这次就不用重新再去确定了( resolved = true ) 。另一方面,autowireNecessary 表示构造方法的参数是否已经处理好了,这个属性为 true 则表示构造方法的参数已经处理好了,那么就可以调用 autowireConstructor 方法去创建一个 Bean 出来,否则调用 instantiateBean 方法初始化 Bean 。
这里涉及到的 autowireConstructor 和 instantiateBean 方法我们先不细说了,因为在后面还会再次涉及到 。
2.4 构造器注入
继续回到一开始的源码中,接下来就是针对各种处理器的预处理了:
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if(ctors != null|| mbd.getResolvedAutowireMode == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues || !ObjectUtils.isEmpty(args)) {
returnautowireConstructor(beanName, mbd, ctors, args);
}
先来看 determineConstructorsFromBeanPostProcessors 方法,这个方法主要是考虑到你可能提供了 SmartInstantiationAwareBeanPostProcessor,松哥在前面的文章中和大家专门讲过 BeanPostProcessor( BeanFactoryPostProcessor 和 BeanPostProcessor 有什么区别? ),这里的 SmartInstantiationAwareBeanPostProcessor 算是 BeanPostProcessor 的一种,也是 Bean 的一种增强器 。SmartInstantiationAwareBeanPostProcessor 中有一个 determineCandidateConstructors 方法,这个方法返回某一个 Bean 的构造方法,将来可以通过这个构造方法初始化某一个 Bean 。
我给大家举一个简单例子,假设我有如下类:
publicclassUser{
privateString username;
privateString address;
publicUser{
System.out.println( "=====no args=====");
}
publicUser(ObjectProvider<String> username){
System.out.println( "args==username");
this.username = username.getIfAvailable;
}
//省略 getter/setter/toString
}
现在我在 Spring 容器中注册这个对象:
< beanclass= "org.javaboy.bean.User"id= "user">
</ bean>
按照我们已有的知识,这个将来会调用 User 的无参构造方法去完成 User 对象的初始化 。
但是现在,假设我添加如下一个处理器:
publicclassMySmartInstantiationAwareBeanPostProcessorimplementsSmartInstantiationAwareBeanPostProcessor{
@Override
publicConstructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throwsBeansException {
if( "user".equals(beanName)) {
Constructor<?> constructor = null;
try{
constructor = beanClass.getConstructor(ObjectProvider . class) ;
} catch(NoSuchMethodException e) {
thrownewRuntimeException(e);
}
returnnewConstructor[]{constructor};
}
returnSmartInstantiationAwareBeanPostProcessor. super.determineCandidateConstructors(beanClass, beanName);
}
}
在 determineCandidateConstructors 方法中,返回一个有参构造方法,那么将来 Spring 容器会通过这里返回的有参构造方法去创建 User 对象,而不是通过无参构造方法去创建 User 对象 。
最后,将这个处理器注册到 Spring 容器:
< beanclass= "org.javaboy.bean.MySmartInstantiationAwareBeanPostProcessor"/>
现在,当我们启动 Spring 容器的时候,User 就是通过有参构造方法初始化的,而不是无参构造方法 。之所以会这样,就是因为本小节一开始提到的源码 determineConstructorsFromBeanPostProcessors ,这个方法就是去查看有无 SmartInstantiationAwareBeanPostProcessor,如果有,就调用对应的方法找到处理器并返回 。
这个弄懂之后,if 中其他几种情况就好理解了,mbd.getResolvedAutowireMode 是查看当前对象的注入方式,这个一般是在 XML 中配置的,不过日常开发中我们一般不会配置这个属性,如果需要配置,方式如下:
推荐阅读
- SpringBoot中使用Cache提升接口性能详解
- 通过Docker和Kubernetes实现容器化的自动伸缩
- 花生油的保存方法 花生油的保存方法用什么容器放花生油最好
- 杨梅泡酒要用什么酒 杨梅泡酒用什么容器比较好
- 微波炉热菜用什么器皿 用微波炉热菜用什么容器
- 简单起泡胶怎么做? 简单起泡胶怎么做
- 微波炉不能用什么容器 微波炉不能用什么容器加热饭菜
- 玻璃容器能放微波炉吗 玻璃容器能放微波炉吗安全吗
- 使用微波炉可以使用金属容器和空载吗 使用微波炉能不能用金属容器
- 空气炸锅能放什么容器 空气炸锅放什么容器最好
