【九】Spring IoC 最全源码详解之initializeBean

版权声明:本博客原创文章遵循CC BY-NC-SA 2.5 CN 协议 https://blog.csdn.net/wuyuwei/article/details/88252969

如果bean的依赖注入完成比作进化出猴子,那么最后的bean初始化过程就是给猴子穿上了衣服,变成了人。


目录

1. 实现Aware接口对bean的设置

2. 依次回调bean后置处理器的postProcessBeforeInitialization方法

2.1 ApplicationContextAwareProcessor

2.2 ImportAwareBeanPostProcessor

2.3 CommonAnnotationBeanPostProcessor

3. 用户自定义的init方法方法

4. 依次回调bean后置处理器的postProcessAfterInitialization方法

5. @PreDestory方法的注册


*本篇文章的项目沿用《【七】Spring IoC 最全源码详解之bean的依赖注入》的。

在doCreateBean中,依赖注入populateBean执行完成后,紧接着就是创建bean的最后一步:初始化bean。本节就来看看Spring是如何初始化bean的。

Object exposedObject = bean;
try {        
    // 依赖注入填充属性
    populateBean(beanName, mbd, instanceWrapper);
    // bean属性填充完成后,就可以进行bean的初始化工作了。依赖注入初始化工作后续文章再详细介绍。
    exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
    throw new xxx;
}

初始化bean的入口函数是initializeBean。

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        // 如果实现了Aware接口,就对该bean进行一些设置。
        // 比如实现了BeanNameAware接口,那么对其bean的属性beanName上set上对应的beanName。
        // 如果实现了BeanFactoryAware接口,那么对其beanFactory属性设置上创建该bean使用的bean工厂。
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    // 如果这个bd不是属于内部类的bd,就调用后置处理器的postProcessBeforeInitialization对bean进行操作。
    // 
    // common 执行LifeCircle操作
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    
    //如果bean实现了InitializingBean或者用户自定义的init方法方法,那么调用这些初始化方法对bean的属性进行一些个性化设置。
    invokeInitMethods(beanName, wrappedBean, mbd);
    
    // 执行后置处理器的postProcessAfterInitialization方法。AOP的原理和实现就在其中(下一篇文章再单独介绍)。
    // org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

初始化步骤大体上可以分为四步:

1. 对实现Aware接口对bean的设置。
2. 依次回调bean后置处理器的postProcessBeforeInitialization方法。
3. 执行实现了InitializingBean或者用户自定义的init方法方法。
4. 依次回调bean后置处理器的postProcessAfterInitialization方法。

1. 实现Aware接口对bean的设置

进入initializeBean方法后,不管是走带有安全检查的if分支还是走不需要检查的else分支,第一步的核心方法都是执行invokeAwareMethods(beanName, bean)方法。实现interface Aware接口用于让bean能拥有某些额外的感知能力。比如实现了BeanNameAware接口,那么对其bean的属性beanName上set上对应的beanName,那么该bean就可以知道自己的beanName是什么。 如果实现了BeanFactoryAware接口,那么对其beanFactory属性设置上创建该bean使用的bean工厂,那么该bean就可以感知到创建自己的bean工厂是哪一个。具体代码如下:

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

2. 依次回调bean后置处理器的postProcessBeforeInitialization方法

如果这个bd不是属于内部类的bd,就调用后置处理器的postProcessBeforeInitialization对bean进行操作。

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

在不引入AOP的情况下,重要的postProcessBeforeInitialization有以下3个:

2.1 ApplicationContextAwareProcessor

ApplicationContextAwareProcessor依靠它内部invokeAwareInterfaces方法实现了以下Aware接口bean的初始化工作。

private void invokeAwareInterfaces(Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof EnvironmentAware) {
            ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
        }
        if (bean instanceof EmbeddedValueResolverAware) {
            ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
        }
        if (bean instanceof ResourceLoaderAware) {
            ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
        }
        if (bean instanceof ApplicationEventPublisherAware) {
            ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
        }
        if (bean instanceof MessageSourceAware) {
            ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
        }
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
        }
    }
}

2.2 ImportAwareBeanPostProcessor

 如果实现了ImportAware接口,在postProcessBeforeInitialization中首先解析出importingClass,使得bean能感知到importingClass。

2.3 CommonAnnotationBeanPostProcessor

CommonAnnotationBeanPostProcessor会实际调用InitDestroyAnnotationBeanPostProcessor的postProcessBeforeInitialization方法执行。

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // 获得声明周期的元数据对象,里面存放有bean中@PostConstruct 和 @PreDestroy注解的方法
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());    
    // 执行@PostConstruct对应的方法集,比如Human.class中对应的是 void com.Hodey.learn.bean.Human.init()这个1个方法
    metadata.invokeInitMethods(bean, beanName);    
    return bean;
}

首先通过findLifecycleMetadata(bean.getClass());寻找到本类中属于声明周期回调的注解元数据对象。也就是寻找本类中是否有@PostConstruct 和 @PreDestroy注解的方法。然后对其中的@PostConstruct注解方法进行回调操作。

public void invokeInitMethods(Object target, String beanName) throws Throwable {    
    Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
    Collection<LifecycleElement> initMethodsToIterate =
            (checkedInitMethods != null ? checkedInitMethods : this.initMethods);
    // 只要存在@PostConstruct注解方法,就执行回调
    if (!initMethodsToIterate.isEmpty()) {
        for (LifecycleElement element : initMethodsToIterate) {
            element.invoke(target);
        }
    }
}

它先获取@PostConstruct对应的方法集checkedInitMethods,然后再for循环中依次通过element.invoke(target),在内部通过反射执行。对于本项目以Adam.class举例,会调用private void init(){ name = "Adam"; }中的name = "Adam";方法对name赋值。

在执行完成所有bean后置处理器postProcessBeforeInitialization方法回调后,就会执行下一个大步骤。

3. 用户自定义的init方法方法

如果bean实现了InitializingBean或者用户自定义的init方法方法,那么调用这些初始化方法对bean的属性进行一些个性化设置。

4. 依次回调bean后置处理器的postProcessAfterInitialization方法

最后,再回调所有bean后置处理器的postProcessAfterInitialization方法。Spring AOP的代理实现场所就在这里,由于本篇文章主要介绍IOC中bean的初始化流程,AOP的知识下个专题再介绍。执行完成postProcessAfterInitialization后,会返回最终经过这些后置处理器加工后的bean返回到doCreateBean方法中。接下来还要执行另外一种声明周期方法的注册。

5. @PreDestory方法的注册

registerDisposableBeanIfNecessary是doCreateBean返回前的最后一步。这一步是完成针对@PreDestory方法的注册。我们分析bd是单例的情况下的注册方式,原型方法大同小异。接下来方法会进入mbd.isSingleton()分支,首先创建一个adapter,然后再注册。

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
    if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
        if (mbd.isSingleton()) {
            // 单例bean 的销毁回调注册。 实现了DestructionAwareBeanPostProcessors,DisposableBean或者用户自定义销毁方法的都在这里注册。
            registerDisposableBean(beanName,
                    new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
        }
        else {
            // 非单例bean的销毁回调注册
            Scope scope = this.scopes.get(mbd.getScope());
            scope.registerDestructionCallback(beanName,
                    new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
        }
    }
}
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
        List<BeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {

    this.bean = bean;
    this.beanName = beanName;
    this.invokeDisposableBean =
            (this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
    this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
    this.acc = acc;
    // 这里会进行一些destroy方法的推断,推断的依据是看看方法名字是不是“close”,“shutdown”。
    String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
    if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
            !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
        this.destroyMethodName = destroyMethodName;
        this.destroyMethod = determineDestroyMethod(destroyMethodName);
        if (this.destroyMethod == null) {
            if (beanDefinition.isEnforceDestroyMethod()) {
                throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
                        destroyMethodName + "' on bean with name '" + beanName + "'");
            }
        }
        else {
            Class<?>[] paramTypes = this.destroyMethod.getParameterTypes();
            if (paramTypes.length > 1) {
                throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
                        beanName + "' has more than one parameter - not supported as destroy method");
            }
            else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
                throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
                        beanName + "' has a non-boolean parameter - not supported as destroy method");
            }
        }
    }
    // 不管怎么样都会执行本行
    this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
}

该方法看起来很复杂其实不然,inferDestroyMethodIfNecessary(bean, beanDefinition)方法仅仅是象征性的根据方法名推断destroy方法,推断的依据是看看方法名是否是“close”或“shutdown”。不管怎样都会调用filterPostProcessors方法。

private List<DestructionAwareBeanPostProcessor> filterPostProcessors(List<BeanPostProcessor> processors, Object bean) {
    List<DestructionAwareBeanPostProcessor> filteredPostProcessors = null;
    if (!CollectionUtils.isEmpty(processors)) {
        filteredPostProcessors = new ArrayList<>(processors.size());
        for (BeanPostProcessor processor : processors) {
            if (processor instanceof DestructionAwareBeanPostProcessor) {
                DestructionAwareBeanPostProcessor dabpp = (DestructionAwareBeanPostProcessor) processor;
                if (dabpp.requiresDestruction(bean)) {
                    filteredPostProcessors.add(dabpp);
                }
            }
        }
    }
    return filteredPostProcessors;
}

在本方法中,它还是会遍历所有的bean后置处理器, 找出实现了DestructionAwareBeanPostProcessor接口的处理器调用其dabpp.requiresDestruction(bean)方法判断是否需要加入之后需要返回的结果集filteredPostProcessors中。显然执行该任务的后置处理器就是2.3方法中的InitDestroyAnnotationBeanPostProcessor,不同的是这次调用的是requiresDestruction方法进行处理,它实际也是检查this.checkedDestroyMethods中的对象是否有值。该对象放置的解析结果就是@PreDestroy的注解方法。假如有@PreDestroy方法,那么就会添加到中返回,在registerDisposableBean中this.disposableBeans.put(beanName, bean);放入到disposableBeans这个map中完成注册。它的回调是在bean工厂的destroySingletons()或destroySingleton()被调用时进行回调方法的执行。

执行完以上步骤后,initializeBean就算执行完成了。接下来的事情,在《【七】Spring IoC 最全源码详解之bean的依赖注入》中已经讲的很明白了,再次就不再赘述了。当所有的bean都初始化完成,标志着refresh()方法中finishBeanFactoryInitialization(beanFactory)这个大步骤的完成。接下来执行完成finishRefresh()后,容器的启动流程就告一段落了。finishRefresh方法非常简单,就留给读者自行分析吧。


初始化完成,标志着容器的启动过程基本技术。时间也就从上一节的06:00来到07:00。太阳已经比你先起床了!

下一篇文章,我们将一起来探究Spring AOP的内幕,敬请期待~

 

 

猜你喜欢

转载自blog.csdn.net/wuyuwei/article/details/88252969