美文网首页
spring被@Bean注解的方法是如何变成SpringBean

spring被@Bean注解的方法是如何变成SpringBean

作者: 黑铁大魔王 | 来源:发表于2020-07-05 22:39 被阅读0次

上一篇文章写到了被@Bean注解的方法如何转变成beanDef,进入bdMap的
现在继续来跟进beanDef是如何转变成为真正的SpringBean的
先上一段Spring源码阅读经典代码

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            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.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                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(); // springboot依赖starter-web后,里会进入AbstractApplicationContext子类AnnotationConfigServletWebServerApplicationContext里的onRefresh(),进而启动web容器

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                // 这里会生成SpringBean对象,跟进去看即可
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }
。。。

从bdMap里拿到需要被制作成SpringBean的beanDef

上面12个方法的第11个,也就是倒数第二个finishBeanFactoryInitialization(beanFactory);方法里,会将beanFactory中的bdMap里的beanDef拿出来实例化,包装,然后放到单利池singletonObjects中。

finishBeanFactoryInitialization
从该方法的最后一个调用继续跟进去
preInstantiateSingletons
该方法很简单
  1. 首先拿到beanNames列表,
  2. 然后循环实例化每个class,
  3. 通过getBean(beanName)继续进行实例化流程

getBean(beanName)是个空壳方法,继续调用doGetBean(name, requiredType, args, false);

doGetBean
doGetBean
doGetBean方法里会进行beanName的转换,循环引用的判断与处理,创建单例bean。
这里314行通过getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法进入,内部再回调lambda表达式里的createBean()方法,完成其后续操作。实际上,创建lambda中高的beanBean(beanName, mbd, args)方法就是真正来创建SpringBean的。
PS: AbstractBeanFactoryDefaultSingletonBeanRegistry的子类
那么就直接看createBean()吧。
getSingleton
这里传递的singletonFactory是AbstractAutowireCapableBeanFactory,所以,246行的getObject()也就进入下面的截图了
createBean
可以看到mbdToUse的属性,大多都是上一篇文章里写的class进入bdMap里面的内容。
doCreateBean
doCreateBean方法里,首先create一个beanInstanceWrapper,这是个BeanWrapper对象,也就是说,先把需要处理的class整成一个包装对象instanceWrapper。
进入createBeanInstance继续看
createBeanInstance

生成class的对象

注意了,在此之前的所有操作,对于@Component,@Service,@Bean是没有区别的,区别从这里开始,因为@Bean注解的方法生成的beanDef,也就是截图里的mbd里的factoryMethodName是有值的。所以会通过instantiateUsingFactoryMethod(beanName, mbd, args)方法来创建 包装对象。
接下来进入该方法

instantiateUsingFactoryMethod
没什么可说的,继续往下跟踪
instantiateUsingFactoryMethod
很简单的代码,拿到factoryBeanName,拿到factoryBean,判断factoryBean是否被代理过,如果被代理过,就去拿代理前的对象。箭头指的代码如下
    public static Class<?> getUserClass(Class<?> clazz) {
        if (clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {
            Class<?> superclass = clazz.getSuperclass();
            if (superclass != null && superclass != Object.class) {
                return superclass;
            }
        }
        return clazz;
    }

为什么要那代理前的对象呢?因为474行,需要通过代理前的类获取候选方法。

image.png
只有一个方法xyz()能够进入候选方法列表里,然后调用instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS)。注意:这里的factoryBean用的可是代理对象哦。
image.png
这个CglibSubclassingInstantiationStrategy是怎么来的呢?其实是事先定义好的。 cglib_instance.gif
跟踪进入后面的instantiate( mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args)方法里
image.png
很简单的来个反射调用,执行xyz()方法里的代码,拿到返回值。
invoke.gif
可以看到调用xyz()方法是,在返回实例之前可以执行其他代码。
result
区别至此结束,@Bean要生成的的对象搞出来了,下面就是如何生成SpringBean了。

下面的内容与@Component,@Service等已基本无差别。属于将class的对象制作成SpringBean的内容
上面代码一路返回,来到这里


wrapper
image.png

得到了包装类型了吧。接着往下来到了非常重要的属性填充环节。


image.png
populateBean()
applyPropertyValues()
这里的pvs,也就是PropertyValues是空,就直接返回了,不是重点。
属性填充完毕后,就是初始化bean了
initializeBean
initializeBean()

initializeBean里会调用setXXX()注入的方法,调用后置处理器,调用生命周期重的初始化回调方法,调用后置处理器的postProcessAfterInitialization()方法然后返回wrappedBean,赋值给exposedObject,并且返回exposedObject。


继续返回
继续返回
image.png 继续返回
这里返回到了getSingletion()里,拿到了SpringBean,然后在282行addSingleton(beanName, singletonObject);里,将其注入到ioc容器
addSingleton

相关文章

网友评论

      本文标题:spring被@Bean注解的方法是如何变成SpringBean

      本文链接:https://www.haomeiwen.com/subject/ipwlqktx.html