• Spring5.2.x03自动注入模型


    知识点笔记

    1. spring是对构造方法做推断来实例化bean
    2. Spring有自己的推断模型, 改变推断模型会改变Spring对构造方法的选择

    AbstractAutowireCapableBeanFactory抽象类中的createBeanInstance方法里的一行代码
    // 推测需要的构造方法
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

    无参构造方法为 null, 会通过clazz.getDeclaredConstructor();最后走反射ctor.newInstance(argsWithDefaultValues);获取

    但内部类不会, Spring会默认编入一个传入父类作为参数的构造方法

    手动注入
    通过xml明确指定如何注入 NO = 0
    自动注入
    AbstractBeanDefinition.AUTOWIRE_BY_NAME = 1
    AbstractBeanDefinition.AUTOWIRE_BY_TYPE = 2
    AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR = 3

    @Autowired是自动注入还是手动注入?

    依赖注入是一种过程, 文档上说是基于构造方法的注入和基于Setter方法的注入

    根据类型和根据名字的区别

    ByType和ByName的区别
    比如有一个方法

    public void setByType(N n) {
    	log.debug("setter N:{}",n);
    }
    

    byNmae, 用的是beanName, 理论上就是n
    byType, 用的是set后面的名字, byType

    @AutoWired和@Resource的主要区别

    @AutoWired
    先根据类型, 再根据名字
    不仅仅是先根据类型找, 先找到a和b, 再根据名字去筛选, 找到一个

    @Resource
    先根据名字, 再根据类型

    @AutoWired的工作原理
    AutowiredAnnotationBeanPostProcessor, 可以加到属性上, 可以加到方法上, 用两个内部类

    629行左右的inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)方法解析

    解析
    value = resolveFieldValue(field, bean, beanName);
    ->DefaultListableBeanFactory#resolveMultipleBeans

    resolveMultipleBeans(): 如果是array/list/map等, 走这里来解析完成查找, 把所有的bean直接注入进来

    获取类型(拿到class): Class<?> type = descriptor.getDependencyType();

    findAutowireCandidates(): 先根据类型找到该类型所有类的bean名字String[] candidateNames, 如果找到多个就放到map里, 再根据名字(实例名字)来找, 找到一个就返回

    @Resource的工作原理

    CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor, 两者都有的方法postProcessProperties()方法, 一个找标记@Autowired的一个找@Resource的

    AutowiredAnnotationBeanPostProcessor#postProcessProperties => 会扫描出有@Autowired的玩意(field或method), 放到InjectionMetadata的属性injectedElements集合里

    遍历injectedElements集合, 调用每个对象(InjectedElement)的inject方法, @Autowired的InjectedElement重写了Field和Method方法(先类型再名字), @Resource的InjectedElement用的是父类的,

    @Resource查找bean
    autowireResource()方法来查找

    根据名字判断容器当中是否有一个名字为属性名字的bean(单例池或者是与之对应的BeanDefinition)如果找到了, 就返回了, 如果找不到, 再根据类型去找

    如果@Resource(name="aaa")注解给了值, 说明是一定要注入name为aaa的bean, 所以需要找到这个bean, 找不到对应的就报错
    如果只是field的名字不一样, 比如 A aaa, 那么就是说, 需要一个name为aaa的bean, 如果没有, 就去找一个类型为A的bean(这里的流程和@Autowired一样), 不是强制要name为aaa的bean

  • 相关阅读:
    druid 配置监控界面和开启spring支持
    关于ComboGrid取值为非下拉框数据是,隐藏面板数据清空
    Error:Execution failed for task ‘:app:processDebugManifest’.
    The newly created daemon process has a different context than expected
    在CentOs6.5下安装Python2.7.6和Scrapy
    【转】Ehcache详细解读
    项目代码的缺陷
    hibernateTemplate
    java.text.SimpleDateFormate错误
    关于集合的空指针问题
  • 原文地址:https://www.cnblogs.com/richardhaha/p/16538875.html
Copyright © 2020-2023  润新知