美文网首页
spring容器之创建bean的终结篇

spring容器之创建bean的终结篇

作者: 会上树的程序猿 | 来源:发表于2019-07-23 23:30 被阅读0次

关于bean的创建篇章,本节是终结篇,也是我们对#doCreateBean(...)方法的最后一个过程的详细分析,即初始化bean,这里的bean是我们最终想要的bean,直接看代码:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            //1.激活Aware,对特殊的bean进行处理,比如:Aware BeanClassLoaderAware BeanFactoryAware
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        //同上
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        //2.应用前置处理器
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        //3.激活用户自定义的init方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        //4.应用后置处理器
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

上述就是初始化bean的过程,简单的来小结一下流程:

    1. 激活Aware方法
  • 2.前置处理器的应用
  • 3.激活用户自定义的方法
    1. 后置处理器的应用

我们分别来看上述的这四个流程

激活Aware方法

我们先来了解下什么是Aware,Aware是感知的意思,在spring中提供了一些Aware相关的接口,如:BeanFactoryAware ApplicationContextAware ResourceLoaderAware ServletContextAware BeanClassLoaderAware及ResourceLoaderAware BootstrapContextAware BeanNameAware,简单的来看几个:

  • BeanFactoryAware:声明BeanFactory
  • BeanClassLoaderAware:是spring类的bean加载器
  • BeanNameAware: 是spring用来申明bean的名字

直接来看激活Aware的方法

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

代码简单,就不多说啥了,接着我们来看前置处理器的应用

前置处理器的应用

BeanPostProcessor相信大家不陌生,这是spring框架中的一个亮点,其主要的作用是:如果我们想要在 Spring 容器完成 Bean 的实例化,配置和其他的初始化后添加一些自己的逻辑处理,那么请使用该接口,该接口给了用户充足的权限去更改或者扩展 Spring是,我们对 Spring 进行扩展和增强处理一个必不可少的接口,直接看代码:

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

上述是前置处理代码,我们再来看后置处理代码:

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

关于前置和后置处理,该方法都是实现接口BeanPostProcessor接口,我们也可以实现该接口来实现对bean的逻辑处理,方法简单就不多说了,最后我们来看激活自定义的init方法

激活用户自定义的方法

何为自定义的init方法这样说可能很蒙蔽,我们可能最熟悉的是在配置文件中有时候会使用init-method,其实这里说的就是该方法,直接看代码;

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
        throws Throwable {
    //首先是检查是否是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>) () -> {
                    //1.属性初始化后的处理
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            //同上
            ((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)) {
            //2.激活自定义方法的入口
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

上述代码是激活用户自定义init方法的过程,简单的小结一下:

  • 首先是对bean的判断是否是InitializingBean,是的话需要调用#afterPropertiesSet()来处理,这里考虑到了另外的一种方式是通过实现InitializingBean接口的方法,并非来自我们的init-method配置
  • 判断完之后,接着是对属性的初始化过程,具体实现我们后面来说
  • 最后调用#invokeCustomInitMethod(...)完成真正的激活过程,具体详解后面说.

到这里我们一个完整的bean从创建到属性填充在到循环依赖的处理最后是完成初始化就说完了,后续的文章中我们来一起学习下spring容器的扩展部分

相关文章

网友评论

      本文标题:spring容器之创建bean的终结篇

      本文链接:https://www.haomeiwen.com/subject/arjzlctx.html