美文网首页程序员Java学习笔记Java 杂谈
spring容器加载分析 四Bean实例化

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

作者: wangjie2016 | 来源:发表于2018-01-19 14:48 被阅读375次

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

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

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

    protected <T> T doGetBean(
            final String name, final Class<T> 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<Object>() {
                        @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<String> autowiredBeanNames = new LinkedHashSet<String>(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<String> 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<String, Object> 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<String, Object> 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实例化

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