# needcoke-ioc **Repository Path**: needcoke/needcoke-ioc ## Basic Information - **Project Name**: needcoke-ioc - **Description**: 实现类似于Spring的容器管理工具,因为项目中不需要使用很重的Spring,而右希望能够拥有它的IOC,DI - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: dev_VER-0.4 - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 2 - **Created**: 2021-09-09 - **Last Updated**: 2022-08-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # needcoke-ioc文档 > **简介**: needcoke-ioc是一个小型的轻量级的容器管理,依赖注入框架。相当于更轻量的Spring,并且提供了更加丰富的特性。 ## 1 启动程序 > needcoke-ioc的启动类似于SpringBoot的启动类,下面是一个标准的needcoke-ioc启动代码块。 ```java package org.needcoke.dfs.nn; import org.needcoke.ioc.ContextRun; import org.needcoke.ioc.annotation.BeanScanner; import org.needcoke.ioc.annotation.Component; import org.needcoke.ioc.core.ContextHolder; @Component @BeanScanner(path = {"org.needcoke.dfs.nn"}) public class NameNodeApplication { public static void main(String[] args) { ContextHolder context = ContextRun.run(NameNodeApplication.class, args); } } ``` > **@Component**标志着该类是一个组件,并且也可以是个配置类。相当于Spring中的 **@Component** 和 **@Configuration** 的结合 > > **@BeanScanner**提供了容器的扫描器,path属性是配置扫描范围。如果不在启动类注解 **@BeanScanner** ,程序会直接结束。如果注解了 **@BeanScanner**但是不配置path,则会默认扫描**org.needcoke.ioc**包路径下的类。如果配置了path并且其中不包含**org.needcoke.ioc**下的包路径,则会同时扫描**org.needcoke.ioc**。 > > **ContextRun** 类是ioc容器的核心启动类。 **ContextRun.run(启动类的类型,main方法的参数列表)**是ioc容器的核心启动方法,启动成功会返回**ContextHolder**容器类。 ## 2 ContextHolder > ContextHolder提供类容器的存取功能,所有的 **@Component** 组件,**@Bean** 定义的bean都会被,配置文件中的配置,在启动容器时被加载到ContextHolder中。 > > 如果我们不需要做二次开发的话,仅需要关注以下核心方法。 ```java /* 通过bean的类型获取bean, 返回该类型的所有bean的列表 */ public List getBean(Class type); /* 通过名称获取bean,注意名称允许重复,但是会发生覆盖,谁被谁覆盖由容器加载顺序决定 */ public T getBean(String name); /**向容器存放一个普通的bean,需要用ContextBean进行一次包装**/ public void putBean(ContextBean bean); ``` > 关于bean的名称: > > ​ bean的名称可以指定,例如 **@Component** 注解的name属性, **@Bean** 的name属性。如果name属性为空 **@Component** 会使用类名的首字母小写; **@Bean** 注解会使用函数名。 **2.1 @Component注解不带name属性** > 该类被容器扫描后,生成的组件bean名称会是threadPool ```java @Component public class ThreadPool { ``` **2.2 @Component注解带name属性** > 该类被容器扫描后,生成的组件bean名称会是executorService ```java @Component(name = "executorService") public class ThreadPool { ``` **2.3 @Bean不带name** >该类被容器扫描后,生成的bean名称会是nameNodeMap ```java @Bean public Map nameNodeMap(){ return new ConcurrentHashMap<>(); } ``` **2.4 @Bean带name** >该类被容器扫描后,生成的bean名称会是nnMap ```java @Bean(name = "nnMap") public Map nameNodeMap(){ return new ConcurrentHashMap<>(); } ``` **2.5 手动设置bean 确定name** > 在**ContextHolder.putBean(ContextBean bean)**属性时,指定的**ContextBean**对象的**name**属性就将会是这个bean的名称。 ```java @Accessors(chain = true) public class ContextBean { public Class clz; public Object value; public String name; public String id; ``` ## 3 Handle接口 > **org.needcoke.ioc.handle.Handle**接口是IOC容器的核心处理器接口,所有在容器扫描范围内实现**Handle**接口的类,全部都会被容器扫描到**ContextRun**类(1中已经说明了它的全路径,和它的地位)执行。 > > 在needcoke-ioc中分为以下**6**种Handle,上五种Handle都是needcoke-ioc的内置Handle会被优先执行,最后一种是其他Handle。 > > 以下是**ContextRun**类中的一段源码,容器扫描到的其他**Handle**都会被**add**到**otherHandles**这个**list**中。 ```java /* 配置文件读取 */ Handle configReaderHandle = null; /* 配置文件注入 */ Handle configInjectHandle = null; /* bean扫描 */ Handle beanScanHandle = null; /* bean注入 */ Handle beanInjectHandle = null; /* component调用初始化方法 */ Handle componentInitHandle = null; /* 其他Handle */ List otherHandles = new ArrayList<>(); ContextBean holderBean = new ContextBean() .setName("contextHolder") .setClz(ContextHolder.class) .setValue(holder); holder.putBean(holderBean); ``` ### 3.1 为什么要强调Handle接口 > 外部扩展needcoke-ioc时,必须要实现Handle接口 > > **例如:** 在实现 **needcoke-aop**时,实现了 **org.needcoke.aop.handle.AOPHandle**,这样启动时并不需要对needcoke-ioc的启动方式做任何修改,仅需要指定 **@BeanScanner** 的扫描范围,就可以自动加载 **needcoke-aop** 的内容。 > > 其他使用: > > needcoke-web中扩展了 **org.needcoke.web.handle.WebHandle** ,来处理http请求等内容。 > > coke-dfs的dfs-name-node中,扩展了 **org.needcoke.dfs.nn.handle.NameNodeCoreHandler** 来处理注册节点的核心功能。 ## 4 基本注解以及使用 https://www.kuangstudy.com/bbs/1438400389824167938 @Autowired 注入默认按照类型注入,name属性赋值则严格按照名称注入,没有则不注入 @bean 类似于Spring的@Bean @Component 配置类和需要被容器托管的类必须写 @Note 目前仅用于注释 @BeanScanner 包扫描注解 @Init 被标注了@Component的方法在执行完构造函数后会调用@Init标注的方法初始化bean @Value 配置文件注入 ContextBean.java 容器对bean的封装 ContextHolder.java 容器 ContextRun.java 容器启动器,只有调用其中的run方法,容器才能够正常启动 ## 5 静态注入有多秀 > needcoke-ioc比Spring更加灵活的一个点就是静态注入,它到底可以有多秀,上代码。 ```java package org.needcoke.dfs.nn.net; import org.needcoke.ioc.annotation.Autowired; import org.needcoke.ioc.annotation.Component; @Component public class StaticInjectDemo { @Autowired private static StaticInjectDemo staticInjectDemo; public static StaticInjectDemo getInstance(){ return staticInjectDemo; } } ``` > 可以通过类名来获取容器中bean,在不是容器托管的类中可以轻松操作容器中的bean