spring学习

2019-10-04  本文已影响0人  7d972d5e05e8

第一先放我自己画的学习spring的图吧


image.png

一、核心方法refresh()方法走读

  1. refresh最上层的申明类:是接口:ConfigurableApplicationContext
    org.springframework.context.ConfigurableApplicationContext#refresh
  2. refresh的实现类,是抽象类:AbstractApplicationContext。该类实现的refresh方法,其实是通过模板方法实现的。很多调用方法都是其子类实现的。比如:obtainFreshBeanFactory()方法中的refreshBeanFacory()其实现类就是AbstractRefreshableApplicationContext类。其实下面的代码,很多方法都是模板方法,要子类去实现。并且很有可能是好几层后的子类去实现。
    org.springframework.context.support.AbstractApplicationContext#refresh代码如下:
@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();

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

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }
}
  1. refresh方法里面,包含了bean解析方法,loadBeanDefinitions方法。由子类实现,比如:AbstractXmlApplicationContext类,该类默认使用XmlBeanDefinitionReader资源解析reader来解析beanDefine。

  2. refresh方法里面,解析完了所有的bean之后,就开始初始化了。初始化在finishBeanFactoryInitialization方法中。该方法会遍历beanNames列表,一个一个初始化bean。核心方法就是getBean,该方法的实现在AbstractBeanFactory的doGetBean中。

  3. 对于doGetBean方法,实现单例,循环依赖功能。当然这里面的细节超级多,这只是一个概要流程。

二、循环依赖源码走读

对于A依赖B,B依赖A的场景。在doGetBean方法中,最开始有行代码,Object sharedInstance = getSingleton(beanName);会判断是否存在过。

解决循环依赖的关键,不在mbd.getDependsOn()方法上。而是在createBean方法里面的populateBean方法。该方法也是AOP实现的核心。最终通过@Resource注解进来的Bean,需要使用
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName)方法来加载依赖的B。但是它不是解决循环依赖的问题关键,它仅仅是完成注解注入的功能。循环依赖的关键,还是在于提前暴露初始化的BeanFactory。

核心:

         // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isTraceEnabled()) {
                logger.trace("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

如下:

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

        final String beanName = transformedBeanName(name);
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isTraceEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

省略。。。

而getSingleton(beanName)的源码如下:

@Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }

三、singletonObjects,singletonFactories,earlySingletonObjects,registeredSingletons的作用,以及加载顺序

定义:
singletonObjects:Bean的单例实例,是初始化之后的
singletonFactories:Bean的原始实例,是调用动态代理生成的原始实例,尚未注册任何依赖,最单纯的实例,没有和任何其他实例Bean建立关系。
earlySingletonObjects:只知道在getSingleton方法的时候,把singletonFactories获取到的对象,put进来。作用还未知???
registeredSingletons:还没了解,好像和singletonObjects同时添加的。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }

四、自定义bean的初始化方法的实现

有两种实现:

  1. 继承InitializingBean,重写afterPropertiesSet方法
  2. spring xml配置,init-method方法
    他们两可以同时存在,但是afterPropertiesSet比init-method方法先执行。源码如下:
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
            throws Throwable {

        boolean isInitializingBean = (bean instanceof InitializingBean);
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            if (logger.isTraceEnabled()) {
                logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
            }
            if (System.getSecurityManager() != null) {
                try {
                    AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                        ((InitializingBean) bean).afterPropertiesSet();
                        return null;
                    }, getAccessControlContext());
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                 //afterPropertiesSet先执行
                ((InitializingBean) bean).afterPropertiesSet();
            }
        }

        if (mbd != null && bean.getClass() != NullBean.class) {
            String initMethodName = mbd.getInitMethodName();
            if (StringUtils.hasLength(initMethodName) &&
                    !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                    !mbd.isExternallyManagedInitMethod(initMethodName)) {
                //在执行init-method方法
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }
上一篇 下一篇

猜你喜欢

热点阅读