spring的自动装配,骚话@Autowired的底层工作原理

  • 时间:
  • 浏览:0
  • 来源:3分时时彩官网_哪里可以玩3分时时彩_3分时时彩在哪里玩

前言

  开心一刻

    十年前,我:我交女票了,比我大两岁。妈:不行!赶紧分!

    八年前,我:我交女票了,比我小两岁,外地的。妈:你就只有我想省点心?

    五年前,我:我交女票了,市长的女儿。妈:别人还能看上你?分了吧!

    今年,我挺着大肚子踏进家门。妈:闺女啊,你终于开窍了 !

前情回顾

  Spring拓展接口之BeanPostProcessor,我们我们我们 我们我们我们 我们我们我们 都来看看它的底层实现中讲到了spring对BeanPostProcessor的底层支持,而且 知道了BeanPostProcessor的另1个 多多最好的土办法:postProcessBeforeInitialization、postProcessAfterInitialization的执行时机,没看的小伙伴可不都要回过头去看看。没法 spring的自动装配是打算放上去上一篇博文中删剪讲解的,可也不 我着实篇幅将会过多了(细心的小伙伴将会会有没法 的表情:,除了几幅图,真没那先 内容!),既然我们我们我们 我们我们我们 我们我们我们 都都感觉出来了,没法 也就明人不说暗话了,难能可贵没放上去上篇讲解,着实是将会篇幅过多了(哈哈哈,是都不 很想打我? ); 好了,我们我们我们 我们我们我们 我们我们我们 都言归正传,难能可贵没放上去上篇来讲,篇幅也不 我我导致 之一,最主要的导致 是发现我犯错了! 犯那先 错了呢(都不 黄赌毒啊,那是犯罪,我是正人君子!),我想当然了! 理所当然的认为自动装配是在AutowiredAnnotationBeanPostProcessor的postProcessBeforeInitialization或postProcessAfterInitialization中实现的,我们我们我们 我们我们我们 我们我们我们 都来看下AutowiredAnnotationBeanPostProcessor类继承图

  它间接实现了BeanPostProcessor,我们我们我们 我们我们我们 我们我们我们 都再去看下那另1个 多多最好的土办法(在父类InstantiationAwareBeanPostProcessorAdapter中)

  竟然啥也没干,也不 我我简单的return bean; 当当事人深以为然的认知被推翻时,那感觉简直毙了狗了 也不 我自动装配只有和BeanPostProcessor放一块讲,不得不开两篇来分开讲,我们我们我们 我们我们我们 我们我们我们 都都知道:强扭的瓜不甜!

自动装配简单示例

  我们我们我们 我们我们我们 我们我们我们 都先来看另1个 多多简单的自动装配的示例,删剪实例代码:spring-boot-BeanPostProcessor

  AnimalConfig

View Code

  AnimalServiceImpl

  AnimalTest

  运行结果

  我们我们我们 我们我们我们 我们我们我们 都不 AnimalConfig中也不 我我将Dog、Cat、Pig的实例注册到了spring容器,那为那先 AnimalServiceImpl实例不需要 直接应用那先 实例了,我们我们我们 我们我们我们 我们我们我们 都并没法手动的将那先 实例赋值到AnimalServiceImpl实例呀? 这着实也不 我我spring提供的自动装配功能,着实我们我们我们 我们我们我们 我们我们我们 都没法手动的将那先 实例赋值到AnimalServiceImpl实例,而且 我们我们我们 我们我们我们 我们我们我们 都发现AnimalServiceImpl的属性实例上多了也不 我注解:@Autowired、@Resource、@Inject,spring通过那先 注解自动完成了属性实例的注入,而不都我你要们我们我们 我们我们我们 我们我们我们 都手动的去赋值了;没法spring是如何实现自动装配的呢? 我们我们我们 我们我们我们 我们我们我们 都慢慢往下看(注意:后文主要以@Autowired为例来讲解

自动装配源码解析

  AutowiredAnnotationBeanPostProcessor的实例化与注册

    不管为什么么说,AutowiredAnnotationBeanPostProcessor终撤回是另1个 多多BeanPostProcessor,没法它的实例化与注册(注册到spring的beanFactory)过程与BeanPostProcessor的实例化与注册一样,在spring的启动过程中,刷新上下文(refresh)的就让,会调用registerBeanPostProcessors(beanFactory)最好的土办法完成BeanPostProcessor的实例化与注册,后续再调用finishBeanFactoryInitialization(beanFactory)实例化非延迟加载的单例bean时,会用到上述注册的BeanPostProcessor

    AutowiredAnnotationBeanPostProcessor的构造最好的土办法值得我们我们我们 我们我们我们 我们我们我们 都看看

    默认情况下,AutowiredAnnotationBeanPostProcessor支持@Autowired和@Value,将会类路径下有java.inject.Inject(也也不 我我引入了javax.inject.jar),没法也支持@Inject注解,是都不 与我们我们我们 我们我们我们 我们我们我们 都最初的认知也不 我不一样?。将支持的注解放上去了autowiredAnnotationTypes属性中,后续会用到该属性

  bean的实例化与依赖注入

    默认情况下,spring会把spring容器中的bean当成non-lazy-init singleton来处理(也不 我特殊的bean除外),也也不 我我说会在spring的启动过程中就会逐个实例化那先 bean,并对那先 bean进行依赖注入;我们我们我们 我们我们我们 我们我们我们 都都真正用到那先 bean的就让,直接用就行,不需要再去实例化,也不 我我用再去注入bean的相关依赖,spring是都不 很厉害?。具体是都不 说的没法 ,我们我们我们 我们我们我们 我们我们我们 都准备好花生、瓜子和啤酒,好戏即将结速了了

    我们我们我们 我们我们我们 我们我们我们 都先找到正确的入口,而且 用下图省略掉无聊的前戏,直接进入高潮:doCreateBean(不应该是这些 吗,一天天的尽胡思乱想

    doCreateBean内容如下

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

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // 创建bean实例
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    // 允许后置处理器来修改bean定义
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                // 调用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition最好的土办法
                // AutowiredAnnotationBeanPostProcessor实现了MergedBeanDefinitionPostProcessor,即MergedBeanDefinitionPostProcessor的MergedBeanDefinitionPostProcessor会被调用
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references 立即缓存单例以便不需要

解析循环引用
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    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));
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // 填充bean,所含依赖注入
        populateBean(beanName, mbd, instanceWrapper);
        // 初始化bean,BeanPostProcessor的另1个

多多最好的土办法在此中被调用
        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.");
                }
            }
        }
    }

    // Register bean as disposable.
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}
View Code

    我们我们我们 我们我们我们 我们我们我们 都重点看下posProcessMergedBeanDefinition最好的土办法和populateBean最好的土办法

  posProcessMergedBeanDefinition

    可不都要看了会读取bean的field和method上的注解,并判断该注解否是是在autowiredAnnotationTypes中,将会在则将field封装成AutowiredFiledElement对象、将method封装成AutoWiredMethodElement对象,并存放上去InjectionMetadata对象的Set<InjectedElement> checkedElements属性中,最后将该InjectionMetadata对象缓存到了AutowiredAnnotationBeanPostProcessor的Map<String, InjectionMetadata> injectionMetadataCache属性中;说白了也不 我我将bean中被@Autowried(当然还包括@Value、@Inject)修饰的field、method找出来,封装成InjectionMetadata对象并缓存起来,就没法简单。不仅仅是上图中的animalServiceImpl这另1个 多多bean,spring中所有的非延迟加载的bean前会 走这些 创建流程。是都不 很简单,是都不 干劲十足了

  populateBean

    调用AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues最好的土办法,从injectionMetadataCache中获取当前bean的依赖信息,比如animalServiceImpl依赖的dog、pig(其他同学将会会有没法 的什么的问题:cat呢? cat是被@Resource修饰的,而@Resource都不 由AutowiredAnnotationBeanPostProcessor支持,后续会讲由谁支持),而且 逐个将依赖bean注入到目标bean(将dog、pig实例注入到animalServiceImpl实例中);依赖bean从哪来呢?还是从beanFactory中获取,将会不所处,则又回到bean的创建过程把依赖bean(dog、pig)创建出来,流程与创建animalServiceImpl实例一模一样,也也不 我我在animalServiceImpl实例的依赖注入过程中会把dog、pig对象也创建出来,而都不 等到spring逐个实例化bean的过程中轮到dog、pig才实例化dog、pig,那后续轮到dog、pig时为什么么办了,spring会把创建的bean缓存起来,下次就直接从缓存中取了。上图只演示Field的,Method也差不过多,就不演示了,都不 通过反射实现的 。

总结

  1、bean的创建与初始化

    (1)instanceWrapper = createBeanInstance(beanName, mbd, args)  创建目标bean实例;

    (2)applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)  寻找目标bean的依赖;

    (3)populateBean(beanName, mbd, instanceWrapper)  填充目标bean,完成依赖注入; (这里的循环依赖,有兴趣的可不都要自行去琢磨下)

    (4)initializeBean(beanName, exposedObject, mbd)  初始化目标bean

  2、自动装配与自动配置

    自动配置一般而言说的是spring的@Autowired,是spring的社会形态之一,而自动配置是springboot的@Configuration,是springboot的社会形态之一

  3、Spring支持几下几种自动装配的注解

    @Autowired、@Inject、@Resource以及@Value,用的最多的应该是@Autowired(至少我是没法 的),@Inject和@Value也是由AutowiredAnnotationBeanPostProcessor支持,而@Resource是由CommonAnnotationBeanPostProcessor支持(还支持@PostConstruct、@PreDestroy等注解)

    关于@Value与@Autowired,别问我我们我们我们 我们我们我们 我们我们我们 都不 否清楚我们我们我们 我们我们我们 我们我们我们 都之间的区别,不清楚的可不都要看看:Spring: @Value vs. @Autowired将会spring的官方文档,总结下:@Value >= @Autowired,也不 我我平时应用中,@Value更多的是用来注入配置值(如:@Value("${db.url}")),而@Autowired则是bean对象的注入

参考

  JAVA 注解的基本原理

  深入理解Spring系列之十四:@Autowired是如何工作的