Spring Bean生命周期与循环依赖等源码学习笔记

目录

前言    

概述        

Bean生命周期   

BeanFactory与FactoryBean

循环依赖

事务

Springboot核心思想


前言    

        最近通过看b站培训机构的Spring和SpringBoot源码教程视频学习Spring&SpringBoot的原理和思想,视频是以源码讲解的方式演示,这里分享一些关键点的笔记。

概述        

        Spring的核心思想是IOC和AOP,IOC是控制反转,是将程序中需要用到的对象创建过程交给容器实现,让容器根据xml的配置实现对对象的创建和依赖注入。AOP是面向切面编程,是对一系列纵向请求做横向的拦截处理,Spring里面使用到AOP的地方主要是BeanFactoryPostProcessor和BeanPostProcessor增强器和Aspect切面。

Bean生命周期   

视频里整理了一个说明Bean生命周期的图:

Spring Bean生命周期与循环依赖等源码学习笔记_第1张图片

         如上图,bean的定义信息由一开始在xml等配置文件中表示,通过beandefinitionreader加载到一开始关联的beanfactory中,beanfactory是bean的工厂类最顶层接口,以懒加载的方式创建bean,而它的子类ApplicationContext实例化的时候就创建好了bean对象。bean的创建过程大概如下:

   1、实例化bean,即开辟空间存放对象;

   2、populatebean,填充属性;当 Bean 本身实现了 BeanNameAware 接口,这个时候会根据接口方法,来设置 Bean 的 name;

   3、当 Bean 本身实现了 BeanFactoryAware 接口,这个时候会根据接口方法,将 BeanFactory         设置给 Bean;

   4、当 Bean 本身实现了 ApplicationContextAware 接口,这个时候 Bean会将获取到ApplicationContext 对象;
   5、当 Bean 本身实现了 BeanPostProcessor 接口时,则执行程序中的前置处理方法;
   6、当 Bean 本身实现了 InitializingBean 接口时,这个时候还会执行 afterPropertiesSet 方法,进行配置的一个加载;

   7、就是执行自身的 init 方法,进行 Bean 的初始化;
   8、执行 BeanPostProcessor 中的后置处理方法,即创建完成;

   9、被程序使用和最终销毁。

关于bean的生命周期,网上还有一个图可以说明:

Spring Bean生命周期与循环依赖等源码学习笔记_第2张图片

 不过这里少了bean实现几个内置接口的过程。

BeanFactory与FactoryBean

Beanfactory作为bean对象的工厂,属于Spring容器相关体系的根结点接口,作为获取bean完整对象的入口。BeanFactory保存从配置文件中读取到的BeanDefinition信息存在beanDefinitionMap中:

private final Map beanDefinitionMap;

默认的BeanFactory实现类:

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    @Nullable
    private static Class javaxInjectProviderClass;
    private static final Map> serializableFactories;
    @Nullable
    private String serializationId;
    private boolean allowBeanDefinitionOverriding = true;
    private boolean allowEagerClassLoading = true;
    @Nullable
    private Comparator dependencyComparator;
    private AutowireCandidateResolver autowireCandidateResolver;
    private final Map, Object> resolvableDependencies;
    private final Map beanDefinitionMap;
    private final Map mergedBeanDefinitionHolders;
    private final Map, String[]> allBeanNamesByType;
    private final Map, String[]> singletonBeanNamesByType;
    private volatile List beanDefinitionNames;
    private volatile Set manualSingletonNames;
    @Nullable
    private volatile String[] frozenBeanDefinitionNames;
    private volatile boolean configurationFrozen; 
  

先创建Bean(doCreateBean),再填充bean属性(populateBean):

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }

        if (instanceWrapper == null) {
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }

        Object bean = instanceWrapper.getWrappedInstance();
        Class beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        synchronized(mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                } catch (Throwable var17) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
                }

                mbd.postProcessed = true;
            }
        }

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

        Object exposedObject = bean;

        try {
            this.populateBean(beanName, mbd, instanceWrapper);
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);


FactoryBean自定义类的生产方式,生产特殊的bean。具有its signalinstance的方法和getobject的方法。在bean的创建过程中,会判断如果bean实现了FactoryBean的接口,则会调用它的getobject方法实例化对象。

public interface FactoryBean {
    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    @Nullable
    T getObject() throws Exception;

    @Nullable
    Class getObjectType();

    default boolean isSingleton() {
        return true;
    }
}

循环依赖

Spring在创建bean对象过程中可能会有循环依赖的问题,也就是两个或者多个bean对象相互作为属性形成了循环依赖。Spring为解决循环依赖使用了三级缓存。其中,一级缓存存放的完整的bean,二级缓存存放的实例化但不完整而且被其他正在创建的bean设置为属性的的bean,三级缓存存放是还没实例化的bean,以一个lambda表达式表示,也是一个匿名对象,内部有一个getObject方法负责生产bean对象,当被调用的时候有两种情况,一种是生产出普通对象,一种是生产bean的动态代理对象,使用三级缓存保证了生产bean过程的唯一性。

三级缓存对象在类DefaultSingletonBeanRegistry中:

private final Map singletonObjects = new ConcurrentHashMap(256); // 一级缓存
private final Map> singletonFactories = new HashMap(16);//三级缓存
private final Map earlySingletonObjects = new ConcurrentHashMap(16);//二级缓存
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                synchronized(this.singletonObjects) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        singletonObject = this.earlySingletonObjects.get(beanName);
                        if (singletonObject == null) {
                            ObjectFactory singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                            if (singletonFactory != null) {
                                singletonObject = singletonFactory.getObject();
                                this.earlySingletonObjects.put(beanName, singletonObject);
                                this.singletonFactories.remove(beanName);
                            }
                        }
                    }
                }
            }
        }

        return singletonObject;
    }

从上面代码看出,获取对象(getSingleton)的时候首先从一级缓存中尝试获取,如果结果为空,则从二级缓存中获取,如果结果再为空,则从三级缓存中获取singletonFactory对象并调用getObject方法创建对象,然后将结果放到二级缓存,删除三级缓存。

事务

Spring事务的两种表示形式,一种是通过注解,也就是是使用transaction注解进行标注,另一种是通过配置文件的方式,也就是在xml配置文件中配置transaction manager以及通知和事务切点。

Springboot核心思想

1、约定大于配置,约定项目目录结构;

2、提供内置tomcat,方便打jar包编译和部署;

3、自动配置集成第三方组件框架,如集成kafka、mybatis等;
4、提供web starter起步依赖,简化配置;

你可能感兴趣的:(java,面试,Spring,后端,java,循环依赖,bean生命周期,IOC)