Spring源码解析(十一)-初始化bean

Spring版本

5.2.5.RELEASE

参考

《芋道源码》

源码解读

1. AbstractAutowireCapableBeanFactory#initializeBean

    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            // 通过aware接口进行一些set设置
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // 初始化之前应用PostProcessors
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            // 应用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()) {
            // 初始化之后应用beanProcessors
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }
 
 

主流程主要包含四个步骤:

  • invokeAwareMethods进行一些属性的设置
  • applyBeanPostProcessorsBeforeInitialization应用BeanPostProcessorsapplyBeanPostProcessorsBeforeInitialization方法
  • invokeInitMethods应用初始化方法
  • applyBeanPostProcessorsAfterInitialization应用BeanPostProcessorsapplyBeanPostProcessorsAfterInitialization

2. AbstractAutowireCapableBeanFactory#invokeAwareMethods

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

Aware接口是spring提供的一种回调机制,这里简单地设置了beanNamebeanClassLoaderbeanFactory的属性,关于Aware接口可戳// TODO

3. AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization

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

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            // 应用每个PostProcessors
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

获取到BeanPostProcessor集合,遍历,应用每个BeanPostProcessorpostProcessBeforeInitialization方法,如果返回值为空,则返回上一次处理后的bean

4. AbstractAutowireCapableBeanFactory#invokeInitMethods

    protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
            throws Throwable {

        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) () -> {
                        ((InitializingBean) bean).afterPropertiesSet();
                        return null;
                    }, getAccessControlContext());
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                // afterPropertiesSet提供了一个机会在properties设置之后去改变properties
                ((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)) {
                // 通过反射调用自定义初始化方法
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }
 
 

做了俩件事:

  • 首先判断bean是否是InitializingBean类型,如果是,应用afterPropertiesSet方法,从方法名可以看出,该方法提供了一个在设置完毕property之后再去修改property的机会
  • 应用自定义的init-method方法

4.1 InitializingBean

public interface InitializingBean {

    /**
     * Invoked by the containing {@code BeanFactory} after it has set all bean properties
     * and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.
     * 

This method allows the bean instance to perform validation of its overall * configuration and final initialization when all bean properties have been set. * @throws Exception in the event of misconfiguration (such as failure to set an * essential property) or if initialization fails for any other reason */ void afterPropertiesSet() throws Exception; }

InitializingBean接口仅包含afterPropertiesSet一个方法,下面通过一个小demo来展示其效果

4.1.1 demo

4.1.1.1 Teacher.java
public class Teacher implements InitializingBean {

    private String name;


    @Override
    public void afterPropertiesSet() throws Exception {
        name = "name set by afterPropertiesSet";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
4.1.1.2 spring.xml
    
        
    
4.1.1.3 测试
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

        Teacher teacher = (Teacher) context.getBean("teacher");
        System.out.println(teacher.getName());

    }
}
4.1.1.4 结果
afterPropertiesSet

4.1.2 结论

可以看到,在spring.xml中,name属性设置的name set by property label已经被afterPropertiesSet方法中的name set by afterPropertiesSet所覆盖

4.2 init-method

对4.1中的demo稍加修改

4.2.1 demo

4.2.1.1 Teacher.java
public class Teacher implements InitializingBean {

    private String name;


    @Override
    public void afterPropertiesSet() throws Exception {
        name = "name set by afterPropertiesSet";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void initMethod() {
        this.name = "name set by init method";
    }
}
4.2.1.2 spring.xml
    
        
    
4.2.1.3 结果
init-method

4.2.2 源码解析

        if (mbd != null && bean.getClass() != NullBean.class) {
            String initMethodName = mbd.getInitMethodName();
            if (StringUtils.hasLength(initMethodName) &&
                    // 如果init-method设置为afterPropertiesSet,那么前面已经运行过了,没必要再跑一遍
                    !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                    !mbd.isExternallyManagedInitMethod(initMethodName)) {
                // 通过反射调用自定义初始化方法
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }

这里做了一个优化,如果init-method设置为afterPropertiesSet方法,那么其实4.1中已经应用了init-method,就无需再次运行了,而invokeCustomInitMethod方法的核心在于使用反射来应用init-method方法:

ReflectionUtils.makeAccessible(methodToInvoke);
methodToInvoke.invoke(bean);

5. AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

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

逻辑与第三点大同小异

总结

初始化bean整体逻辑相对于其他流程来说,可以说是简单了很多,通过俩个小demo,也更清晰地理解了源码的执行流程,没有什么比实例来得更有说服力了。

你可能感兴趣的:(Spring源码解析(十一)-初始化bean)