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的理解

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

#学习路径##Spring#
全部评论
> SpringIOC设计思想是面向对象应用中对于对象间依赖关系松耦合、资源复用以及对象统一的生命周期管理的实现方案介绍   > 对象的创建以及对象依赖组件的创建均由IOC容器实现,他们只需声明自己是否需要由IOC容器管理即可   > 其次IOC容器还将对象的依赖在初始化时动态注入进去(DI),对象只需声明所需依赖类型即可,而不需要知道注入依赖的具体对象   > 对于对象的生命周期管理交由IOC容器管理,对象仅对依赖有使用权,方便IOC容器进行功能拓展
点赞 回复
分享
发布于 2021-03-16 00:17

相关推荐

3 10 评论
分享
牛客网
牛客企业服务