转载

实现一个ioc容器

  之前花了一些时间阅读了一部分spring源码,于是想自己实现一个类似spring容器功能的框架。利用工作之余花了半个月时间总算是写出了一个简单的容器seed。功能模块实现思想和spring类似,希望能够更好的帮助小伙伴了解spring的原理( github地址 )。

容器的刷新

   seed容器是通过invokeBeanFactoryPostProcessors方法来执行提前注册在容器当中的处理器。该处理的功能就是解析加载进来的配置类。解析配置类上的 @ComponentScan , @Import@Bean 注解。将所有 @Component 标识的组件加载到容器当中并形成bean的定义信息。 该方法通过扫描配置的路径来读取所有的class文件将其封装成Resource对象。之后解析class文件的信息读取到注解信息进行再解析。通过Resource信息来生成BeanDefinition,我这里解析class文件时使用的cglib包中带的asm组件使用里面的ClassReader类来解析class文件再进一步封装成bean的定义信息。

  之后调用registerBeanPostProcessor方法将所有的BeanPostProcessor实例化添加到容器当中为之后的bean创建准备工作。   最后就是将所有的单例,非懒加载的bean创建到容器当中。在创建bean时会有一些前置后置处理流程。通过实现BeanPostProcessor接口可以来自定义bean创建时的前置后置处理方法。懒加载对象和多例对象会在调用getBean的时候才去进行创建对象。在getBean的时候将单例对象缓存起来,之后进行bean的获取工作时都是从缓存中获取。在以类型进行getBean的时候会先更具类型查出所有的bean名称,并生成一个类型对应名称的缓存,加快之后获取的效率。根据类型获取单个bean时,或检验bean上有没有@Primary注解。选择由@Primary注解的对象返回。如果都没有则会抛异常。这一点和Spring的实现类似。创建bean就是使用简单的反射调用构造函数来生成对象。在处理@Bean注解的时候和spring有点差异,spring不会将@Bean导入的对象当作配置类继续处理,而我这边的实现会将其作为配置类继续处理。即:在@Bean导入的类上也可以引入其他类。

bean的生命周期

   seed的生命周期和spring容器几乎一致。

  1. 首先是创建初步的bean对象。
  2. 之后再进行bean的依赖注入工作(该功能待完成)。
  3. 调用beanPostProcessor的前置处理方法。
  4. 如果该bean实现Initialization接口那么会先执行afterPropertiesSet方法。之后执行init方法(通过@InitMethod注解来标记init方法)
  5. 调用beanPostProcessor的后置处理方法。

其他功能

  1. 通过实现seed的BeanFactoryPostProcessor接口可以再容器扫包之后往容器中添加一些bean定义信息。
  2. 实现EnvironmentAware接口可以往类中添加Environment环境变量类。从该类中可以获取环境变量信息,jvm参数信息,以及使用@PropertySources导入的配置文件数据。
  3. 实现BeanFactoryAware接口可以获取容器的beanFactory。
  4. 实现ApplicationContextAware接口可以获取到ApplicationContext容器。
  5. 容器中默认注册了环境变量信息,以及配置的读取配置文件的数据信息。通过getBean可获取容器中的组件来获取上述信息。

这些功能都是基于一个后置处理器来实现的。再bean的创建当中如果该bean实现以上接口则会将以上对相应的信息通过接口方法注入。

总结

   这个项目自己结合spring源码写出来的缩减版ioc容器。其实每一步的程序实现都是比较简单的。难点就在于通用性接口设计,功能抽象等(其实这些我都是模仿的spring:sweat:)。之后这个项目还会加上依赖注入,aop以及web服务的功能。

原文  https://juejin.im/post/5ce24d666fb9a07eb051933e
正文到此结束
Loading...