spring容器加载分析 四Bean实例化

spring中按照Bean的scop可以被定义为两种模式:prototype(多例)和singleton(单例),按照Bean的实例化方式可以被定义为预加载和懒加载(@Lazy)。

prototype(多例)和懒加载(@Lazy)的Bean被延迟到使用时才进行实例化,而非延迟加载的单例Bean则在容器刷新(refresh)时通过finishBeanFactoryInitialization方法进行实例化,只是实例化的时机和处理循环依赖的方式不同,这里只分析非延迟单例Bean的实例化过程。

Bean实例化的方法是在AbstractApplicationContext类中通过doGetBean方法进行的:

protected  T doGetBean(
        final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
        throws BeansException {
    
    // 提取对应的beanName,如果是工厂Bean则加前缀&
    final String beanName = transformedBeanName(name);
    Object bean;
    // 尝试从缓存或者singletonFactories中的ObjectFactory中获取  
    Object sharedInstance = getSingleton(beanName);// step 1
    if (sharedInstance != null && args == null) {
        // 返回对应的实例
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);//step 2
    }else {
        // 只有在单例的情况才会尝试解决循环依赖
        if (isPrototypeCurrentlyInCreation(beanName)) { // step 3
            throw new BeanCurrentlyInCreationException(beanName);
        }
        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        // 如果beanDefinitionMap中,也就是所有已加载的类中不包含beanName则尝试从parentBeanFactory中检查
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            String nameToLookup = originalBeanName(name);
            if (args != null) {
                // 递归查找
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
        }
        // 不仅仅是做类型检查,而是创建BEAN则记录
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        try {// 将各种类型的BeanDefinition转换成RootBeanDefinition
            //  如果指定的BEAN为子BEAN的话,则合并父BEAN的属性
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            String[] dependsOn = mbd.getDependsOn();
            // 如果存在强制依赖,则递归实例化依赖的bean
            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);
                    // 实例化依赖的Bean
                    getBean(dep);
                }
            }

            // 实例化依赖的bean后则进行实例化
            // 单例模式创建
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, new ObjectFactory() {
                    @Override
                    public Object getObject() throws BeansException {
                        try {
                            // bean实例化核心方法  step 5
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                
            }
            // 省略非单例 实例创建代码  ... .... ....
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }
    return (T) bean;
}
 
 

step1、尝试从缓存或者singletonFactories中的ObjectFactory工厂中获取,在创建单例bean的时候会存在依赖注入的情况,spring创建bean的原则是不等bean创建完成 就会将创建bean的ObjectFactory提早曝光,也就是将ObjectFactory加入缓存中,一旦下一个bean依赖上个bean则直接使用ObjectFactory。

step 2 获取对应的实例
存在BeanFactory的情况并不是直接返回对象本身而是返回工厂方法返回的实例

protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
    // 如果BeanName为&前缀,但却不是FactoryBean的实例,抛出异常
    if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
        throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
    }
    // 如果是一般的BEAN,或者是工厂bean,但是name的前缀为&
    // 直接返回该实例
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }
    // 加载FactoryBean
    Object object = null;
    if (mbd == null) {
        object = getCachedObjectForFactoryBean(beanName);
    }
    if (object == null) {
        // 已经明确了beanInstance为FactoryBean,可以强制转换
        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());
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

step3 非单例Bean循环依赖检查
如果是Prototype类型的Bean,两次进入创建则抛出异常,如Bean A中有Bean B的引用,Bean B中有Bean A的引用,注入时候就会产生当A还未创建完成的时候对应B的创建需要再次返回创建A,从而第二次进入同一个Bean的getBean方法,一定会在此抛出异常,不能完成注入,也就是说prototype类型的Bean不能实现循环依赖,只有在单例的Bean才会尝试解决循环依赖。

step4 单例Bean实例创建
实际调用的方法在AbstractAutowireCapableBeanFactory类中,这里还不是真正的创建实例,可以看出是创建前的准备工作,比如类的解析、BeanPostProcessors处理器的调用等,需要注意的是这里还有一个AOP的切入点。

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    RootBeanDefinition mbdToUse = mbd;
    // 锁定并解析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 {
        // 调用Bean的前置处理器:BeanPostProcessors
        // step 4.1
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        // 如果前置处理返回了Bean,Bean不为空就直接返回
        if (bean != null) {
            System.out.println(beanName+":");
            return bean;
        }
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }
    // step 4.2
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    return beanInstance;
}

step 4.1 调用InstantiationAwareBeanPostProcessors
InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口,在实例化Bean之前调用postProcessBeforeInstantiation方法,实例化Bean之后调用applyBeanPostProcessorsAfterInitialization方法。调用过程:

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    // 尚未被解析
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // Make sure bean class is actually resolved at this point.
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            Class targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                // 前置处理调用
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    // 后置处理调用
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}
protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
            if (result != null) {
                return result;
            }
        }
    }
    return null;
}

先调用前置方法,如果返回的不为空则调用后置方法,注意,此时Bean还没有进如真正的doCreate方法,如果此时返回了一个Bean,那肯定是一个代理,所有此处可以作为AOP的切入点,有机会返回代理对象。

step 4.2 doCreateBean
方法在AbstractAutowireCapableBeanFactory类中实现,这里才是真正创建Bean实例、进行各种属性和依赖注入的地方。

有四个主要的步骤:

1、调用createBeanInstance()方法创建Bean实例,使用构造方法和工厂方法来实例化,首先要根据参数来锁定具体的构造方法或工厂方法,然后处理参数的引入,最后实例化。
2、应用MergedBeanDefinitionPostProcessors,MergedBeanDefinitionPostProcessor也是BeanPostProcessor的子接口,扩展了postProcessMergedBeanDefinition方法,这个方法是用来处理合并Bean定义的。
3、解决单例的循环依赖,根据”正在创建的Bean池“singletonsCurrentlyInCreation中是否包含当前的Bean,如果包含则认为存在循环依赖,为了避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory放入工厂,因为此时Bean的属性尚未填充所以可以理解为未初始化完成。这个步骤可以理解为”提前曝光单例Bean“。
4、对Bean的各种依赖和属性进行填充,比如@Autowired、@Resource、@Value注解的属性都在此进行赋值。

属性的方法是populateBean在AbstractAutowireCapableBeanFactory类中实现:

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    PropertyValues pvs = mbd.getPropertyValues();
    // 省略部分代码 ... ...
    // BeanPostProcessor理器已经初始化
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    // 需要依赖检查
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
    if (hasInstAwareBpps || needsDepCheck) {
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    // 对所有需要依赖检查的属性进行处理 
                    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvs == null) {
                        return;
                    }
                }
            }
        }
        if (needsDepCheck) {
            // 依赖检查
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }
    }
    //将属性应用到BEAN中
    applyPropertyValues(beanName, mbd, bw, pvs);
}

代码中又一次对BeanPostProcessor进行了遍历执行,在容器构造分析中提到了在初始化容器的时候会向容器注入一些BeanPostProcessor的实现:
AutowiredAnnotationBeanPostProcessor
RequiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
其中AutowiredAnnotationBeanPostProcessor就是用来处理@Autowired、@Value注解的属性。
RequiredAnnotationBeanPostProcessor是用来处理@Required注解的属性。

CommonAnnotationBeanPostProcessor是用来处理@Resource注解的属性,@Resource注解来自JAVAEE5规范,这个规范中还有两个常用的注解@PostConstruct和@PreDestroy。

我们来看AutowiredAnnotationBeanPostProcessor是怎么进行属性填充的。

public PropertyValues postProcessPropertyValues(
        PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
    // 查找@Autowired和@Value注入的元数据缓存中有直接返回,没有则创建  step 4.2.1
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        // 注入step 4.2.2
        metadata.inject(bean, beanName, pvs);
    }
    // 省略部分 代码 ... ...
    return pvs;
}

step 4.2.1 查找自动注入元数据
使用ReflectionUtils反射工具从类中获取有@Autowired或@Value注解的字段封装成AutowiredFieldElement对象返回。
使用ReflectionUtils反射工具从类中获取有@Autowired或@Value注解的犯法封装成AutowiredMethodElement对象返回。
这两类都是InjectionMetadata.InjectedElement的子类。

step 4.2.2 注入

AutowiredFieldElement字段属性的自动注入:

protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
    Field field = (Field) this.member;// 属性字段
    Object value;
    if (this.cached) {// 如果有缓存直接从缓存中拿出
        value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    }
    else {
        // 封装依赖描述类
        DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
        desc.setContainingClass(bean.getClass());
        Set autowiredBeanNames = new LinkedHashSet(1);
        // 类型转换器具
        TypeConverter typeConverter = beanFactory.getTypeConverter();
        try {
            // 调用DefaultListableBeanFactory中的resolveDependency step 4.2.3
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
        }
        synchronized (this) {
            // 省略 引用快照缓存的代码 ... ....
        }
    }
    if (value != null) {
        ReflectionUtils.makeAccessible(field);// 使字段可访问
        field.set(bean, value);// 设置字段的值
    }
}
}

属性的依赖值是从DefaultListableBeanFactory类中解析出来的:

public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
        Set autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    try {
        // 省略部分代码...  ...
        // 依赖的属性类型
        Class type = descriptor.getDependencyType();
        // 获取@Value的建议值,类似:"${jsets.jdbc.dialect}"
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
        if (value != null) {
            if (value instanceof String) {
                String strVal = resolveEmbeddedValue((String) value);
                BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
                // 这里使用beanExpressionResolver进行表达式解析
                value = evaluateBeanDefinitionString(strVal, bd);  
            }
            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
            return (descriptor.getField() != null ?
                    converter.convertIfNecessary(value, type, descriptor.getField()) :
                    converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
        }
        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
            return multipleBeans;
        }
        // 查找自动注入的候选Beans
        Map matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        // 如果 匹配的beans为空,且@Autowired的required为true ,抛出异常
        if (matchingBeans.isEmpty()) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }
        String autowiredBeanName;
        Object instanceCandidate;
        if (matchingBeans.size() > 1) {// 多个候选者
            autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
            if (autowiredBeanName == null) {
                if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                    return descriptor.resolveNotUnique(type, matchingBeans);
                }
                else {
                    return null;
                }
            }
            instanceCandidate = matchingBeans.get(autowiredBeanName);
        }
        else {// 单个候选这
            Map.Entry entry = matchingBeans.entrySet().iterator().next();
            autowiredBeanName = entry.getKey();
            instanceCandidate = entry.getValue();
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.add(autowiredBeanName);
        }
        return (instanceCandidate instanceof Class ?
                descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
    }
    finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }
}

针对@Value注解的属性从AutowireCandidateResolver中获取建议的值,如"${jsets.jdbc.dialect}",然后使用beanExpressionResolver进行表达式解析器进行解析。
@Autowired注解的属性使用BeanFactoryUtils根据属性的类型从BeanFactory中获取对应的Bean实例,如果对应类型的Bean只有一个就直接返回这个Bean实例,如果有多个候选的Bean实例,使用有@Primary注解的哪个实例,如果没有@Primary注解则根据属性的名称进行匹配,匹配不到则抛出异常。

AutowiredMethodElement的注入逻辑于此类似,不做分析。

@Resource的处理逻辑和@Autowired 处理逻辑类似,只是@Resource依BeanName进行注入。

码字不易,转载请保留原文连接https://www.jianshu.com/p/ad4a5d35481b

你可能感兴趣的:(spring容器加载分析 四Bean实例化)