spring源码学习之路---IOC初探(二)

Spring IoC源码学习:总览 前言 Spring 作为现在最优秀的框架之一,被广泛的应用于 Java 项目中,但是大多数人都只知道如何使用,而不知其中的原理。对大多数人来说可能知道如何使用已经足够了,但是对于想提升自己的人来说,学习 Spring 的源码是一个不错的选择。在过去的几个月里,我利用空闲时间将 IoC 的相关源码学习了一下,按照老习惯准备整理成笔记,以博文的形式记录下来,供自己以后使用,也供其他网友参考。由于涉及... 阅读详情
  •  上一章当中我没有提及具体的搭建环境的步骤,一个是不得不承认有点懒,另外一个我觉得如果上章所述的那些环境都还不会搭建的话,研究spring的源码还有些过早。

              如果你有兴趣的话,相信已经搭建好了学习研究的环境,接下来就可以进入正题了。

              网上也有很多关于spring源码学习的文章以及帖子,讲的也都不错,但是有些可能高估了读者的能力,该深入的地方反倒一句带过,我现在也是在一步一步研究,和大家的进度一样,所以可能在我的角度来和各位探讨,更加容易。

              首先我们来说一下IOC,IOC是spring最核心的理念,包括AOP也要屈居第二,那么IOC到底是什么呢,四个字,控制反转。

              网上有不少是这么解释IOC的,说IOC是将对象的创建和依赖关系交给容器,这句话我相信不少人都知道,在我个人的理解,IOC就是让我们的开发变的更简单了。

              为什么这么说呢,光说没意思,直接上代码。

     public class Person {
    
        public void work(){
            System.out.println("I am working");
        }
    }

             上面这个是Person类,如果我们还有一个Company公司类,公司要开张需要人来工作,所以我们可能需要这样。

    public class Company {
    
        public Person person;
        
        public Company(Person person){
            this.person = person;
        }
        
        public void open(){
            person.work();
            System.out.println("I am opening");
        }
    }

             好了,这样可以了,虽说和现实有些区别,毕竟没有一个人的公司,但是就是这么个意思。必须要有人在公司里,公司才能开张。

             有了spring上述情况我们是怎么写的呢?Person类不变,Company就可以简单些了。

    public class Company {
    
        @Autowired
        public Person person;
        
        public void open(){
            person.work();
            System.out.println("I am opening");
        }
    }

             OK了,使用注解后,spring里的写法是这样的,是不是简单很多?或许你可能会说,这才减少了多少代码,但是事实上是,真正的项目中,不可能有这么简单的依赖关系,或许是2层,3层甚至N层。

             当然,可能我们有时候用的XML,XML和注解的区别就在于这里,注解可以快速的完成依赖的注入,但是缺点也很明显,那就是比如我公司里不需要人了,我需要的是机器,那么我还要手动改代码,将Person换成机器(这里应该是英文,英语不好,懒得查了,只记得念“磨洗”),而如果是XML配置,那么我们只需要改下配置文件就可以。维护起来会方便很多,当然XML的缺点也很明显,那就是依赖关系复杂的时候,XML文件会比较臃肿,所以我们一般的做法是将XML分离开来。

             说到这里,有些扯远了,但是我觉得以上可以足够说明IOC的好处,知道了IOC的好处,我们自然就要知道怎么来实现IOC了。

             或许看了spring的源码,第一感觉是很蒙,包太多,我也很蒙,但是研究东西就是得沉下心来,先来关注一下这个接口,BeanFactory,附上代码。

    package org.springframework.beans.factory;
    
    import org.springframework.beans.BeansException;
    
    /*
     * @author Rod Johnson
     * @author Juergen Hoeller
     * @since 13 April 2001
     */
    public interface BeanFactory {
    
        String FACTORY_BEAN_PREFIX = "&";
    
    
        Object getBean(String name) throws BeansException;
    
    
        <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    
        
        <T> T getBean(Class<T> requiredType) throws BeansException;
    
        
        Object getBean(String name, Object... args) throws BeansException;
    
        
        boolean containsBean(String name);
    
        
        boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    
        
        boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    
        
        boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;
    
        
        Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    
        
        String[] getAliases(String name);
    
    }

              这个便是spring核心的Bean工厂定义,上面的author说是2001年写的,已经历史久远了,这个类是spring中所有bean工厂,也就是俗称的IOC容器的祖宗,各种IOC容器都只是它的实现或者为了满足特别需求的扩展实现,包括我们平时用的最多的ApplicationContext。从上面的方法就可以看出,这些工厂的实现最大的作用就是根据bean的名称亦或类型等等,来返回一个bean的实例。

              一个工厂如果想拥有这样的功能,那么它一定需要以下几个因素:

              1.需要持有各种bean的定义,否则无法正确的完成bean的实例化。

              2.需要持有bean之间的依赖关系,否则在bean实例化的过程中也会出现问题。例如上例,如果我们只是各自持有Person和Company,却不知道他们的依赖关系,那么在Company初始化以后,调用open方法时,就会报空指针。这是因为Company其实并没有真正的被正确初始化。

              3.以上两种都要依赖于我们所写的依赖关系的定义,暂且认为是XML文件(其实可以是各种各样的),那么我们需要一个工具来完成XML文件的读取。

              我目前想到的,只需要满足以上三种条件,便可以创建一个bean工厂,来生产各种bean。当然,spring有更高级的做法,以上只是我们直观的去想如何实现IOC。

              其实在上述过程中仍旧有一些问题,比如第一步,我们需要持有bean的定义,如何持有?这是一个问题。我们知道spring的XML配置文件中,有一个属性是lazy-init,这就说明,bean在何时实例化我们是可以控制的。这个属性默认是false,但是我们可以将这个属性设置为true,也就是说spring容器初始化以后,配置了延迟加载的各种bean都还未产生,它们只在需要的时候出现。

              所以我们无法直接的创建一个Map<String,Object>来持有这些bean的实例,在这里要注意,我们要储存的是bean的定义,而非实例。

              那么接下来,又是一个祖宗级别的接口要出现了,来看BeanDefinition。

    package org.springframework.beans.factory.config;
    
    import org.springframework.beans.BeanMetadataElement;
    import org.springframework.beans.MutablePropertyValues;
    import org.springframework.core.AttributeAccessor;
    
    
    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    
    
        String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
    
    
        String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
    
    
        int ROLE_APPLICATION = 0;
    
    
        int ROLE_SUPPORT = 1;
    
    
        int ROLE_INFRASTRUCTURE = 2;
    
    
        String getParentName();
    
    
        void setParentName(String parentName);
    
    
        String getBeanClassName();
    
    
        void setBeanClassName(String beanClassName);
    
    
        String getFactoryBeanName();
    
        
        void setFactoryBeanName(String factoryBeanName);
    
        
        String getFactoryMethodName();
    
        
        void setFactoryMethodName(String factoryMethodName);
    
    
        String getScope();
    
        
        void setScope(String scope);
    
        
        boolean isLazyInit();
    
        
        void setLazyInit(boolean lazyInit);
    
        
        String[] getDependsOn();
    
        
        void setDependsOn(String[] dependsOn);
    
        
        boolean isAutowireCandidate();
    
        
        void setAutowireCandidate(boolean autowireCandidate);
    
        
        boolean isPrimary();
    
        
        void setPrimary(boolean primary);
    
    
        ConstructorArgumentValues getConstructorArgumentValues();
    
    
        MutablePropertyValues getPropertyValues();
    
    
        boolean isSingleton();
    
    
        boolean isPrototype();
    
        
        boolean isAbstract();
    
        
        int getRole();
    
        
        String getDescription();
    
        
        String getResourceDescription();
    
        
        BeanDefinition getOriginatingBeanDefinition();
    
    }

                顾名思义,这个便是spring中的bean定义接口,所以其实我们工厂里持有的bean定义,就是一堆这个玩意,或者是他的实现类和子接口。这个接口并非直接的祖宗接口,他所继承的两个接口一个是core下面的AttributeAccessor,继承这个接口就以为这我们的bean定义接口同样具有处理属性的能力,而另外一个是beans下面的BeanMetadataElement,字面翻译这个接口就是bean的元数据元素,它可以获得bean的配置定义的一个元素。在XML文件中来说,就是会持有一个bean标签。

                仔细观看,能发现beanDefinition中有两个方法分别是String[] getDependsOn()和void setDependsOn(String[] dependsOn),这两个方法就是获取依赖的beanName和设置依赖的beanName,这样就好办了,只要我们有一个BeanDefinition,就可以完全的产生一个完整的bean实例。

                今天就先到这里吧,我也是边看边写的,与其说跟我一起学,其实这个系列的应该叫源码学习笔记,更多的还是看到哪里,写到哪里,谈不上跟我一起学。

                如果文中有不周到的地方,希望各位尽管指出。

               

     

     


    版权声明:本文版权归作者(左潇龙)所有,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。原文地址:http://www.zuoxiaolong.com/html/article_131.html

打怪上分! 手写Spring ioc 框架,狠狠的“撸撸”Spring 源码 估计很多朋友使用 spring 很长时间,对于 spring 使用非常频繁,实际上对于源码一直没有静下心来学习过。 你是不是有这样的感觉呢? 但是 spring 源码存在一个问题,那就是过于抽象,导致学习起来成本上升。所以本文由浅入深,只实现 spring 的核心功能,便于自己和他人学习 spring 的核心原理。 文章有点长,耐心阅读!如果对你有帮助,记得三连哦! spring 的核心 Spring 的核心就是 spring-beans,后面的一切 spring-boot,spring-cloud 阅读详情

相关推荐

储能逆变器动态无功补偿:从原理到算法实现

本文深入解析了储能逆变器动态无功补偿的核心原理与算法实现。通过四象限运行与解耦控制技术,储能逆变器可在充放电的同时,快速、精准地调节无功功率,有效提升电网电能质量与功率因数。文章详细阐述了从相位调节、容量限制到PI控制算法的完整技术路径,并结合工程实践,探讨了其在光伏/储能系统中的协同控制策略与进阶应用价值。

weixin_29216353的博客 207

spring 源码系列(四)spring中的重要类介绍

目录 一、BeanDefinition 二、BeanFactory和FactoryBean BeanFactory FactoryBean 三、BeanFactoryPostProcessor BeanDefinitionRegistryPostProcessor 四、BeanPostProcessor 总结 spring源码非常负责,如果想阅读好spring源码,那么一些重要类...

linhui258的博客 1380

【AutoDL】使用云服务器跑深度学习代码

1.算力市场 租用服务器,选择自己心仪的服务器2.镜像可以选择一些基础的镜像,社区镜像里是git上有的环境。3.上传文件在文件存储中,选择上传的区,在右边点击上传,选择自己的文件上传到云服务器中。

weixin_45768644的博客 3703

Spring Framework 源码阅读(二):BeanDefinition的作用

Spring Framework 源码阅读(二):BeanDefinition接口的作用 BeanDefinition接口的定义: package org.springframework.beans.factory.config; import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.MutablePropertyValues; import org.springframework.co

kaven 1975

Mixly米思齐——超声波测距控制LED灯

为了更加地贴近中小学信息技术的课程,我们用米思齐做了一个实验——根据距离的远近开启警报灯(利用超声波测出距离)。 实验硬件准备 arduino uno R3 、USB 数据线、YFROBOT UNO I/O扩展板、YFROBOT超声波传感器模块、模块3P连接线x1、LED灯x1 硬件连接图如下: 在arduino uno R3 上再接一个LED灯,实物图如下: 在本次实验中,LE...

Janise_的博客 9978

SiamFC++笔记

SiamFC++: Towards Robust and Accurate Visual Tracking with Target Estimation Guidelines 文章根据这些思路:引入分类和目标状态估计分支(G1),无歧义的分类得分(G2),无先验知识的跟踪(G3)和评估质量得分(G4)来设计SiamFC ++。 SiamRPN ++和SiamFC ++的比较(红色部分代表得分高的区域): guide: G1 : 分类和状态估计任务的分离:分类任务将目标从干扰物和背景中分类出来,目标状态

木木JL的博客 9433

Spring - IOC源码分析(一)

Spring IOC容器的加载过程 @Configuration @ComponentScan("com.spring.ioc.service") public class MainStat { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(MainStat.class); UserServiceImpl bean = con

java123456111的博客 829

【DEIM创新改进】独家下采样创新改进篇 | ECCV 2026 | DEIM 引入FSD-Down频域-空间动态下采样,在下采样过程中保留小目标的高频信息、助力小目标检测、遥感小目标检测有效涨点

🔥本文提出了一种名为FSD-Down的频域-空间动态下采样模块,用于改进DEIM网络模型在小目标检测中的性能。FSD-Down通过小波分解显式保留低频语义和高频细节,结合分组卷积、动态通道权重和可学习缩放因子,自适应强化目标边缘与纹理特征。该模块能有效减轻传统下采样造成的频率混叠和细节丢失,提升对小目标、密集目标和低对比度目标的检测能力。实验表明,FSD-Down计算开销可控,在保持实时性的同时显著提升检测精度,特别是在VisDrone和AITODv2数据集上对小目标的检测性能提升显著。

Ai缝合怪、助力小伙伴高效发论文 82

Spring事务如何基于SpringAOP来实现事务代理?

通常我们要开启spring的事务我们需要加上@EnableTransactionManagement这个注解,那么肯定的这个注解的作用就是往容器里面去import了一个组件从而使得方法上面的@Transaction注解生效,而且spring事务的原理也是基于代理去实现事务回滚,事务隔离等功能的,那么既然是基于代理的原理,spring的事务与springAOP在实现这方面上有何异曲同工之处呢? 首先来看看@EnableTransactionManagement这个注解做了什么事 @Override .

我神级欧文的博客 1616

26、机器学习模型的成员推断攻击与隐私保护

本文探讨了机器学习模型面临的成员推断攻击及其对隐私的潜在威胁。通过使用CIFAR-10数据集,详细介绍了如何利用影子模型和攻击模型推断特定数据点是否属于模型的训练集。实验表明,即使无法直接访问模型参数和原始数据,攻击者仍能以高于随机猜测的概率进行推断,从而构成隐私风险。此外,文章还分析了实验的关键技术点,并提出了多种隐私保护建议,包括数据脱敏、差分隐私、模型正则化等方法。

coffee的博客 123

基于Playwright与异步技术的公司评价智能爬取实战:以Glassdoor为例

本文将介绍一套基于最新Python技术的智能爬虫解决方案,使用Playwright实现浏览器自动化,结合异步编程和智能解析技术,高效抓取Glassdoor等平台的公司评价数据。我们不仅关注数据获取,更注重数据的结构化处理和反反爬虫策略的实现。

2201_76125261的博客 223

springboot注解(全)

Spring Boot是一个快速开发框架,快速的将一些常用的第三方依赖整合(通过Maven子父亲工程的方式),简化xml配置,全部采用注解形式,内置Http服务器(Jetty和Tomcat),最终以Java应用程序进行执行。

zhaoshuangjian 7283

AIGC实战——多模态模型DALL.E 2

DALL.E 2 是 OpenAI 提出的一个大规模文本生成图像模型,可以根据文本提示生成各种风格的逼真图像。它通过将预训练模型 CLIP 与 GLIDE 中的扩散模型架构相结合完成任务。它还具有其他应用,例如通过文本提示编辑图像和提供给定图像的变体。虽然它也有一些局限性,例如不一致的文本渲染和属性绑定,但 DALL.E 2 是仍然一个非常强大的AI模型,推动了生成模型的发展。

盼小辉丶的博客 1万+

Spring源码学习之路---IOC初探(二)

原文地址:https://blog.youkuaiyun.com/zuoxiaolong8810/article/details/8550421          上一章当中我没有提及具体的搭建环境的步骤,一个是不得不承认有点懒,另外一个我觉得如果上章所述的那些环境都还不会搭建的话,研究spring的源码还有些过早。          如果你有兴趣的话,相信已经搭建好了学习研究的环境,接下来就可以进入正题了。...

杨春建的博客 559

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Spring IoC源码学习:invokeBeanFactoryPostProcessors 详解

前言 随着Spring IoC:context:component-scan节点解析的结束,obtainFreshBeanFactory方法的解析也告一段落,我们通过5篇文章,完整的介绍了obtainFreshBeanFactory方法。本文将介绍obtainFreshBeanFactory方法之后的另一个重要方法——invokeBeanFactoryPostProcessors。 ...

程序员囧辉 2万+

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Spring IoC源码学习:obtainFreshBeanFactory 详解

前言 上文Spring IoC:ApplicationContext 刷新前的配置介绍了refresh 方法前的环境准备操作,接下来正式进入 refresh方法。prepareRefresh是refresh里的第一个方法,主要是一些准备工作,比较简单的方法,看一下就了解了。接下来是obtainFreshBeanFactory方法,该方法用于获得一个新的 BeanFactory,本...

程序员囧辉 1万+

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Spring IOC 源码分析

【1】Spring容器在启动的时候,先会保存所有注册来的Bean的定义信息;■Xml注册■ 注解注册Bean@Service@Component@Bean等等【2】Spring容器会在合适的时机创建bean;■ 用到这个bean的时候,利用getBean创建bean,创建好后保存在容器中。■ 统一创建剩下所有bean的时候,调用:每一个bean的创建完成,都会使用各种后置处理器进行处理,来增强bean的功能:■:处理自动注入;■:来做AOP功能;等等。。。事件监听。

程序猿进阶 2409

Spring深度学习:IOC容器及源码解析

大家经常戏称Java工程师为Spring工程师,毫无疑问,这句话体现出Spring框架在Java开发中的重要性和普及度。本文小豪将带大家深度学习Spring IOC底层源码,学习过程中不仅仅是了解Spring IOC的工作原理,更重要的是学会理解框架的底层逻辑,从而提升我们的思维能力。

Code豪客 1676

Spring IoC源码学习:finishBeanFactoryInitialization 详解

前言 在介绍了 obtainFreshBeanFactory、invokeBeanFactoryPostProcessors、registerBeanPostProcessors三个重要方法后,我们终于来到了最后一个重要方法:finishBeanFactoryInitialization。finishBeanFactoryInitialization 是这四个方法中最复杂也是最重要的,是整个...

程序员囧辉 9840

【Spring源码系列-IOC容器二】

spring获取bean的流程

qq_45592483的博客 1473

Spring IoC源码学习:getBean 详解

前言 接着Spring IoC:finishBeanFactoryInitialization详解,我们正式开始学习获取bean实例方法,该方法是Spring最核心的方法。 正文 单击 preInstantiateSingletons方法里的getBean(beanName)代码,进入该方法。 getBean @Override public Object ...

程序员囧辉 1万+
上一篇: spring源码学习之路---环境搭建(一)
下一篇: spring源码学习之路---IOC实现原理(三)
admin_java
博客等级 码龄10年 17粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值