spring单例bean的实例化以及完成依赖注入

本文详细介绍了Spring中单例bean的创建过程,包括通过无参构造函数实例化对象、bean的属性填充,涉及InstantiationAwareBeanPostProcessor、AutowiredAnnotationBeanPostProcessor等,以及initializeBean阶段的初始化方法调用。最后讨论了FactoryBean和早期引用的限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.通过无参构造函数创建实例对象

    return ctor.newInstance(argsWithDefaultValues);     
2.用BeanWrapper包装当前实例,注册一些属性编辑器
     BeanWrapper bw = new BeanWrapperImpl(beanInstance);
     this.registerCustomEditors(bw);
3.执行后置处理器,合并BeanDefinition定义,MergedBeanDefinitionPostProcessor,将需要自动装配的信息记录,其实主要做的事就是用处理器把属性和方法上的自动装配的信息记录下来,放到bean定义里,
后面进行填充的时候可以用到,其中就包括CommonAnnotationBeanPostProcessor的生命周期方法和webService,ejb,Resource注解信息
以及AutowiredAnnotationBeanPostProcessor的Autowired和Value注解信息。
     this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
     3.1 InitDestroyAnnotationBeanPostProcessor,这个主要是生命周期的一些回调函数的注册,
比如带PostConstruct和PreDestroy注解的方法。ReflectionUtils.doWithLocalMethods  LifecycleMetadata
     checkedInitMethods <= initMethods
     3.2 CommonAnnotationBeanPostProcessor,找到当前类及父类带WebServiceRef,EJB,Resource注解的属性,
ReflectionUtils.doWithLocalFields && ReflectionUtils.doWithLocalMethods  InjectionMetadata
     3.3 AutowiredAnnotationBeanPostProcessor 找到带Autowired,Value,Inject注解的方法和属性 
mbd:
     externallyManagedConfigMembers 自动注入的方法和属性
     externallyManagedInitMethods 初始化方法
     externallyManagedDestroyMethods 销毁方法

4.bean提前暴露,加入三级缓存

if (!this.singletonObjects.containsKey(beanName)) {
    this.singletonFactories.put(beanName, singletonFactory);
    this.earlySingletonObjects.remove(beanName);
    this.registeredSingletons.add(beanName);
}

============================================

5.进行bean的属性填充populateBean
     5.1 先执行InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation可以修改bean实例,
如果有一个postProcessor返回false,则会停止属性填充
spring自带的postProcessor都不做任何处理,返回true,可以自定义继承InstantiationAwareBeanPostProcessor实现自己的需求修改bean
     5.2 AutowireMode 1:autowireByName 2:autowireByType 默认为0
     5.3 属性填充InstantiationAwareBeanPostProcessor.postProcessProperties

              5.3.1 CommonAnnotationBeanPostProcessor 处理@Resource注解的属性和方法
              5.3.2 AutowiredAnnotationBeanPostProcessor处理@Autowired和@value注解的方法和属性

                   metadata.inject(bean, beanName, pvs);

                        element.inject(target, beanName, pvs);

                             AutowiredFieldElement.inject 解决属性的value resolveFieldValue(field, bean, beanName);

                                  value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);  

                                                 DefaultListableBeanFactory.doResolveDependency 
                                     5.3.2.1  设置当前的DependencyDescriptor为当前注入点 并返回之前的注入点(后续注入完成后还需要设置回去)
                                         InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);   

                                     5.3.2.2 看看是否有建议的value可以用 Object value = this.getAutowireCandidateResolver().getSuggestedValue(descriptor); 

                                     5.3.2.3 find候选项 findAutowireCandidates 并匹配type的value返回

                    Map<String, Object> matchingBeans = this.findAutowireCandidates(beanName, type, descriptor);

                                     Entry<String, Object> entry = (Entry)matchingBeans.entrySet().iterator().next();
                                     autowiredBeanName = (String)entry.getKey();
                                     instanceCandidate = entry.getValue();

                    instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
                         beanFactory.getBean(beanName);
                         this.doGetBean(name, (Class)null, (Object[])null, false);
                         三级缓存中已经存在时,取出三级缓存中的singletonFactory,通过factory获得EarlyBeanReference
                         this.addSingletonFactory(beanName, () -> {
                            return this.getEarlyBeanReference(beanName, mbd, bean);
                          });
                         通过处理器获得包装bean,SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference
                              AnnotationAwareAspectJAutoProxyCreator根据需要bean的创建代理对象并返回
                         将bean从三级缓存移除并放入二级缓存(可能是被代理过的singletonObject)
[三级缓存中都没有的时候,通过构造函数创建实例

                        ctor.newInstance(argsWithDefaultValues) 重复上面的过程完成实例化]

                                AutowiredAnnotationBeanPostProcessor.registerDependentBeans 注册依赖bean 

                                       dependentBeanMap key = 当前被依赖的beanName,value = 所有依赖key的beanName

                                       dependenciesForBeanMap key = 当前beanName,value=所有依赖的beanName

例:A依赖B和C,dependenciesForBeanMap :A -> B, C            dependentBeanMap  : B ->A    C->A

将DependencyDescriptor创建ShortcutDependencyDescriptor(便于后面别的地方重复使用?但是这里的shortcut是依赖描述信息)

通过反射将属性的value值set到属性上

ReflectionUtils.makeAccessible(field);
field.set(bean, value);  

到此填充属性完成

============================================

6.initializeBean

     -》applyBeanPostProcessorsBeforeInitialization

           所有BeanPostProcessor 处理,如果有返回null了就直接返回,否则就把处理后的对象替换原来的,返回最新对象。(可以通过自定义实现返回null结束后面postProcessor的执行)
           InitDestroyAnnotationBeanPostProcessor执行init方法(@PostConstruct)   checkedInitMethods element

     -》 invokeInitMethods 执行beanDefinition中的initMethodName

     -》applyBeanPostProcessorsAfterInitialization

         -》AbstractAutoProxyCreator看是否需要代理wrapIfNecessary(bean, beanName, cacheKey);

7.getSingleton(beanName, false); allowEarlyReference不能提前引用,即不能放入二级缓存中

addSingletonFactory放入三级缓存

doGetBean -》getSingleton(beanName);  -》 getSingleton(beanName, true);放入二级缓存

createBean - 》doCreateBean -》getSingleton(beanName, false); 不能放入二级缓存 要么返回一级缓存对象,要么返回二级缓存对象,要么返回null

      如果有返回值,则判断与之前实例化的bean是不是相等

8.addSingleton(beanName, singletonObject);加入一级缓存,从二级缓存和三级缓存移除

9.getObjectForBeanInstance(针对FactoryBean)

preInstantiateSingletons()完成一个bean的实例化及依赖bean的实例化工作

bean中的 public C c = new C(value); 这样的初始化创建属性实例对象在执行构造函数创建实例的时候就完成了,所有的依赖注入都还没有执行,所以如果属性的实例创建依赖了依赖注入的值,则取不到真正的值

app.value=1
@Service
public class ValueTest {
    @Value("${app.value}")
    private int value;

    public C c = new C(value);

    @PostConstruct
    public void init(){
        c.say();
    }
}
public class C {
    private int c;

    public C(int c) {
        this.c = c;
    }

    public int getC() {
        return c;
    }

    public void setC(int c) {
        this.c = c;
    }

    public void say(){
        System.out.println("c = " +c);
    }
}

最後輸出c = 0,value = 1,value的值并没有赋值给c

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值