Spring第四周

Spring解密 - Bean的加载流程

入口

public class Application {

    public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");

        Person person = context.getBean("person", Person.class);

        System.out.println(person.toString());
    }
}

BeanFactory 的由来

1.查看getBean()的源码.

public class AbstractApplicationContext{

    @Override
    public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
        assertBeanFactoryActive();
        // getBeanFactory() 是怎么来的?我们接着看
        return getBeanFactory().getBean(name, requiredType);
    }
}

2.应用程序的上下文

在 new ClassPathXmlApplicationContext("bean.xml"); 中,跳转到重载的构造方法中,发现如下代码

public class ClassPathXmlApplicationContext {

    public ClassPathXmlApplicationContext(
            String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
            throws BeansException {

        super(parent);
        // 解析 bean.xml 文件
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }
}

它的目的是将普通路径解析为 类(classpath) 路径资源名称。多个配置文件的情况下,后加载的 Bean 会覆盖先前定义好的 Bean,这样做的目的是为了通过额外的XML文件来特意重写某个 Bean。这里我们可以看到调用了一个 refresh(),它的作用是什么呢?
3.初始化

刷新容器

public class AbstractApplicationContext {

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 准备刷新上下文
            prepareRefresh();
            // 通知子类,刷新内部 BeanFactory(创建 BeanFactory 的入口)
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        }
    }

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        // 跟踪该方法
        refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }
}

初次加载完 bean.xml 后,肯定会进入到 refresh() 方法中,这个时候会做容器初始化的工作,也就是 标签解析、Bean加载 等等工作.

创建 DefaultListableBeanFactory

public class AbstractRefreshableApplicationContext {

    @Override
    protected final void refreshBeanFactory() throws BeansException {
        // 判断是否存在
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            // 创建 DefaultListableBeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                // 然后赋值给 beanFactory 变量
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

    // 提取 BeanFactory
    @Override
    public final ConfigurableListableBeanFactory getBeanFactory() {
        synchronized (this.beanFactoryMonitor) {
            if (this.beanFactory == null) {
                throw new IllegalStateException("BeanFactory not initialized or already closed - " +
                        "call 'refresh' before accessing beans via the ApplicationContext");
            }
            return this.beanFactory;
        }
    }
}

从上面的代码块中,我们可以看到 如果已经存在 beanFactory,将销毁旧的实例,然后在创建新的 DefaultListableBeanFactory,最后 getBeanFactory() 就可以正常使用了。

Bean 加载
整个 Bean 的装载过程中,重点围绕 AbstractBeanFactory

public abstract class AbstractBeanFactory {

    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
        // 别名转换
        final String beanName = transformedBeanName(name);
        Object bean;

        // 检查缓存中是否存在 该 Bean 的单例(Bean默认的Scope = singleton)
        // 比如容器初始化的时候或者其他地方调用过getBean,已经完成了初始化
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
        //执行一次logger.isDebugEnabled()这样的判断花费的时间大概是写日志时间的万分之一
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                } else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            // 返回实例,FactoryBean 的情况下,并不是直接返回实例本身而是返回指定方法返回的实例
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // 存在循环依赖则报错
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // 判断工厂中是否含有当前 Bean 的定义
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // 如果没有,查询父工厂
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // 执行带有 args 参数的 getBean 方法
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // 如果没有参数,执行标准的 getBean 方法 
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            if (!typeCheckOnly) { // 如果不是做类型检查,则需要标记此 Bean 正在创建之中
                markBeanAsCreated(beanName);
            }

            try {
                // 将存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,如果BeanName是子Bean的话会合并父类的相关属性
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // 获取依赖的 Bean
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        registerDependentBean(dep, beanName);
                        getBean(dep);
                    }
                }

                // 终于开始创建 Bean 实例了,如果是单例的,那么会创建一个单例的匿名工厂,
                // 如果是原型模式的,则不需要创建单例的工厂的,其他的如 request、session 作用域的,则根据自身的需要
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);// 调用默认构造函数,有兴趣自己跟进下代码
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                else {
                    String scopeName = mbd.getScope();
                    final 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, () -> {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        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",
                                ex);
                    }
                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        // 类型检查,如果不能进行类型转换,则抛出异常
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            catch (TypeMismatchException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }
}

一步一步的分析

转换 BeanName

final String beanName = transformedBeanName(name);

protected String transformedBeanName(String name) {
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

去除 FactoryBean 的修饰符,最终取指定 alias 所表示的 beanName。因为有可能获取到以 & 开头的 FactoryBean,所以要进行转化

加载单例

检查缓存中是否存在 该 Bean 的单例(Bean默认的Scope = singleton),如容器初始化的时候或者其他地方已经调用过 getBean() 完成了初始化

Object sharedInstance = getSingleton(beanName);

默认在装载 Bean 的时候会先去检查 singletonObjects 是否存在,如果存在直接提取缓存的。

public class DefaultSingletonBeanRegistry {

    /** 保存 BeanName 和创建 bean 实例之间的关系 bean name --> bean instance */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    /** 保存 BeanName 和创建 bean 实例的工厂之间的关系 bean name --> ObjectFactory */
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

    /** 保存 BeanName 和创建 bean 实例之间的关系 bean name --> bean instance */
    /** 与 singletonObjects 不同的是当一个单例 bean 被放到里面后,那么在 bean 在创建过程中,就可以通过 getBean 方法获取到,可以用来检测循环引用。 **/
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

    /** 保存当前所有已注册的 bean */
    private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 尝试从缓存获取实例
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                // 若该 bean 正在加载则不处理
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        // 存入到缓存中
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }
}

构建实例(无缓存情况)

缓存中没有,那就当场构建一个 bean 出来,可以看到 getSingleton(String beanName, ObjectFactory<?> singletonFactory) 有两个参数

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    synchronized (this.singletonObjects) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            // 记录加载状态,,以便对循环依赖进行检测
            beforeSingletonCreation(beanName);
            singletonObject = singletonFactory.getObject();
            // 移除加载状态
            afterSingletonCreation(beanName);
            addSingleton(beanName, singletonObject);
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
}

构建 ObjectFactory
此处与其说是构建 ObjectFactory ,不如说是在创建一个单例 Bean

if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, () -> {
        try {
            // 对 JDK8 lambda 表达式熟悉的小伙伴就不会陌生了
            return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {
            destroySingleton(beanName);
            throw ex;
        }
    });
    // 划重点了
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

创建 Bean

public class AbstractAutowireCapableBeanFactory {

    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        if (logger.isDebugEnabled()) {
            logger.debug("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;

        // 首先判断需要创建的bean是否可以被实例化,这个类是否可以通过类装载器来载入。
        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 配置了 PostProcessor,那么这里返回的是一个代理)
            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 {
            // 重点来了
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isDebugEnabled()) {
                logger.debug("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException ex) {
            // A previously detected exception with proper bean creation context already...
            throw ex;
        }
        catch (ImplicitlyAppearedSingletonException ex) {
            // An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }
}

在创建 Bean 之前,Spring 还做了不少工作。

  • 判断创建的 bean 是否可以被实例化,这个类是否可以通过 ClassLoader 来载入,根据设置的 class 属性或根据 className 来解析 class。
  • 对覆盖进行标记并验证,在 Spring 配置中存在 lookup-mothod 和 replace-method 的,这两个配置的加载时将配置统一存放在 BeanDefinition 中的 methodOverrides 属性里,这个方法的操作也是针对于这两个配置的;
  • 应用初始化前的后处理器,最后创建 bean。在 createBean() 方法里执行完 resolveBeforeInstantiation 方法后,如果创建了代理且不为空的话就直接返回,否则需要进行常规 bean 的创建,这个创建过程是在 doCreateBean 中完成的

初始化 Bean
上面 createBean 交给了 doCreateBean 来创建 bean (上面还有一个重要的方法getObjectForBeanInstance,在后面分析)

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {

    // 实例化 Bean
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // 根据指定 bean 使用相应策略创建实例(正确情况会调用无参构造函数)
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // 获取实例化好的 Bean(Person person = new Person()),此处还未进行赋值
    final Object bean = instanceWrapper.getWrappedInstance();
    // 获得实例化好的 class
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // 记录创建 Bean 的 ObjectFactory,初始化前调用 post-processors,可以让我们在 bean 实例化之前做一些定制操作
    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;
        }
    }

    // 检测循环依赖,是否需要提早初始化(只能解决单例Bean)
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isDebugEnabled()) {
            logger.debug("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // 初始化bean实例。
    Object exposedObject = bean;
    try {
        // 在这个方法里面初始化对象,配置 xml 中的各种属性
        populateBean(beanName, mbd, instanceWrapper);
        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) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            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);
                    }
                }
                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 {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }
    return exposedObject;
}

上面源码完成的操作可以概括为以下几点

  • RootBeanDefinition 是不是单例,如果是单例先移除缓存
  • 实例化 bean,将 RootBeanDefinition 转换为 BeanWrapper
  • 使用 MergedBeanDefinitionPostProcessor,Autowired注解 就是通过此方法实现类型的预解析;
  • 解决循环依赖问题
  • 在 populateBean() 中填充属性,配置在 XML 中的各种属性
  • 注册到 DisposableBean 中
  • 完成创建并返回 Bean 的实例
    接下来看下 Spring 是如何创建 bean 实例的。跟踪 createBeanInstance() 方法

创建Bean实例

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 获取 beanClass , 要先确保 Bean 是正确的,已经解析到当前节点了
    Class<?> beanClass = resolveBeanClass(mbd, beanName);

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

    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }

    // 若工厂方法不为空则使用工厂方法初始化
    if (mbd.getFactoryMethodName() != null)  {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    // Shortcut when re-creating the same bean...
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    // 如果已经解析过则使用解析好的构造方法不需要再次锁定
    if (resolved) {
        if (autowireNecessary) {
            // 构造方法自动注入
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            // 使用默认构造方法
            return instantiateBean(beanName, mbd);
        }
    }

    // 根据参数解析构造方法
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // 没有特殊处理的情况下,只需使用无参数的构造函数。
    return instantiateBean(beanName, mbd);
}

可以看出如果在 RootBeanDefinition 中存在 factoryMethodName属性,或者说配置文件中配置了 factory-method,那么 Spring 会尝试使用 instantiateUsingFactoryMethod(beanName, mbd, args) 方法根据 RootBeanDefinition 中的配置生成bean实例。然后再解析构造方法并进行实例化,Spring 会根据参数及类型判断使用哪个构造方法进行实例化。判断调用哪个构造方法的过程会采用缓存机制,如果已经解析过则不需要重复解析而是从 RootBeanDefinition 中的属性 resolvedConstructorOrFactoryMethod 缓存的值去取,否则需再次解析。

populateBean 属性注入

这块代码比较多,就不贴出来了

在 populateBean 方法的中的主要处理流程:

  • InstantiationAwareBeanPostProcessor 处理器的 postProcessAfterInstantiation 方法控制程序是否继续填充属性;
  • 根据注入类型提取依赖的 bean,并存入 PropertyValues 中;
  • InstantiationAwareBeanPostProcessor 处理器的 postProcessPropertyValues 方法对属性在填充前再次处理(主要还是验证属性);
  • 将所有 PropertyValues 中的属性填充到 BeanWrapper 中;

initializeBean 初始化Bean
Spring 的 bean 配置时有一个 init-method 属性,这个属性的作用是在 bean 实例化前调用 init-method 指定的方法进行需要的操作,现在就进入这个方法了;Spring 执行过 bean 的实例化,并且进行属性填充后,就会调用用户设定的初始化方法。

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 {
        // 特殊bean处理
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // 调用配置的 init-method
        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()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

最后加载完 Bean 并执行完初始化操作后,一个 bean 的加载基本就结束了。

增强的 Bean
通过上面的描述,我们已经知道了一个的 Bean 是如何初始化的,已经具备普通 Bean 的功能。但是 Spring 还提供了一种增强的 Bean(FactoryBean),具备 factory 能力的 Bean,这个能力主要在 getObjectForBeanInstance 得到。

public class AbstractBeanFactory {

    protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    
        // 如果想要获取 FactoryBean 本身,那么 beanInstance 必须是 FactoryBean 的实例
        if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
        }
    
        // 如果 instance 不是 FactoryBean 实例,或者想要获取的就是 FactoryBean 实例,那么直接返回就好
        if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
            return beanInstance;
        }
    
        Object object = null;
        if (mbd == null) {
            // 获取缓存的实例
            object = getCachedObjectForFactoryBean(beanName);
        }
        if (object == null) {
            // 缓存中没有对象,那么从头准备 bean defition 实例化一个
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
            // Caches object obtained from FactoryBean if it is a singleton.
            if (mbd == null && containsBeanDefinition(beanName)) {
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            // 在这里面获得最终的FactoryBean
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,123评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,031评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,723评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,357评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,412评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,760评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,904评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,672评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,118评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,456评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,599评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,264评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,857评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,731评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,956评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,286评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,465评论 2 348

推荐阅读更多精彩内容