springboot之IoC学习

IoC:Inversion of Control,控制反转。

IoC容器是spring中非常重要的一个概念,它是一种思想。

IoC的作用就是将整个业务代码解耦,使得各个模块之间不再直接关联。下面的图可以清晰地描述这种关系:

我们看上面的例子来解释控制反转的事情。

假如对象A要依赖于对象B。

在传统编程中,我们会在A中主动取创建B,这是一种主动控制行为,代码类似下面

public class TestP {
    
    
    private Yaoming b;
    
    public TestP(Yaoming b){
        this.b = b;
    }
    
}

而有了IoC容器之后,当A需要B时,Ioc容器负责去创建对象B,而A不再需要主动去创建对象。就是将主动行为变成了一种被动的行为,这就是控制反转的含义。

刚才提到了IoC是一种思想,它的其中一种实现就是依赖注入(DI),在下面有个参考资料通俗解释了DI,我觉得很形象,它是用USB和电脑的例子解释的,有兴趣的可以参考下面的文章,我也不再赘述。

在Spring中,有了IoC,我们可以按照下面方式开发:

public class ActivityManageTest  {

    private static final Logger logger = LoggerFactory.getLogger("logStash");
    private static final Logger locallogger = LoggerFactory.getLogger(ActivityManageTest.class);

    private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();

    private HashSet<String> hashSet = new HashSet<>();

    @Autowired
    ActivityManageService activityManageService;
    

上面的activityManageService就是我们依赖的对象,这里就不用调用方再去管理该对象,其创建和销毁等过程完全交给IoC容器来实现。看到这,应该很清楚地看到,IoC容器的加入,让我们的开发变得更加简单,且利用Ioc统一管理这些对象,更加规范。

Ioc容器目前在很多成熟的框架都有应用,比如laravel(php)的服务容器以及spring系列等等。他们实现的最基本的方法就是通过反射,即利用反射技术动态地创建对象。

本文主要学习springboot的容器(相对于spring,不再是依赖众多的xml文件)。

在Spring系列中,Ioc容器的两个重要模块是BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的扩展。

一、BeanFactory

先看几个重要的概念

1、BeanDefinition

它是对Bean对象的封装,在Bean初始化过程中,会将Bean的信息都存储到BeanDefinition。其就是sping对Bean的一种定以,后续对Bean的操作,实际上是对BeanDefinition的操作。看源码也可以看到Spring中保存注册bean的map的value就是BeanDefinition。

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);

看一下它的源码:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    String SCOPE_SINGLETON = "singleton";
    String SCOPE_PROTOTYPE = "prototype";
    int ROLE_APPLICATION = 0;
    int ROLE_SUPPORT = 1;
    int ROLE_INFRASTRUCTURE = 2;

    void setParentName(@Nullable String var1);

    @Nullable
    String getParentName();

    void setBeanClassName(@Nullable String var1);

    @Nullable
    String getBeanClassName();

    void setScope(@Nullable String var1);

    @Nullable
    String getScope();

    void setLazyInit(boolean var1);

    boolean isLazyInit();

    void setDependsOn(@Nullable String... var1);

    @Nullable
    String[] getDependsOn();

    void setAutowireCandidate(boolean var1);

    boolean isAutowireCandidate();

    void setPrimary(boolean var1);

    boolean isPrimary();

    void setFactoryBeanName(@Nullable String var1);

    @Nullable
    String getFactoryBeanName();

    void setFactoryMethodName(@Nullable String var1);

    @Nullable
    String getFactoryMethodName();

    ConstructorArgumentValues getConstructorArgumentValues();

    default boolean hasConstructorArgumentValues() {
        return !this.getConstructorArgumentValues().isEmpty();
    }

    MutablePropertyValues getPropertyValues();

    default boolean hasPropertyValues() {
        return !this.getPropertyValues().isEmpty();
    }

    void setInitMethodName(@Nullable String var1);

    @Nullable
    String getInitMethodName();

    void setDestroyMethodName(@Nullable String var1);

    @Nullable
    String getDestroyMethodName();

    void setRole(int var1);

    int getRole();

    void setDescription(@Nullable String var1);

    @Nullable
    String getDescription();

    boolean isSingleton();

    boolean isPrototype();

    boolean isAbstract();

    @Nullable
    String getResourceDescription();

    @Nullable
    BeanDefinition getOriginatingBeanDefinition();
}

上面包含bean类名,是否单例等等属性,其实它是一个接口,它还有几种实现类,如ChildBeanDefinition等。

2、BeanDefinitionRegistry

从其名字也可以看到,它的作用就是把BeanDefinition注册到IoC容器中。看一下它的源码:

public interface BeanDefinitionRegistry extends AliasRegistry {
    //注册bean
    void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
    //移除bean
    void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

    BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

    boolean containsBeanDefinition(String var1);

    String[] getBeanDefinitionNames();

    int getBeanDefinitionCount();

    boolean isBeanNameInUse(String var1);
}

同样,它也是一个接口。

3、BeanFactory

它是一个bean工厂类,提供了已注册Bean对象的获取等操作,看以下它的接口定以

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;

    @Nullable
    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;

    String[] getAliases(String var1);
}

其中最重要的就是getBean方法,当我们在实际要获取某个对象时,底层都是通过该方法。

二、ApplicationContext

其实它是BeanFactory的扩展,目前也基本上都使用它。看一下继承关系图:

它除了继承BeanFactory,还继承了其他几个类:

  • MessageSource:支持不同的信息源,支持国际化实现
  • ResourcePatternResolver:访问资源,使得我们可以从不同的地方获取到Bean定义
  • ApplicationEventPublisher:提供事件机制,跟Bean的整个生命周期结合,方便扩展

ApplicationContext有很多的实现类,其中一个是ConfigurableApplicationContext,它提供了几个关键方法:refresh()和 close(),让 ApplicationContext 具有启动、刷新和关闭应用上下文的能力。在应用上下文关闭的情况下调用 refresh()即可启动应用上下文,在已经启动的状态下,调用 refresh()则清除缓存并重新装载配置信息,而调用close()则可关闭应用上下文。

对于一个Bean来说,它主要经历了定以和初始化两个过程,大致如下图:

首先根据源码,分析一下启动阶段。

看一下一个调用的流程例子:

从应用启动入口开始:

    SpringApplication.run(HbnnshopApplication.class, args);

看一下run方法:

 public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        this.configureHeadlessProperty();
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting();

        Collection exceptionReporters;
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);
            context = this.createApplicationContext();
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            listeners.started(context);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }

        try {
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }

首先是创建应用上下文:

    context = this.createApplicationContext();
 protected ConfigurableApplicationContext createApplicationContext() {
        Class<?> contextClass = this.applicationContextClass;
        if (contextClass == null) {
            try {
                switch(this.webApplicationType) {
                case SERVLET:
                    contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
                    break;
                case REACTIVE:
                    contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
                    break;
                default:
                    contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
                }
            } catch (ClassNotFoundException var3) {
                throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
            }
        }

        return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);

接下来创建IoC容器:

this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);

其中,prepareContext源码:

 private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
        context.setEnvironment(environment);
        this.postProcessApplicationContext(context);
        this.applyInitializers(context);
        listeners.contextPrepared(context);
        if (this.logStartupInfo) {
            this.logStartupInfo(context.getParent() == null);
            this.logStartupProfileInfo(context);
        }

        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
        if (printedBanner != null) {
            beanFactory.registerSingleton("springBootBanner", printedBanner);
        }

        if (beanFactory instanceof DefaultListableBeanFactory) {
            ((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }

        Set<Object> sources = this.getAllSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        this.load(context, sources.toArray(new Object[0]));
        listeners.contextLoaded(context);
    }

其具体操作包括设置环境变量,加载两个单例bean等等,具体可以移步到下面的prepareContext的文章。

下面重点看一下refresh,它是IoC容器创建的关键部分。

看下其源码:

public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }

1、obtainFreshBeanFactory 主要解析配置文件,并装载Beandinition,添加到Map.除了resources下面定以的XML配置文件,还会解析@Controller、@Service、@Component、@Repository等注解,一并解析为BeanDifiniton,并添加到BeanFactory(实现类应用上下文的实现类)的Map中。主要加载的内容包括:

beanDefinitionNames缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 集合。
beanDefinitionMap缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 和 BeanDefinition 映射。
aliasMap缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 和别名映射。
更详细的资料可参考: Spring IoC:obtainFreshBeanFactory 详解

2、prepareBeanFactory是准备工作,会注册ResouceLoader,ApplicationEventPublisher等依赖,添加BeanPostProcessor。

3、接着postProcessBeanFactory,它的作用主要是执行后续的一些BeanFactory操作,具体的还要看具体的实现类。

4、this.invokeBeanFactoryPostProcessors(beanFactory)

它会获取注册到上下文的BeanFactoryPostProcessor,它主要是在实例化Bean之前对Bean进行修改,相当于对Bean的一种扩展。看一下官网描述:

Allows for custom modification of an application context's bean definitions, adapting the bean property values of the context's underlying bean factory. Application contexts can auto-detect BeanFactoryPostProcessor beans in their bean definitions and apply them before any other beans get created. A BeanFactoryPostProcessor may interact with and modify bean definitions, but never bean instances. Doing so may cause premature bean instantiation, violating the container and causing unintended side-effects. If bean instance interaction is required, consider implementing BeanPostProcessor instead.

它主要使用了两种processor:regularPostProcessors和registryProcessors接口.

比较典型的就是ConfigurationClassPostProcessor,它实现了上面两个接口,其作用:

  • ConfigurationClassPostProcessor#postProcessBeanFactory :主要负责在实例化Bean的过成中,对Bean进行增强,比如实现CGLIB代理,添加后值处理器,ImportAwareBeanPostProcessor等等。

例子:

@Configuration
public class RedisConfig {

    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.timeout}")
    private int timeout;
}

我定以了一个配置类,加了@Configuration注解,我们测试一下是否走了代理。


    @Autowired
    RedisConfig redisConfig;

    System.out.println(redisConfig.getClass().getName());

输出:

com.hnshop.hbnnshop.config.RedisConfig$$EnhancerBySpringCGLIB$$cf6a9ff4
可以看到,它使用了cglib代理.

其实除了@Configuraton,@Component等等凡是该类解析的都类似。

  • ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry :负责扫描我们的程序,类如 @Componet,@Import, ComponentScan等注解,根据程序的中Bean创建 BeanDefinition ,并注册到容器中。

具体关于这个类的介绍,可参考: ConfigurationClassPostProcessor —— Spring中最!最!最!重要的后置处理器!没有之一!!!

4、注册BeanFactoryPostProcessor

后续的流程就不说了,就是初始化小戏院,注册监听器等等。只要说一点,Sring的Bean是采用懒加载的模式,在启动时,不会真正初始化。

上面已经说了BeanFactory有个方法是getBean,他就是用来获取对象的。它的实现类有很多

  • impleJndiBeanFactory - spring beanFactory接口的基于jndi的简单实现
  • StaticListableBeanFactory - 简化版的BeanFactory,由于未实现BeanDefinitionRegistry,所以并不支持BeanDefinition的注册操作
  • StubWebApplicationContext - WebApplicationContext的实现
  • AbstractApplicationContext - ApplicationContext是应用的配置中的核心接口,应用运行过程中是只读的,但是可以通过实现其中的接口来达到reload的目的,AbstractApplicationContext是ApplicationContext的抽象类。相比于简单的BeanFactory,ApplicationContext能在类内部检查特定的bean的定义,这个类会自动注册BeanFactoryPostProcessor和BeanPostProcessors和ApplicationListeners
  • AbstractBeanFactory - BeanFactory实现的一个抽象基类,我们重点研究。

在获取Bean时,首先要检查一下单例缓存,如果存在,直接根据缓存的Bean返回对象,如果不存在就走创建的逻辑。创建也要区分是单例还是Prototype。

源码很多,就直接看创建的主逻辑:

 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();
                    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的过程。代码太多了,只能所个大改

它会调用实现createBean的子类:

AbstractAutowireCapableBeanFactory
 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,然后调用createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
    // 获取 bean 对应的 class 
    Class<?> beanClass = resolveBeanClass(mbd, beanName);
    // 如果工厂方法不为空,则使用工厂方法创建
    if (mbd.getFactoryMethodName() != null)  {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
            // 一个类有多个构造方法,带有不同的参数,所以调用前,需要根据参数解析出需要调用的构造方法,
            // 这里使用了缓存,如果以前解析过构造方法,则在这里直接使用即可。
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    if (resolved) {
        if (autowireNecessary) {
            // 构造方法自动注入
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            // 默认构造方法自动注入
            return instantiateBean(beanName, mbd);
        }
    }
    // 解析构造方法
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
        // 构造方法自动注入
        return autowireConstructor(beanName, mbd, ctors, args);
    }
    // 默认构造方法自动注入
    return instantiateBean(beanName, mbd);
}

Bean的实例化要么通过反射,要么通过CGLib实现,但返回的不是代理对象,而是实例本身。

CglibSubclassingInstantiationStrategy
        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;
        }

循环引用问题:

目前spring也只能解决单例的循环引用问题,在创建Bean的过程中会把其放进缓存中,那么在其他的对象也依赖他时,会首先去缓存拿到对象。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //首先直接检查缓存,看缓存是否存在
        Object singletonObject = this.singletonObjects.get(beanName);
         //如果没有,先查找正在创建的Bean,都在ObjectFactories中。
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            synchronized(this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }

        return singletonObject;
    }

上面检查的过程,再看创建bean的过程,是需要把其放进Map中

 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);
            });
        }





  protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(singletonFactory, "Singleton factory must not be null");
        synchronized(this.singletonObjects) {
            if (!this.singletonObjects.containsKey(beanName)) {
                this.singletonFactories.put(beanName, singletonFactory);
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.add(beanName);
            }

        }
    }

Bean的生命周期先看一张图:

  • IoC 容器对 Bean 进行实例化,上面也简要说了createBean的过程。
  • 实例化完成后,如果该 bean 设置了一些属性的话,则利用 set 方法填充Bean属性。
  • 如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName() 方法。
  • 如果 Bean 实现了 BeanClassLoaderAware 接口,则调用 setBeanClassLoader() 方法。
  • 如果Bbean 实现了 BeanFactoryAware接口,则调用 setBeanFactory() 方法。
  • 如果IoC注册了 BeanPostProcessor,则调用postProcessBeforeInitialization() 方法完成 bean 前置处理,BeanPostProcessor是在启动阶段注册到IoC容器中的;
  • 如果该 bean 实现了 InitializingBean 接口,则调用 afterPropertiesSet() 方法,该部分不是对Bean对象本身的处理,只是增加了一些额外的逻辑;
  • 如果该 bean 配置了 init-method 方法,则调用 init-method 指定的方法;
  • 初始化完成后,如果该容器注册了 BeanPostProcessor 则会调用; postProcessAfterInitialization() 方法完成 bean 的后置处理;
  • 对象完成初始化,开始方法调用;
  • 在容器进行关闭之前,如果该 bean 实现了 DisposableBean 接口,则调用 destroy() 方法;
  • 在容器进行关闭之前,如果该 bean 配置了 destroy-mehod,则调用其指定的方法。

参考资料:

spring-boot-2.0.3启动源码篇五 - run方法(四)之prepareContext

SpringBoot源码之旅——IoC容器

Spring IOC 容器源码分析

Spring的IOC原理[通俗解释一下]

深入剖析 Laravel 服务容器

IoC-spring 的灵魂(带你轻松理解IOC思想及bean对象的生成过程)

Attack-spring-boot-3:深入理解 Application Context

SpringBoot源码分析之Spring容器的refresh过程

Spring中Bean的作用域

springboot源码中一窥BeanFactory接口getBean的实现

Spring 的 getBean 方法源码解析

--------EOF---------
微信分享/微信扫码阅读