ByxContainer是一个用Java编写的轻量级IOC容器,具有以下特性:
使用JSON格式的配置文件
支持构造函数注入、静态工厂注入、实例工厂注入、属性注入、setter注入、条件注入
组件的延迟加载和单例组件
根据id注册、获取容器中的组件
项目地址:https://github.com/byx2000/ByxContainer
配置文件
ByxContainer使用JSON作为配置文件的格式。你可以将配置文件命名为任何名字,放在任何你喜欢的路径下。
ByxContainer配置文件的基本框架如下:
{ "typeAlias": { // 配置components中使用的类型别名 }, "components": { // 定义容器中的所有组件 }}
键
类型
说明
是否必须
typeAlias
对象
components中使用的类型别名
否
components
对象
定义容器中的所有组件
是
关于类型别名的使用,请参考这里。
组件
ByxContainer使用组件来管理系统中的所有对象。组件代表了系统中的一个对象,并封装了该对象的创建过程。每个组件都有一个唯一的key,当我们向ByxContainer注册一个组件时,需要为组件指定一个唯一的key,同时还要定义组件的创建过程和依赖关系。
ByxContainer的所有组件都定义在components中。组件以键值对的形式写在components对象中,键就是组件的id,值就是组件的定义。
有很多种方式来定义组件,详见下文。
{ "components": { "c1": ... // 组件c1的定义 "c2": ... // 组件c2的定义 "c3": ... // 组件c3的定义 ... }}
加载与使用ByxContainer
在应用程序的初始化代码中,按照以下方式加载配置文件,并初始化容器:
InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("配置文件路径");ContainerFactory factory = new JsonContainerFactory(inputStream);Container container = factory.create();
容器初始化完成后,需要使用注册组件时的id来获取某个特定组件:
// 获取id为c1的组件SomeType c1 = container.getComponent("c1");
组件的创建方式
在ByxContainer中,支持以下四种组件创建方式:
常数
构造函数(constructor)
静态工厂(static factory)
实例工厂(instance factor)
常数
ByxContainer支持JSON中的所有基本类型常数,包括整数、浮点数、字符串、布尔、null,它们在Java中对应的类型分别是:int、double、String、boolean、null。
{ "components": { "intValue": 123, "doubleValue": 3.14, "stringValue": "hello", "trueValue": true, "falseValue": false, "nullValue": null }}
以上配置声明了几种不同类型的常数组件。
构造函数
配置构造函数创建方式时,需要指定全限定类名,如果要传递参数则指定参数数组。
键
类型
说明
是否必须
class
字符串
全限定类名
是
parameter
数组
构造函数参数
否
{ "components": { "a1": { "class": "byx.test.A" }, "a2": { "class": "byx.test.A", "parameters": ["hello", 123] } }}
以上配置等价于以下Java代码:
A a1 = new A();A a2 = new A("hello", 123);
注:parameters数组中的元素既可以是常数,也可以嵌套其它组件的定义:
{ "components": { "a3": { "class": "byx.test.A", "parameters": [ "hello", 123, {"class": "byx.test.B"} ] } }}
以上配置等价于以下Java代码:
A a3 = new A("hello", 123, new B());
静态工厂
配置静态工厂创建方式时,需要指定工厂类的类名和工厂函数名,如果要传递参数则指定参数数组。
键
类型
说明
是否必须
factory
字符串
工厂类全限定类名
是
method
字符串
工厂类静态方法名
是
parameter
数组
方法参数
否
{ "components": { "a1": { "factory": "byx.test.Factory", "method": "createDefault" }, "a2": { "factory": "byx.test.Factory", "method": "create", "parameters": ["hello", 123] } }}
以上配置等价于以下Java代码:
A a1 = Factory.createDefault();A a2 = Factory.create("hello", 123);
实例工厂
配置实例工厂创建方式时,需要指定实例组件和工厂函数名,如果要传递参数则指定参数数组。
键
类型
说明
是否必须
instance
对象或基本类型
实例组件定义
是
method
字符串
实例工厂方法名
是
parameter
数组
方法参数
否
{ "components": { "a1": { "instance": {"class": "byx.test.B"}, "method": "createDefault" }, "a2": { "instance": {"class": "byx.test.B"}, "method": "create", "parameters": ["hello", 123] } }}
以上配置等价于以下Java代码:
A a1 = new B().createDefault();A a2 = new B().create("hello", 123);
组件的依赖声明
声明完组件的创建方式后,还可继续声明组件的依赖。ByxContainer支持以下两种依赖声明方式:
属性设置
setter方法
属性设置
ByxContainer支持在组件创建完成之后对组件的属性进行设置。这里的属性等同于JavaBean的Property。
键
类型
说明
是否必须
properties
对象
(属性名, 属性值)键值对
否
{ "components": { "a": { "class": "byx.test.A", "properties": { "id": 1001, "name": "byx", "score": 97.5 } } }}
以上配置等价于以下Java代码:
A a = new A();a.setId(1001);a.setName("byx");a.setScore(97.5);
注:properties中的属性值既可以是常数,也可以嵌套其它组件的定义:
{ "components": { "a": { "class": "byx.test.A", "properties": { "id": 1001, "b": {"class": "byx.test.B"} } } }}
以上配置等价于以下Java代码:
A a = new A();a.setId(1001);a.setB(new B());
setter方法
ByxContainer支持在组件创建完成之后调用组件的setter方法,并传递参数。
键
类型
说明
是否必须
setters
对象
(setter方法名, 方法参数)键值对
否
{ "components": { "a": { "class": "byx.test.A", "setters": { "setId": [1001], "setNameAndScore": ["byx", 97.5] } } }}
以上配置等价于以下Java代码:
A a = new A();a.setId(1001);a.setNameAndScore("byx", 97.5);
其它组件定义
ByxContainer还支持以下特殊组件定义:
集合组件
引用组件
条件组件
集合组件
ByxContainer支持List、Set和Map这三种集合组件。
下面是这三种集合组件的定义:
{ "components": { "c1": {"list": [1, 2, 3]}, "c2": {"set": [4, 5, 6]}, "c3": { "map": { "k1": 100, "k2": 200, "k3": 300 } }, "c4": { "map": [ {"key": 400, "value": "v1"}, {"key": 500, "value": "v2"}, {"key": 600, "value": "v3"} .........