首页 > Spring控制反转IOC和依赖注入DI结构化简述
头像
归墨
编辑于 2021-03-22 08:35
+ 关注

Spring控制反转IOC和依赖注入DI结构化简述

开头先举一个通俗的例子

《Spring婚介所》
Spring国规定不允许自己私人找对象(官方约定,不犯法,但是会乱了Spring国的正常婚配原则),并且每个人在喝孟婆汤投胎前Spring国都会要他将自己信息以及自己所需什么样子的对象登记到婚姻介绍所再喝孟婆汤投胎.投胎后婚介所会根据你的需求帮你把对象给你当然如果你对象还没投胎你得等对象投胎完再塞给你.看着就很棒解决了我们平时找对象的问题,只不过这个婚介所比较黑.你需要的这个对象全国就一个,谁要他都给,全国通用.而且你也不用管对象的生活管理问题,只需要用到对象的时候叫过来用就好了,反正这时候你已经知道对象在哪里了

IOC控制反转介绍

1. IOC是什么: IOC名字是控制反转,是一种解决面向对象中对象依赖管理松耦合技术思想,将对象创建、资源获取和生命周期管理统一交由外部容器,而不需要对象本身关心
2. IOC解决的问题: 之前对象对自身依赖的功能对象创建由对象本身实现,并且需要指定具体类型,导致对象间的耦合度非常高,功能重用率低下
3. IOC的实现思想: 通过IOC思想将对象创建和依赖注入的控制权转交由外部组件,使用对象本身只需声明自己需要哪一种类型的对象即可,依赖组件会通过外部组件自动注入进来,使得对象间的耦合度降低,也提高了对象资源复用率
4. 反转解释: 依赖对象创建由本身创建移交至外部容器统一创建并注入进来、对象自身也由外部容器创建、它们的管理权也由外部容器管理,例如什么时候需要释放销毁、在那些阶段需要执行什么方法之类的(以前对象依赖的创建由对象本身操作,并且依赖何时生成何时丢弃也由自己决定,现在统一交由外部容器,对象仅有依赖的使用权,该依赖何时生成与销毁由容器决定)
5. IOC实现: 依靠@ComponentScan注解,扫描需要进行加载的Bean.声明为Bean通常使用@Component、@Controller、@RestController、@Service、@Mapper等

DI依赖注入介绍

1. 依赖注入是什么: 依赖注入就是由外部容器在运行中通过对象依赖关系声明动态的将对象的依赖添加到对象中去,具体注入什么依赖由容器决定(IOC思想的延申与具化)
2. 依赖注入解决问题: 降低不同对象间的强耦合关系,提高资源复用率
3. DI实现: 依赖注入依靠@Autowired、@Resource

Spring源码实现(结合源码才是理解最快的方式)

控制反转和依赖注入大部分功能实现都在AbstractAutowireCapableBeanFactory类中
doCreateBean实现了通过类的元数据信息创建并初始化Bean添加到容器中
populateBean方法实现依赖注入功能
其中(1390行)描写到根据BeanDefinition获取该Bean的属性注入模式.然后根据名称/类型将依赖的Bean创建并添加到属性中.这里后续给Bean注入属性方法还可以拓展InstantiationAwareBeanPostProcess的Bean属性注入和属性值注入自定义方法(1412行)
其中BeanDefinition中依赖信息是第576行applyMergedBeanDefinitionPostProcessors添加进去的,可以查看SpringApplication上下文刷新第六步来辅助理解

PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    // 按名称查找Bean. 
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
        autowireByName(beanName, mbd, bw, newPvs);
    }
    // 按类型查找Bean
    if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        autowireByType(beanName, mbd, bw, newPvs);
    }
    pvs = newPvs;
}

PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
    if (pvs == null) {
        pvs = mbd.getPropertyValues();
    }
    for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
        // 拓展点
        PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
        if (pvsToUse == null) {
            if (filteredPds == null) {
                filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            // 拓展点
            pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                return;
            }
        }
        pvs = pvsToUse;
    }
}

参考

IOC与DI的理解

文中有描述错误的烦请大佬指正

全部评论

(1) 回帖
加载中...
话题 回帖

推荐话题

相关热帖

近期热帖

近期精华帖

热门推荐