zoukankan      html  css  js  c++  java
  • spring bean的生命周期

    1.源码分析

    对于 Spring Bean 来说,并不是启动阶段就会触发 Bean 的实例化,只有当客户端通过显式或者隐式的方式调用 BeanFactory 的 getBean() 方法时,它才会触发该类的实例化方法。当然对于 BeanFactory 来说,也不是所有的 getBean() 方法都会实例化 Bean 对象,例如作用域为 singleton 时,只会在第一次,实例化该 Bean 对象,之后会直接返回该对象。但如果使用的是 ApplicationContext 容器,则会在该容器启动的时候,立即调用注册到该容器所有 Bean 的实例化方法。

    getBean() 既然是 Bean 对象的入口,我们就先从这个方法说起,getBean() 方法是属于 BeanFactory 接口的,它的真正实现是 AbstractAutowireCapableBeanFactory 的 createBean() 方法,而 createBean() 是通过 doCreateBean() 来实现的,具体源码实现如下:

    @Override
    
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    
            throws BeanCreationException {
    
        if (logger.isTraceEnabled()) {
    
            logger.trace("Creating instance of bean '" + beanName + "'");
    
        }
    
        RootBeanDefinition mbdToUse = mbd;
    
        // 确定并加载 Bean 的 class
    
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    
            mbdToUse = new RootBeanDefinition(mbd);
    
            mbdToUse.setBeanClass(resolvedClass);
    
        }
    
        // 验证以及准备需要覆盖的方法
    
        try {
    
            mbdToUse.prepareMethodOverrides();
    
        }
    
        catch (BeanDefinitionValidationException ex) {
    
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
    
                    beanName, "Validation of method overrides failed", ex);
    
        }
    
        try {
    
            // 给BeanPostProcessors 一个机会来返回代理对象来代替真正的 Bean 实例,在这里实现创建代理对象功能
    
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    
            if (bean != null) {
    
                return bean;
    
            }
    
        }
    
        catch (Throwable ex) {
    
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
    
                    "BeanPostProcessor before instantiation of bean failed", ex);
    
        }
    
        try {
    
            // 创建 Bean
    
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    
            if (logger.isTraceEnabled()) {
    
                logger.trace("Finished creating instance of bean '" + beanName + "'");
    
            }
    
            return beanInstance;
    
        }
    
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
    
            throw ex;
    
        }
    
        catch (Throwable ex) {
    
            throw new BeanCreationException(
    
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    
        }
    
    }
    
    

    doCreateBean 源码如下:

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
    
            throws BeanCreationException {
    
        // 实例化 bean,BeanWrapper 对象提供了设置和获取属性值的功能
    
        BeanWrapper instanceWrapper = null;
    
        // 如果 RootBeanDefinition 是单例,则移除未完成的 FactoryBean 实例的缓存
    
        if (mbd.isSingleton()) {
    
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    
        }
    
        if (instanceWrapper == null) {
    
            // 创建 bean 实例
    
            instanceWrapper = createBeanInstance(beanName, mbd, args);
    
        }
    
        // 获取 BeanWrapper 中封装的 Object 对象,其实就是 bean 对象的实例
    
        final Object bean = instanceWrapper.getWrappedInstance();
    
        // 获取 BeanWrapper 中封装 bean 的 Class
    
        Class<?> beanType = instanceWrapper.getWrappedClass();
    
        if (beanType != NullBean.class) {
    
            mbd.resolvedTargetType = beanType;
    
        }
    
        // 应用 MergedBeanDefinitionPostProcessor 后处理器,合并 bean 的定义信息
    
        // Autowire 等注解信息就是在这一步完成预解析,并且将注解需要的信息放入缓存
    
        synchronized (mbd.postProcessingLock) {
    
            if (!mbd.postProcessed) {
    
                try {
    
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    
                } catch (Throwable ex) {
    
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    
                            "Post-processing of merged bean definition failed", ex);
    
                }
    
                mbd.postProcessed = true;
    
            }
    
        }
    
        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");
    
            }
    
            // 为了避免循环依赖,在 bean 初始化完成前,就将创建 bean 实例的 ObjectFactory 放入工厂缓存(singletonFactories)
    
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    
        }
    
        // 对 bean 属性进行填充
    
        Object exposedObject = bean;
    
        try {
    
            populateBean(beanName, mbd, instanceWrapper);
    
            // 调用初始化方法,如 init-method 注入 Aware 对象
    
            exposedObject = initializeBean(beanName, exposedObject, mbd);
    
        } catch (Throwable ex) {
    
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
    
                throw (BeanCreationException) ex;
    
            } else {
    
                throw new BeanCreationException(
    
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
    
            }
    
        }
    
        if (earlySingletonExposure) {
    
            // 如果存在循环依赖,也就是说该 bean 已经被其他 bean 递归加载过,放入了提早公布的 bean 缓存中
    
            Object earlySingletonReference = getSingleton(beanName, false);
    
            if (earlySingletonReference != null) {
    
                // 如果 exposedObject 没有在 initializeBean 初始化方法中被增强
    
                if (exposedObject == bean) {
    
                    exposedObject = earlySingletonReference;
    
                } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
    
                    // 依赖检测
    
                    String[] dependentBeans = getDependentBeans(beanName);
    
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
    
                    for (String dependentBean : dependentBeans) {
    
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
    
                            actualDependentBeans.add(dependentBean);
    
                        }
    
                    }
    
                    // 如果 actualDependentBeans 不为空,则表示依赖的 bean 并没有被创建完,即存在循环依赖
    
                    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 {
    
            // 注册 DisposableBean 以便在销毁时调用
    
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
    
        } catch (BeanDefinitionValidationException ex) {
    
            throw new BeanCreationException(
    
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    
        }
    
        return exposedObject;
    
    }
    
    

    从上述源码中可以看出,在 doCreateBean() 方法中,首先对 Bean 进行了实例化工作,它是通过调用 createBeanInstance() 方法来实现的,该方法返回一个 BeanWrapper 对象。BeanWrapper 对象是 Spring 中一个基础的 Bean 结构接口,说它是基础接口是因为它连基本的属性都没有。

    BeanWrapper 接口有一个默认实现类 BeanWrapperImpl,其主要作用是对 Bean 进行填充,比如填充和注入 Bean 的属性等。

    当 Spring 完成 Bean 对象实例化并且设置完相关属性和依赖后,则会调用 Bean 的初始化方法 initializeBean(),初始化第一个阶段是检查当前 Bean 对象是否实现了 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 等接口,源码如下:

    private void invokeAwareMethods(final String beanName, final Object bean) {
    
        if (bean instanceof Aware) {
    
            if (bean instanceof BeanNameAware) {
    
                ((BeanNameAware) bean).setBeanName(beanName);
    
            }
    
            if (bean instanceof BeanClassLoaderAware) {
    
                ClassLoader bcl = getBeanClassLoader();
    
                if (bcl != null) {
    
                    ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
    
                }
    
            }
    
            if (bean instanceof BeanFactoryAware) {
    
                ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    
            }
    
        }
    
    }
    
    

    其中,BeanNameAware 是把 Bean 对象定义的 beanName 设置到当前对象实例中;BeanClassLoaderAware 是将当前 Bean 对象相应的 ClassLoader 注入到当前对象实例中;BeanFactoryAware 是 BeanFactory 容器会将自身注入到当前对象实例中,这样当前对象就会拥有一个 BeanFactory 容器的引用。

    初始化第二个阶段则是 BeanPostProcessor 增强处理,它主要是对 Spring 容器提供的 Bean 实例对象进行有效的扩展,允许 Spring 在初始化 Bean 阶段对其进行定制化修改,比如处理标记接口或者为其提供代理实现。

    在初始化的前置处理完成之后就会检查和执行 InitializingBean 和 init-method 方法。

    InitializingBean 是一个接口,它有一个 afterPropertiesSet() 方法,在 Bean 初始化时会判断当前 Bean 是否实现了 InitializingBean,如果实现了则调用 afterPropertiesSet() 方法,进行初始化工作;然后再检查是否也指定了 init-method,如果指定了则通过反射机制调用指定的 init-method 方法,它的实现源码如下:

    protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
    
            throws Throwable {
    
        // 判断当前 Bean 是否实现了 InitializingBean,如果是的话需要调用 afterPropertiesSet()
    
        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 {
    
                ((InitializingBean) bean).afterPropertiesSet(); // 属性初始化
    
            }
    
        }
    
        // 判断是否指定了 init-method()
    
        if (mbd != null && bean.getClass() != NullBean.class) {
    
            String initMethodName = mbd.getInitMethodName();
    
            if (StringUtils.hasLength(initMethodName) &&
    
                    !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
    
                    !mbd.isExternallyManagedInitMethod(initMethodName)) {
    
                // 利用反射机制执行指定方法
    
                invokeCustomInitMethod(beanName, bean, mbd);
    
            }
    
        }
    
    }
    
    

    初始化完成之后就可以正常的使用 Bean 对象了,在 Spring 容器关闭时会执行销毁方法,但是 Spring 容器不会自动去调用销毁方法,而是需要我们主动的调用。

    如果是 BeanFactory 容器,那么我们需要主动调用 destroySingletons() 方法,通知 BeanFactory 容器去执行相应的销毁方法;如果是 ApplicationContext 容器,那么我们需要主动调用 registerShutdownHook() 方法,告知 ApplicationContext 容器执行相应的销毁方法。

    2.流程图

    2OcKfI.png

  • 相关阅读:
    Linux的iptables和netfilter
    adb安装电视apk
    令牌桶实现服务器限流
    观察者模式代码实现
    Windows系统安装Oracle 11g 数据库
    Gitlab安装后 启动之后报错502
    Git两库合并历史记录
    Maven打包时指定对应环境的配置文件
    HierarchicalDataTemplateGridControl
    自定义CommandHandler
  • 原文地址:https://www.cnblogs.com/xiaodou00/p/14890120.html
Copyright © 2011-2022 走看看