前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot源码解析(十二)- Autowired是如何注入的

SpringBoot源码解析(十二)- Autowired是如何注入的

作者头像
写一点笔记
发布2020-10-10 11:01:32
8020
发布2020-10-10 11:01:32
举报
文章被收录于专栏:程序员备忘录程序员备忘录

在上一期中我们大概得学习了SpringBoot获取Bean的逻辑。其实对于开发来说,明白这些感觉已经足够了。但是在上期我们没有指出类似@Autowired等注解是如何注入到bean中的。按照逻辑的话应该在initalizetionBean的前后。因为在对getBean方法分析的时候,我们发现applyMergedBeanDefinitionPostProcessors方法里边有很多处理器,通过查看发现有很多眼熟的方法大概就是处理哪些类内注解的。但是我好奇的是我们的Bean都没有初始化,调用这些个方法又有何用。怀着疑问咋继续探索。

如图所示的三个方法就是我们今天探索的目标。在applyMergedBeanDefinitionPostProcessors中,我们主要学习一下autowiredAnnotationBeanProcessors。

 private InjectionMetadata findAutowiringMetadata(String beanName, Class clazz, @Nullable PropertyValues pvs) {
        String cacheKey = StringUtils.hasLength(beanName) ? beanName : clazz.getName();
        InjectionMetadata metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
        if (InjectionMetadata.needsRefresh(metadata, clazz)) {
            synchronized(this.injectionMetadataCache) {
                metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
                if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                    if (metadata != null) {
                        metadata.clear(pvs);
                    }
//找到具有@Autowired注解的属性
                    metadata = this.buildAutowiringMetadata(clazz);
                    this.injectionMetadataCache.put(cacheKey, metadata);
                }
            }
        }
        return metadata;
}
其中的buildAutowiringMetadata就是将所有的@Autowired修饰的属性信息返回。
    private InjectionMetadata buildAutowiringMetadata(Class clazz) {
        List elements = new ArrayList();
        Class targetClass = clazz;
        do {
            List currElements = new ArrayList();
            ReflectionUtils.doWithLocalFields(targetClass, (field) -> {
//拿到类上的每个属性的所有注解信息,遍历
                AnnotationAttributes ann = this.findAutowiredAnnotation(field);
                if (ann != null) {
//@Autowired不能使用在static修饰的字段上
                    if (Modifier.isStatic(field.getModifiers())) {
                        if (this.logger.isInfoEnabled()) {
                            this.logger.info("Autowired annotation is not supported on static fields: " + field);
                        }
                        return;
                    }
//是否为requeired的
                    boolean required = this.determineRequiredStatus(ann);
                    currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement(field, required));
                }
            });
            ReflectionUtils.doWithLocalMethods(targetClass, (method) -> {
                Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
                if (BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                    AnnotationAttributes ann = this.findAutowiredAnnotation(bridgedMethod);
                    if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                        if (Modifier.isStatic(method.getModifiers())) {
                            if (this.logger.isInfoEnabled()) {
                                this.logger.info("Autowired annotation is not supported on static methods: " + method);
                            }
                            return;
                        }
                        if (method.getParameterCount() == 0 && this.logger.isInfoEnabled()) {
                            this.logger.info("Autowired annotation should only be used on methods with parameters: " + method);
                        }
                        boolean required = this.determineRequiredStatus(ann);
                        PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                        currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement(method, required, pd));
                    }
                }
            });
            elements.addAll(0, currElements);
            targetClass = targetClass.getSuperclass();
        } while(targetClass != null && targetClass != Object.class);
        return new InjectionMetadata(clazz, elements);
    }

在bean的信息填充的时候

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    if (bw == null) {
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
    } else {
        boolean continueWithPropertyPopulation = true;
        if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {//获取注入解析的后置处理器
            Iterator var5 = this.getBeanPostProcessors().iterator();
            while(var5.hasNext()) {
                BeanPostProcessor bp = (BeanPostProcessor)var5.next();
                if (bp instanceof InstantiationAwareBeanPostProcessor) {//InstantiationAwareBeanPostProcessor接口
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }
        if (continueWithPropertyPopulation) {
            PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;
            if (mbd.getResolvedAutowireMode() == 1 || mbd.getResolvedAutowireMode() == 2) {
                MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
                if (mbd.getResolvedAutowireMode() == 1) {//通过名称注入的属性进行标记
                    this.autowireByName(beanName, mbd, bw, newPvs);
                }
                if (mbd.getResolvedAutowireMode() == 2) {//类型注入的标记
                    this.autowireByType(beanName, mbd, bw, newPvs);
                }
                pvs = newPvs;
            }
            boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
            boolean needsDepCheck = mbd.getDependencyCheck() != 0;
            PropertyDescriptor[] filteredPds = null;
            if (hasInstAwareBpps) {
                if (pvs == null) {
                    pvs = mbd.getPropertyValues();
                }
                Iterator var9 = this.getBeanPostProcessors().iterator();
                while(var9.hasNext()) {
                    BeanPostProcessor bp = (BeanPostProcessor)var9.next();
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                        PropertyValues pvsToUse = ibp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
                        if (pvsToUse == null) {
                            if (filteredPds == null) {
                                filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                            }//这里进行属性注入
                            pvsToUse = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                            if (pvsToUse == null) {
                                return;
                            }
                        }
                        pvs = pvsToUse;
                    }
                }
            }
            if (needsDepCheck) {
                if (filteredPds == null) {
                    filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
            }
            if (pvs != null) {
                this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
            }
        }
    }
}

在调用postProcessPropertyValues方法之后进行属性注入。看到这里就是循环遍历找到属性之后就进行注入的。那么我们看看element.inject做了哪些事情。

protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) throws Throwable {
    if (this.isField) {
        Field field = (Field)this.member;//设置属性可以直接访问,跳过private的作用
        ReflectionUtils.makeAccessible(field);//依赖设置
        field.set(target, this.getResourceToInject(target, requestingBeanName));
    } else {
        if (this.checkPropertySkipping(pvs)) {
            return;
        }
        try {
            Method method = (Method)this.member;//设置方法可以直接访问,跳过private的作用
            ReflectionUtils.makeAccessible(method);//直接赋值
            method.invoke(target, this.getResourceToInject(target, requestingBeanName));
        } catch (InvocationTargetException var5) {
            throw var5.getTargetException();
        }
    }
}

代码分析到这里,我们大概明白了注入的原理,spring直接取修改@Autowired修饰符,然后直接访问。然后将值进行设置,使得其和public修饰没有界限。设置完毕这些属性之后,就开始调用我们的初始化方法InitlizationBean方法了。

上图是比较清晰的调用过程。这里就不赘述了。

总结:@Autowired不能被static进行修饰,其次注入的原理是Spring直接修改了属性的修饰符号然后直接设置值,让其与public属性一样。所以可以不用写set、get方法。在初始化的过程中,我们要记得初始化类的过程调用是:aware接口、bean的前置处理、bean的初始化方法、bean的后置处理。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员备忘录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云代码分析
腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档