Code-Life icon indicating copy to clipboard operation
Code-Life copied to clipboard

IOC容器简易实现的知识点

Open Draymonders opened this issue 3 years ago • 9 comments

简易IOC容器实现: https://github.com/Draymonders/IoC-Implement

四种定义Bean的注解

  • Controller
  • Service
  • Repository
  • Component

Draymonders avatar Aug 22 '20 00:08 Draymonders

IOC容器需要使用者给出具体的扫描的位置,才能获取相对应的bean

在此我们使用 包名 作为扫描的位置,如何根据包名定位到具体的class路径呢?

  • 使用绝对路径是不优雅的,因为每个用户的绝对路径不同,且最终打成jar包或者war包,少有人知道package的实际路径。

实现方式:

  1. 获取当前的类加载器。
  2. 根据类加载器去获取对应包名的URI信息
  3. 根据URI提取出来绝对路径
  4. 对绝对路径下的所有的文件夹扫描,收集Class信息 (具体的packageName,className)
  5. 通过反射机制去获取到Class

Draymonders avatar Aug 22 '20 01:08 Draymonders

我们最终期待系统中有一个bean容器,那么如何构造线程安全的bean容器呢?

用到了单例模式

有三种实现

  • 饿汉式
  • 懒汉式
  • 反射无法注入的 枚举方法(EnumSingleton)

Draymonders avatar Aug 22 '20 04:08 Draymonders

实现容器

  1. 保存Class对象及示例的载体 (这里用ConcurrentHashMap来存)
  2. 容器的加载 (加载容器 && 加载beans)
  3. 容器的操作方式
    • 增加,删除bean
    • 根据Class获取对应实例
    • 获取所有的Class和实例
    • 通过注解来获取被注解标注的Class AController a = new AController();
    • 通过超类获取对应的子类Class (类似这种AService a = new AServiceImpl())
    • 获取容器载体保存Class的数量

Draymonders avatar Aug 22 '20 05:08 Draymonders

简易依赖注入(暂无循环依赖情况, 暂时也不考虑多impl的情况), 只注入到Field

  • 扫描basePackage下的所有的bean,并且加载到bean容器中
  • 对所有的bean扫描其所有的field,找出包含Autowired的字段
  • 提取Autowired注解的类,然后根据类去bean容器中寻找对应的bean
  • 对相关的beanfiled进行反射注入。

多impl的情况

  • 比如AServiceAServiceImpl1,AServiceImpl2两个实现类
  • 如果不指定,IoC容器不知道注入哪个依赖,因而抛出异常,如果指定了@Qualifier, 则会去取@Qualifier对应的值去关联对应的 AService实现类

Draymonders avatar Aug 22 '20 12:08 Draymonders

BeanFactory 和 FactoryBean的区别

  • BeanFactorySpring里最基础的容器,定义了多种getBean方法
  • FactoryBean 则是Bean的工厂实现,用于获取对应的bean, 定义了 getObject方法

简单BeanFactory实现

todo: 阅读 DefaultListableBeanFactory 源码

Draymonders avatar Aug 23 '20 06:08 Draymonders

ApplicationContext

Spring高级容器

  • 传统使用有FileSystemXmlApplicationContext, ClassPathXmlApplicationContext, XmlWebApplicationContext
  • 当今使用有AnnotationConfigServletWebServerApplicationContext, AnnotationConfigServletReactiveApplicationContext

Draymonders avatar Aug 23 '20 10:08 Draymonders

Spring处理流程

Bean -> Spring托管的对象
|
|
Resource  -> 配置,文件, xml,数据库的一个抽象
|
|
ResourceLoader / ResourcePatternResolver -> 根据路径或者其他信息,定位到Resource
|
|
BeanDefinitonReader -> 获取BeanDefinition容器, 也即BeanFactory, ApplicationContext的实现类
|
|
BeanDefinition -> 获取bean的配置信息,以用于生成bean,可以注册到容器中。Map<name, BeanDefintion>
|
|
BeanFactory   -> 基础容器
|
|
ApplicationContext  -> 高级容器

Draymonders avatar Aug 23 '20 11:08 Draymonders

AOP实现

AOP简易实现

Draymonders avatar Aug 26 '20 06:08 Draymonders

循环依赖

  • 如何发现循环依赖? A:加入一个正在构造的bean的记录,每个bean开始构造时加入到记录中,构造完成就移走,如果有依赖,先看依赖的bean是否在构造中,如果是,就构成了循环,抛出异常

Draymonders avatar Oct 27 '20 02:10 Draymonders