spring的循环依赖详解

spring实例化入口

在启动程序的时候,启动代码如下:

public class SpringMain {

    public static void main(String[] args) {

        //初始化spring容器  在初始化的时候完成了依赖注入
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringTest.class);

    }
}

在执行该代码的时候便完成了spring容器的初始化的过程。

而依赖注入的功能便是在spring容器初始化(即初始化bean–该过程是bean的生命周期)的时候完成。

bean和对象的区别

springBean有完整的生命周期。
java对象只是我们new出来的。
springBean可以是java对象,java对象不可以是bean。

普通类 vs bean 的实例化过程

普通类

在这里插入图片描述
User.java通过javac编译为了class文件

程序执行启动类的时候,会调用c++代码启动jvm虚拟机

jvm虚拟机会将编译好的class文件加载到jvm的内存当中,比如说方法区。

当遇到new关键字的时候,会根据方法区的java模版,去堆上分配一块内存用来存储该new的对象

bean

在这里插入图片描述
在这里插入图片描述
首先X Y等是添加了Component注解的类

这些类会被编译为class文件

当程序启动的时候,会调用c++启动jvm虚拟机

jvm虚拟机会将class文件加载到虚拟机当中

当虚拟机执行到启动类的部分的时候,即如下部分

在这里插入图片描述
spring会先去解析SpringTest.class类中的@ComponentScan注解中包中的所有的bean
在这里插入图片描述
获取到所有的bean之后,要分别获取各自bean的类上的各种注解

如@Lazy @DependOn等等,然后spring会new一个对象(BeanDefinition的子类)来存储这些信息
在这里插入图片描述
随后,该对象会被放在一个map中
在这里插入图片描述
然后调用preinstantiateSingleton方法遍历该map,获取到beanDefinition的对象,通过该对象判断该bean是否是单例,是否有懒加载等等等等,遍历验证完该对象之后,会将该对象放在单例池当中。

小结

单例对象生成过程:

通过javac编译为class文件

spring对class文件进行解析(读取注解)并生成beanDefinition对象存储bean的基本信息

将该beanDefinition存储在map中

调用preinstantiateSingleton获取map,遍历map,对map中的该beanDefinition内存储的信息进行验证,验证是否是单例,是否有懒加载等等注解

将验证后没问题的bean存储到spring的单例池中

spring对外扩展

spring提供了程序员扩展的空间

在对象存到map中后,调用preinstantiateSingleton方法之前,程序员可以进行一定的扩展。
在这里插入图片描述
spring在将数据存放到map中之后,调用preinstantiateSingleton方法之前,会看一下程序员是否进行了扩展,如果进行了扩展,spring就会调用扩展的一些方法将该map传过去。

程序员获取到了map,即获取到了BeanDefinition,在BeanDefinition中有一个是beanClass,存储的就是我们使用@Component等注解的X类。程序员可以修改该beanClass的值,比如将X改为了Y。修改的这一步就是在进行扩展操作。修改完成之后再将值重新放回map中。

此时spring再将map放到spring的单例池中。此时放进去的就是Y而不是X了。
在这里插入图片描述
在这里插入图片描述

扩展demo

public class IndexService {
    
    public IndexService(){
        System.out.println("indexService construct");
    }
    
}
@Component
public class UserService {
    
    public UserService(){
        System.out.println("UserService construct");
    }

}
@ComponentScan("com.guo.admin.web.spring")
public class SpringTest {
}
//扩展类
@Component
public class BeanDefinationSelf implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        GenericBeanDefinition genericBeanDefinition = (GenericBeanDefinition) beanFactory.getBeanDefinition("userService");

        genericBeanDefinition.setBeanClass(IndexService.class);

    }
}
//在该类中获取到添加了@Component注解的UserService类,然后将其的BeanClass值设为了IndexService类。

启动类

public class SpringMain {

    public static void main(String[] args) {

        //初始化spring容器  在初始化的时候完成了依赖注入
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringTest.class);

        System.out.println(context.getBean(IndexService.class));

    }
}

执行结果如下:可以看到IndexService对象生成了,成为了Spring的bean对象。
在这里插入图片描述
如果没有扩展类(将扩展类上的@Component注解注释掉)的话,启动启动类的结果是如下图:
在这里插入图片描述
该demo实现了对speing的二次扩展。

spring源码

入口

public AnnotationConfigApplicationContext(Class... componentClasses) {
        this();
        this.register(componentClasses);
        this.refresh();//真正实现spring 的bean初始化的方法。
    }

this.refresh()

进入this.refresh();方法中

public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            //该方法完成了扫描操作--该方法执行完成之后--,an Definition放进了map中
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                //该方法完成bean对象的初始化操作。如果bean类对象的构造方法里面有日志输出,则在此方法执行之后,日志会输出出来。
                //即该方法中完成了bean对象的生命周期过程
                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();
            }

        }
    }

finishBeanFactoryInitialization()

bean对象初始化的方法源码:finishBeanFactoryInitialization();

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
            beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
        }

        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver((strVal) -> {
                return this.getEnvironment().resolvePlaceholders(strVal);
            });
        }

        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        String[] var3 = weaverAwareNames;
        int var4 = weaverAwareNames.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String weaverAwareName = var3[var5];
            this.getBean(weaverAwareName);
        }

        beanFactory.setTempClassLoader((ClassLoader)null);
        beanFactory.freezeConfiguration();
    	//该方法将会实例化所有非懒加载的单例对象
        beanFactory.preInstantiateSingletons();
    }

preInstantiateSingletons()

实例化非懒加载的单例对象源码:beanFactory.preInstantiateSingletons();

该方法获取所有的bean的名字,通过循环一个一个getBean

public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Pre-instantiating singletons in " + this);
        }

    //该list是所有bean的名字  然后对该list做了一个循环  根据名字去map中获取到对应的beanDefinition对象
        List<String> beanNames = new ArrayList(this.beanDefinitionNames);
        Iterator var2 = beanNames.iterator();

        while(true) {
            String beanName;
            Object bean;
            do {
                while(true) {
                    RootBeanDefinition bd;
                    do {
                        do {
                            do {
                                if (!var2.hasNext()) {
                                    var2 = beanNames.iterator();

                                    while(var2.hasNext()) {
                                        beanName = (String)var2.next();
                                        Object singletonInstance = this.getSingleton(beanName);
                                        if (singletonInstance instanceof SmartInitializingSingleton) {
                                            SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
                                            if (System.getSecurityManager() != null) {
                                                AccessController.doPrivileged(() -> {
                                                    smartSingleton.afterSingletonsInstantiated();
                                                    return null;
                                                }, this.getAccessControlContext());
                                            } else {
                                                smartSingleton.afterSingletonsInstantiated();
                                            }
                                        }
                                    }

                                    return;
                                }

                                beanName = (String)var2.next();
                                //在这里合并
                                bd = this.getMergedLocalBeanDefinition(beanName);
                            } while(bd.isAbstract());//判断该对象是不是
                        } while(!bd.isSingleton());//判断该对象是不是单例对象
                    } while(bd.isLazyInit());//判断该对象是不是非懒加载的对象

                    if (this.isFactoryBean(beanName)) {
                        bean = this.getBean("&" + beanName);
                        break;
                    }
//如果验证结束没有问题(不是懒加载,是单例),则执行getBean方法去完成实例化。
                    this.getBean(beanName);
                }
            } while(!(bean instanceof FactoryBean));

            FactoryBean<?> factory = (FactoryBean)bean;
            boolean isEagerInit;
            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                SmartFactoryBean var10000 = (SmartFactoryBean)factory;
                ((SmartFactoryBean)factory).getClass();
                isEagerInit = (Boolean)AccessController.doPrivileged(var10000::isEagerInit, this.getAccessControlContext());
            } else {
                isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
            }

            if (isEagerInit) {
                this.getBean(beanName);
            }
        }
    }

getBean(beanName)

getBean()

public Object getBean(String name) throws BeansException {
        return this.doGetBean(name, (Class)null, (Object[])null, false);
    }

doGetBean()

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
    	//该行代码非常重要  验证bean的名字是否非法
        String beanName = this.transformedBeanName(name);
    	//bean的名字没有非法情况后,下面该行代码会根据名字去单例池中拿bean,看单例池中是否已经存在了被实例化的该bean对象
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
    	//如果发现该bean对象已经在单例池中存在了,则走这个if方法  ---但是我们需要知道,该doGetBean方法就是在刚开始初始化bean的时候去调用的,所以不可能进入这个if方法中。
        if (sharedInstance != null && args == null) {
            if (this.logger.isTraceEnabled()) {
                if (this.isSingletonCurrentlyInCreation(beanName)) {
                    this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
                } else {
                    this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }

            bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        } 
    //因此,出了if,程序进入了else方法
    else {
        	//该if,是判断该bean对象是否正在创建过程中,如果是,则抛出异常
            if (this.isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            BeanFactory parentBeanFactory = this.getParentBeanFactory();
            if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
                String nameToLookup = this.originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                }

                if (args != null) {
                    return parentBeanFactory.getBean(nameToLookup, args);
                }

                if (requiredType != null) {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }

                return parentBeanFactory.getBean(nameToLookup);
            }

            if (!typeCheckOnly) {
                this.markBeanAsCreated(beanName);
            }

            try {
                //在该行代码中解析合并后的bd对象
                RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
                //判断bean类对象上是否添加了@DependOn注解
                String[] dependsOn = mbd.getDependsOn();
                String[] var11;
                if (dependsOn != null) {
                    var11 = dependsOn;
                    int var12 = dependsOn.length;

                    for(int var13 = 0; var13 < var12; ++var13) {
                        String dep = var11[var13];
                        if (this.isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }

                        this.registerDependentBean(dep, beanName);

                        try {
                            this.getBean(dep);
                        } catch (NoSuchBeanDefinitionException var24) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
                        }
                    }
                }

                //判断是否是单例对象---如果是单例对象,则进入该if方法   然后执行createBean方法,此时bean才开始实例化了。
                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;
            }
        }

        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = this.getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                } else {
                    return convertedBean;
                }
            } catch (TypeMismatchException var25) {
                if (this.logger.isTraceEnabled()) {
                    this.logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var25);
                }

                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        } else {
            return bean;
        }
    }

在这里插入图片描述

createBean()

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    	//校验日志
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Creating instance of bean '" + beanName + "'");
        }

    	//将mbd(RootBeanDefinition)赋值给mbdToUse----
        RootBeanDefinition mbdToUse = mbd;
    	//获取mbd的class这个属性的值(值就是bean对象的类的全限定名,这个值就是这个类,获取到了类)
        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 {
            //--------------------------
            //该行中的doCreateBean创建bean开始了~~~~ 在该行代码中,完成了原身对象和代理对象的创建(如果只是创建bean则创建bean,如果该bean被aop了,则创建了bean和它的代理bean)
            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()

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
    	//判断是否是单例  如果是单例  则将cache  remove 掉
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }

    
        if (instanceWrapper == null) {
            //实例化对象,里面第二次调用后置处理器  这里实例化的是对象,而不是bean,我们需要注意。当该方法执行完成后,构造方法中如果有日志输出,则会输出,说明对象被实例化出来了,但是这并不表示bean创建出来。因为如果我们debug一下,可以看到该bean里面的一些属性还是没有值的,还是null,只是构造方法执行完成了而已。此时实例化的是对象。
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }

    	//debug到这一行的时候,我们可以看到这个bean中的属性还是没有值的,上一行的
    //instanceWrapper = thiscreateBeanInstance(beanName, mbd, args)这个方法只是将对象实例化了,但是bean还没有被实例化。
        Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        synchronized(mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    //通过后置处理器来合并beanDefinitation 举例:AService中有两个使用@Autowire注解的属性,该方法就是将所有需要注入的属性都合并起来放到一个list集合中
                    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;
            }
        }

    	//判断是否允许循环依赖
    	//mbd.isSingleton()  默认是单例,所以结果是true
    	//this.allowCircularReferences  没讲
    	//this.isSingletonCurrentlyInCreation(beanName)   百分之百是true 理由为:老师还没讲。
        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
    	//如果允许循环依赖的话,则执行if中的方法
        if (earlySingletonExposure) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }

            //第四次调用后置处理器,spring需要将该bean对象提前暴漏出来,并且做aop
            this.addSingletonFactory(beanName, () -> {
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }

    	//将bean对象赋值给  Object exposedObject
        Object exposedObject = bean;

        try {
           //该方法进行属性的填充  就是我们常说的自动注入,里面会完成第五次和第六次的后置处理器的调用
            //在该方法中,先判断是否需要进行属性的注入,如果需要,才进行属性的注入工作
            this.populateBean(beanName, mbd, instanceWrapper);
            //初始化spring,里面会进行第七次  第八次的后置处理器的调用
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
        }

        if (earlySingletonExposure) {
            Object earlySingletonReference = this.getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                    String[] dependentBeans = this.getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                    String[] var12 = dependentBeans;
                    int var13 = dependentBeans.length;

                    for(int var14 = 0; var14 < var13; ++var14) {
                        String dependentBean = var12[var14];
                        if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }

                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        try {
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }

createBeanInstance()

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
        } else {
            Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
            if (instanceSupplier != null) {
                return this.obtainFromSupplier(instanceSupplier, beanName);
            } else if (mbd.getFactoryMethodName() != null) {
                return this.instantiateUsingFactoryMethod(beanName, mbd, args);
            } else {
                boolean resolved = false;
                boolean autowireNecessary = false;
                if (args == null) {
                    synchronized(mbd.constructorArgumentLock) {
                        if (mbd.resolvedConstructorOrFactoryMethod != null) {
                            resolved = true;
                            autowireNecessary = mbd.constructorArgumentsResolved;
                        }
                    }
                }

                if (resolved) {
                    return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd);
                } else {
                    //该行用来获取到构造方法后对构造方法进行推断
                    Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
                    if (ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args)) {
                        ctors = mbd.getPreferredConstructors();
                        //如果构造方法不为null的话,就反射autowireConstructor,如果为null 的话,就instantiateBean执行这个方法,获取默认的无参构造方法实例化对象
                        return ctors != null ? this.autowireConstructor(beanName, mbd, ctors, (Object[])null) : this.instantiateBean(beanName, mbd);
                    } else {
                        return this.autowireConstructor(beanName, mbd, ctors, args);
                    }
                }
            }
        }
    }

instantiateBean

protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
        try {
            Object beanInstance;
            if (System.getSecurityManager() != null) {
                beanInstance = AccessController.doPrivileged(() -> {
                    //通过执行instantiate得到默认的构造方法
                    return thisx.getInstantiationStrategy().instantiate(mbd, beanName, this);
                }, this.getAccessControlContext());
            } else {
                beanInstance = this.getInstantiationStrategy().instantiate(mbd, beanName, this);
            }

            BeanWrapper bw = new BeanWrapperImpl(beanInstance);
            this.initBeanWrapper(bw);
            return bw;
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", var6);
        }
    }

在该方法中通过执行instantiate方法得到默认的构造方法
在这里插入图片描述
instantiateClass方法中

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
        Assert.notNull(ctor, "Constructor must not be null");

        try {
            ReflectionUtils.makeAccessible(ctor);
            //ctor.newInstance(args)该方法完成对象的实例化
            return KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ? BeanUtils.KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args);
        } catch (InstantiationException var3) {
            throw new BeanInstantiationException(ctor, "Is it an abstract class?", var3);
        } catch (IllegalAccessException var4) {
            throw new BeanInstantiationException(ctor, "Is the constructor accessible?", var4);
        } catch (IllegalArgumentException var5) {
            throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", var5);
        } catch (InvocationTargetException var6) {
            throw new BeanInstantiationException(ctor, "Constructor threw exception", var6.getTargetException());
        }
    }
插入讲一下spring对AOP的处理
initializeBean()
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(() -> {
                this.invokeAwareMethods(beanName, bean);
                return null;
            }, this.getAccessControlContext());
        } else {
            //执行或者说回调awre方法(并不是所有的awre方法都在这个方法中进行回调)
            this.invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            //执行spring的生命周期回调  该方法执行处理的是使用注解的方法
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }

        try {
            //执行生命周期初始化回调方法  这里执行的是接口和xml方法的
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            //下面这一行代码中多后置处理器进行循环,通过其中一个后置处理器处理完成了aop
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }
完成aop代理的方法applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
  public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;

        Object current;
      //获取到所有的后置处理器后进行循环处理
        for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
            BeanPostProcessor processor = (BeanPostProcessor)var4.next();
            current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
        }

        return result;
    }

处理aop的后置处理器如下图,通过该后置处理器改变了bean,变成了代理对象
在这里插入图片描述

策略模式

上图体现了策略模式

所有的后置处理器都实现了BeanPostProcessor,每个方法都有不同的实现。有的没有对bean进行处理,有的则进行了改动。

其中有一个后置处理器的实现是这样的,看下面的代码块

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    //得到所有的注解信息   findLifecycleMetadata(找到生命周期的元数据)
    //这里使用@PostConstruct注解的bean里面的这个方法(假设叫init())就会被找到,找到后被存储了起来
        InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata metadata = this.findLifecycleMetadata(bean.getClass());

        try {
            //在该行代码中通过反射执行元数据方法即可。如上面的init()方法就会被执行
            metadata.invokeInitMethods(bean, beanName);
            return bean;
        } catch (InvocationTargetException var5) {
            throw new BeanCreationException(beanName, "Invocation of init method failed", var5.getTargetException());
        } catch (Throwable var6) {
            throw new BeanCreationException(beanName, "Failed to invoke init method", var6);
        }
    }

在这里插入图片描述

spring创建bean的顺序

spring根据bean的首字母进行排序进行创建

比如有x,y这两个bean要创建,那么会先创建x,后创建y

spring的生命周期有三种方法

这三种方法可以同时存在

在这里插入图片描述

1.实现接口

在这里插入图片描述

2.spring.xml里面添加标签参数

如下图,回调了A类的aa方法
在这里插入图片描述

3.使用注解

如下图,在类的方法上添加该注解
在这里插入图片描述

三种方法都存在的时候,spring执行的顺序是什么?

在这里插入图片描述
看上图,先执行注解,再执行接口重写方法,最后执行xml

为什么是这个顺序?

代码就是这个顺序

在这里插入图片描述

生命周期回调

生命周期回调有两种方法:初始化回调和销毁回调

@PostConstruct注解

生命周期的初始化回调方法。

问题

spring默认支持单例是循环依赖的,如何证明?

在上面的java代码块中,有一行代码是用来判断spring容器是否允许循环依赖的,即下行代码:

boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);

即spring在创建bean的过程中,该代码会判断有没有开启spring的循环依赖,判断的结果主要取决于allowCircularReferences这个属性的true false值。

通过看代码,我们可以看到该allowCircularReferences的值默认为true。

public AbstractAutowireCapableBeanFactory() {
         
        this.allowCircularReferences = true;
         
    }

如何关闭spring默认的循环依赖?

可以修改allowCircularReferences的值为false。
由于源码我们无法更改,只能在主启动类中进行更改

public class SpringMain {

    public static void main(String[] args) {

        //初始化spring容器  在初始化的时候完成了依赖注入
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringTest.class);

        //这两行代码是新增用来修改allowCircularReferences值的。但是!不起作用的!原因在下面写着。
        AbstractAutowireCapableBeanFactory beanFactory = (AbstractAutowireCapableBeanFactory) context.getBeanFactory();
        beanFactory.setAllowCircularReferences(false);
        
        
        System.out.println(context.getBean(IndexService.class));
    }
}


AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringTest.class);

之后对allowCircularReferences进行赋值为false。

但是我们需要注意的是,在

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringTest.class);

执行完成之后,bean对象已经初始化完成,bean的属性也均赋值完成,因此在该行代码之后对allowCircularReferences进行重新赋值是无用的,因为bean已经初始化完成。

解决方案

public class SpringMain {

    public static void main(String[] args) {

        //这里我们使用无参构造方法创建了context
        //然后再执行context的register方法,然后添加我们修改属性值的方法,最后执行refresh方法。
        //这样就实现了属性修改。为什么这样能实现属性修改呢?看下面文字讲解。
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(SpringTest.class);
        AbstractAutowireCapableBeanFactory beanFactory = (AbstractAutowireCapableBeanFactory) context.getBeanFactory();
        beanFactory.setAllowCircularReferences(false);
        context.refresh();

        System.out.println(context.getBean(IndexService.class));
    }
}

当代码为

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringTest.class);

的时候,我们创建context是使用了有参构造,而有参构造的源码为:

public AnnotationConfigApplicationContext(Class... componentClasses) {
        this();//调用默认构造方法
        this.register(componentClasses);
        this.refresh();
    }

而我们的解决方案中的代码为:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

使用的是无参构造创建的context,无参构造的源码为:

public AnnotationConfigApplicationContext() {
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

这个无参构造方法就是 有参构造方法中的 this()方法。

因此方案一中,

先调用无参构造,再执行register方法,然后执行手动代码(修改属性),最后执行refresh方法,便可以成功修改属性。因为refresh方法才是正式初始化bean的方法。

源码继续跟踪

populateBean()

populateBean()方法源码 该方法实现bean的属性注入

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        if (bw == null) {
            if (mbd.hasPropertyValues()) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
        } else {
            boolean continueWithPropertyPopulation = true;
            if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
                Iterator var5 = this.getBeanPostProcessors().iterator();

                while(var5.hasNext()) {
                    BeanPostProcessor bp = (BeanPostProcessor)var5.next();
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                        if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                            continueWithPropertyPopulation = false;
                            break;
                        }
                    }
                }
            }

            if (continueWithPropertyPopulation) {
                PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;
                if (mbd.getResolvedAutowireMode() == 1 || mbd.getResolvedAutowireMode() == 2) {
                    MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
                    if (mbd.getResolvedAutowireMode() == 1) {
                        this.autowireByName(beanName, mbd, bw, newPvs);
                    }

                    if (mbd.getResolvedAutowireMode() == 2) {
                        this.autowireByType(beanName, mbd, bw, newPvs);
                    }

                    pvs = newPvs;
                }

                boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
                boolean needsDepCheck = mbd.getDependencyCheck() != 0;
                PropertyDescriptor[] filteredPds = null;
                if (hasInstAwareBpps) {
                    if (pvs == null) {
                        pvs = mbd.getPropertyValues();
                    }

                    //获取所有的后置处理器   转换为迭代器进行循环处理
                    Iterator var9 = this.getBeanPostProcessors().iterator();

                    //在这里进行后置处理器的循环
                    //也就是说,每个后置处理器依次对该bean进行处理,完成该bean的属性注入操作
                    while(var9.hasNext()) {
                        BeanPostProcessor bp = (BeanPostProcessor)var9.next();
                        if (bp instanceof InstantiationAwareBeanPostProcessor) {
                            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                            //该行执行完成之后,bean的属性才被注入进去的。这里插入一个问题,看下面文字。
                            PropertyValues pvsToUse = ibp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
                            if (pvsToUse == null) {
                                if (filteredPds == null) {
                                    filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                                }

                                pvsToUse = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                                if (pvsToUse == null) {
                                    return;
                                }
                            }

                            pvs = pvsToUse;
                        }
                    }
                }

                if (needsDepCheck) {
                    if (filteredPds == null) {
                        filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                    }

                    this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
                }

                if (pvs != null) {
                    this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
                }

            }
        }
    }

首先,在上面代码块中

Iterator var9 = this.getBeanPostProcessors().iterator();该代码获取到了所有的后置处理器,并转换为了迭代器。

即, this.getBeanPostProcessors()获取到的是一个后置处理器x,y,z等的list集合。当循环到了AutowiredAnnotationBeanPostProcessor这个后置处理器的时候,再执行

if (hasInstAwareBpps) {
                    if (pvs == null) {
                        pvs = mbd.getPropertyValues();
                    }

                    Iterator var9 = this.getBeanPostProcessors().iterator();

                    while(var9.hasNext()) {
                        BeanPostProcessor bp = (BeanPostProcessor)var9.next();
                        if (bp instanceof InstantiationAwareBeanPostProcessor) {
                            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                            PropertyValues pvsToUse = ibp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
                            if (pvsToUse == null) {
                                if (filteredPds == null) {
                                    filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                                }

                                pvsToUse = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                                if (pvsToUse == null) {
                                    return;
                                }
                            }

                            pvs = pvsToUse;
                        }
                    }
                }

ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)这个方法之后,bean对象中如果有使用@Autwired注解注入的属性X,那么在这一行代码执行完成之后,该属性就有值了。

说的再直白一点便是:

如果该X的构造方法中有日志输出,那么在这一行代码执行完成之后,该日志便会输出来。说明该X对象被创建了。但是我们需要注意的是,是X对象被new出来了,而不是被初始化完成了。

如果属性是使用@Resouce这个注解去注入的话,会被@CommonAnnotationBeanPostProcessor注解解析并完成该属性的值的注入。


此时,X被new出来之后,X便要继续走初始化生命周期的流程了。同理,走到这儿的时候,X里面如果有需要注入的属性M,则一样要走M的声明流程。这里就有一个情况,X中有Y属性,Y中有X属性。这种情况怎么走呢?

代码如下:

@Component
public class UserService {

    @Autowired
    private IndexService indexService;


    public UserService() {
        System.out.println("UserService construct");
    }

}
@Component
public class IndexService {

    @Autowired
    private UserService userService;

    public IndexService() {
        System.out.println("indexService construct");
    }

}

当程序主启动类启动的时候,会初始化扫描包下面的所有的component。

如果首先初始化的是IndexService,那么执行到populateBean()方法时,需要给IndexService的属性进行值注入。此时IndexService的属性是UserService。
在这里插入图片描述
看上图,走到这一步的时候,ibp是AutowiredAnnotation···的后置处理器,(UserService在IndexService里面就是用@Autowired注解去实现注入的),debug的那一行还没有执行的时候,userService的值还是空的,值还没有注入进来。

当执行了这一步的时候,我们可以看到下图,直接跳到了getBean方法,开始getBean(userService)了。
在这里插入图片描述
然后也是一模一样的流程,走到下图这一步的时候,userService对象被创建出来了。(执行了构造方法)
在这里插入图片描述
然后继续执行,执行到了同样的需要属性注入的地方

在这里插入图片描述
该行执行完成之后,马上就跳转到了getBean方法去获取indexService(请看下图)
在这里插入图片描述
然后我们可以看到,在doGetBean方法中的第二行方法(下图),indexService的this.getSingleton方法是有值的。
在这里插入图片描述

getSingleton()

@Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        //如果下行判断成立,则会走进if代码里面。里面代码是会去第三个缓存中去获取bean对象
        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;
    }
看这个源码第一行,通过beanName去singletonObjects中找数据。而这个singletonObjects是去单例池中找数据的。如果IndexService还没有初始化完成,并且也不在创建当中,那么返回的值就是一个null,进不了if代码中,该方法便会返回一个null

在这里插入图片描述

public boolean isSingletonCurrentlyInCreation(String beanName) {
        return this.singletonsCurrentlyInCreation.contains(beanName);
    }

判断bean是否正在创建中,是通过上块代码块执行的。那么这个

private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap(16));

那么,这个Set是哪儿给赋值的呢?
就是在doGetBean方法中

在这里插入图片描述

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        synchronized(this.singletonObjects) {
            //根据beanName没有获取到数据,就进入下面的if里面
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }

                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
				//这一步是在创建单例对象之前执行的一个方法。
                this.beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = this.suppressedExceptions == null;
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet();
                }

                try {
                    
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                } catch (IllegalStateException var16) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw var16;
                    }
                } catch (BeanCreationException var17) {
                    BeanCreationException ex = var17;
                    if (recordSuppressedExceptions) {
                        Iterator var8 = this.suppressedExceptions.iterator();

                        while(var8.hasNext()) {
                            Exception suppressedException = (Exception)var8.next();
                            ex.addRelatedCause(suppressedException);
                        }
                    }

                    throw ex;
                } finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }

                    this.afterSingletonCreation(beanName);
                }

                if (newSingleton) {
                    this.addSingleton(beanName, singletonObject);
                }
            }

            return singletonObject;
        }
    }

this.beforeSingletonCreation(beanName);源码:该方法就是将beanName放到 Set中去,就表示这个bean正在被创建。

protected void beforeSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) &&
            //这个方法将bean放到set中,表示该bean正在创建当中。
            !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    }

然后在this.beforeSingletonCreation(beanName)这一行代码之后的singletonObject = singletonFactory.getObject();,其实执行的就是

return this.createBean(beanName, mbd, args);

这个方法。

三个map缓存bean

在刚进入doGetBean()方法中的时候,会先执行以下方法判断该bean是否已经存在了

@Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //从一级缓存中查找     该singletonObjects就是一级缓存
        Object singletonObject = this.singletonObjects.get(beanName);
        //如果是第一次创建bean对象且正在创建过程中,此时singletonObject为null,但是后面的条件为true,此时进入了if方法中
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            synchronized(this.singletonObjects) {
                //earlySingletonObjects 是第三个map。该map是三级缓存。在三级缓存中没有找到该bean,取出来的值是null
                singletonObject = this.earlySingletonObjects.get(beanName);
                //allowEarlyReference该值是在调用getSingleton()这个方法的时候写死传进来的,写死为true,因此该if条件满足,进入了if里面的方法
                if (singletonObject == null && allowEarlyReference) {
                    //singletonFactories 是第二个map
                    //从该map中再次获取一次beanFactory,此时是能够获取到的。
                    //是在哪里往singletonFactories里面放数据的呢?在doCreateBean方法里面放的,可以看下面的图。
                    ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        //从该工厂中获取到bean
                        singletonObject = singletonFactory.getObject();
                        //将bean放到三级缓存中
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        //将bean从二级缓存中移除,为什么要移除呢?
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }

        return singletonObject;
    }

singletonFactories 也是一个map
在这里插入图片描述
doCreateBean()方法中

满足是单例,允许循环依赖,当前bean正在创建中这三个条件,便执行addSingletonFactory方法,将bean放在该factory中
在这里插入图片描述

小结

一共有三个map

1.singletonObjects 单例池 (可以理解为spring容器)(一级缓存)(存储的是bean对象)

2.singletonFactory 工厂(二级缓存,存放的是工厂)

3.earlySingletonObjects 三级缓存(存储的是对象)

为什么要从二级缓存工厂中拿出对象后,put进三级缓存中,为什么不直接从二级缓存中拿这个对象去使用?

答:防止工厂重复生产对象

具体解析

singletonObject = singletonFactory.getObject();

该getObejct()方法,具体是走下面这个代码
在这里插入图片描述
getEarlyBeanReference()方法如下:
在这里插入图片描述
获取到了所有的后置处理器,并进行了循环处理,这样才在工厂中将该bean创建了出来

因此我们每次从二级缓存中执行getObject方法,都是在工厂中创建一次bean对象的过程。为了防止bean对象重复创建(有的bean创建的时间很长,如果重复创建,会影响性能),就出现了三级缓存,我们第一次从二级缓存中创建了对象后,便将其放接了三级缓存中,然后remove了二级缓存。

有三个service:aService,bService,cService,aService和bService中都注入了cService,如果没有三级缓存的话,aService这个bean创建的时候,需要注入cService,工厂创建了一次cService;bService这个bean创建的时候,需要注入cService,工厂又创建了一次cService,那么这样是不太合理的。

二级缓存的作用

1.有两个service,且为循环依赖场景
在这里插入图片描述
在这里插入图片描述
2.过程如下:

1.spring启动,先进行indexService的bean的创建

2.执行到doCreateBean-createBeanInstance执行了indexService的构造方法, indexService的对象创建完成

3.接下来将该indexService放到二级缓存工厂中

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

4.接下来执行this.populateBean(beanName, mbd, instanceWrapper)方法进行属性的注入,这里的属性指userService。

5.userService同样先进行对象的创建,然后放到二级缓存工厂中,然后进行属性的注入,此时需要注入的属性是indexService

6.在执行populateBean方法的时候,会跳到getBean方法去获取indexService

7.doGetBean方法中会执行getSingleton方法获取indexService

8.getSingleton方法中,先去单例池中获取bean对象,没有获取到(因为此时indexService还只是对象,而不是bean),接下来去三级缓存中获取,也没有获取到(因为还没有往三级缓存中put过)。最后到二级缓存factory中生产对象,执行getObject方法,在该方法中对后置处理器进行了循环,将indexService创建了出来(在此过程中,也完成了indexService 的PostConstruct方法,完成了aop代理)。

9.userService继续执行initializeBean完成初始化

10.将userService放入单例池中

11.将indexService继续执行initializeBean完成初始化

12.将indexService放入单例池中

为什么二级缓存中不放对象,而是放工厂?

放了工厂后,该工厂后期需要对要注入的还不是bean的对象进行改造优化升级,最后改造成bean的。

为什么需要三个缓存map?

第一个map:单例池,因为spring的单例对象只会被实例化一次,所以需要一个单例池来缓存该信息

第二个map:缓存的是工厂,主要是为了解决循环依赖。X中注入Y,Y中注入X,先创建X,接下来注入Y的时候去创建Y,在注入Y的属性X的时候,获取到了第二个缓存map中的X对应的工厂,通过工厂对X进行了加工,这里的加工指对X进行代理操作以及其他等等操作,最后将X赋值给Y的属性。

什么叫spring容器?

spring容器并不是简单的单例池。

在spring中有很多的组件如beanFactory,三个map,各类后置处理器等所有组件的组成叫做spring容器。

为什么在spring判断支持循环依赖后,要提前暴漏自己?

判断是否需要属性注入的源码逻辑

在这里插入图片描述
有上图这样一个后置处理器

如果我们扩展这个后置处理器,如下行代码那样写

@Component
public class XXX implements InstantiationAwareBeanPostProcessor {

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

}

项目中的所有的bean各自的属性都无法注入了

spring的生命周期

spring容器启动

随后进行扫描,将类变成bean definition存储到bean defitionMap当中

然后对该map进行遍历,目的是验证是否单例、是否原型、是否懒加载、是否有DepensOn、是否抽象、是否factoryBean、是否这个bean的名字符合等等

随后获取当前实例化的类是否存在单例池当中(是否被创建,如果没有被创建,则去二级缓存中判断是否存在,即判断是否被提前暴漏),是否被提前暴漏,如果没有提前暴漏的话,则spring的bean就会开始创建该bean

创建bean的过程:

通过推断构造方法的过程把当前bean所代表的类当中的构造方法得到一个最佳的构造方法(因为bean代表的是一个JAVA类,一个JAVA类当中可能存在十几个构造方法,不同的注重模型会使用不同的构造方法,因此spring需要推断一下创建该bean的时候需要使用哪个构造方法)

通过反射实例化java对象

根据该java对象对这个bean进行一些初始化的工作,如是否要对该bean进行beanDefinition的合并;如spring容器是否支持循环依赖,如果支持循环依赖的话,需要提前暴漏当前java对象也就是半成品所对应的一个ObjectFactory的工厂类,即提前暴漏该工厂类。

提前暴漏具体指什么?

将要暴漏的对象存储到一个map中,这个map我们称之为是二级缓存。

暴漏执行完成之后,spring会进行属性填充操作,即自动注入。具体指,如A中依赖了B,则将Bset到A中。

set操作执行完成之后,spring会继续执行一些接口的回调操作

然后会进行一个生命周期初始化的回调操作,如添加了注解@PostConstract 或者@InitializerBean等等

如果项目当中有AOP的话,会生成代理,如果没有的话,则不会生成代理。随后会进行事件的发布操作。

bean的声明周期到此完成,该bean对象会被存储到单例池当中。

map解决循环依赖

spring实例化A的时候,会对A进行基本的验证操作,随后查看A是否被提前暴漏,即A对应的ObjectFactory是否有被提前暴漏

此时是没有被提前暴漏的

随后spring会推断出一个合适的构造方法将A实例化出来。

随后A走到了是否要提前暴漏的方法中,因为当前默认容器是都需要提前暴漏的

A被提前暴漏,此时暴漏的是A生成的创建出来的一个ObjectFactory对象,一个工厂对象

随后进行A的属性填充,填充Y

此时发现Y并没有存在spring的容器中,即Y并没有被实例化,此时会进行Y的实例化操作,即进行Y 的生命周期的一系列过程。

在对Y进行属性填充的时候,填充X,发现X并没有被实例化完全(因为此时X实例化流程完成了一半还没有全部完成),会走一遍创建X的流程,在进行创建X的过程中,会发现X已经被提前暴漏了,所以Y能够拿到已经被提前暴漏的ObjectFactory所产生的一个X对象,这样就完成了循环依赖。

注意:此时的spring是单例的,也就是说循环依赖是支持单例的。但是这里需要注意,此时的循环依赖支持的bean对象 A B,不是通过构造函数的方式注入对象的。因为如果AB对象是通过构造方法创建方式的话,那么永远也无法创建该对象出来。

为什么不直接缓存一个X而是缓存一个ObejctFactory呢?

如果缓存的是X,那么从缓存中拿出来的便仅仅是一个X,程序员很难对其进行扩展改变。

但是如果缓存的是ObjectFactory,springFarmwork的内部通过BeanProcessor 这个接口可以对该factory产生X的过程中进行一定的扩展改变干预的,可以得到自己想要的一个Bean对象。

总结:

bean是由一个BeanDefinition来构建的,BeanDefinition可以理解为springBean的一个建模。

参考

在这里插入图片描述

b站:https://www.bilibili.com/video/BV1uE411d7L5?p=7&spm_id_from=pageDriver

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GYX--UP

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值