你都可以注入什么

优质
小牛编辑
132浏览
2023-12-01

你可以向对象注入值的位置有两个

  1. 构造函数参数
  2. 属性

向构造函数里注入参数

你的 JSON 配置文件会是这样

{
    xb : {
        type : 'nutz.demo.ioc.book.Pet',
        args : ['XiaoBai']
    }
}

args 的值时一个数组,里面每一个元素都将对应构造函数的一个参数。当然,你
必须确保你得有这样的构造函数。每个参数按照 JSON 的规定,是用半角逗号分隔的。

向属性注入参数

你的 JSON 配置文件会是这样

{
    xb : {
        type : 'nutz.demo.ioc.book.Pet',
        fields : {
            name : 'XiaoBai'
        }
    }
}

如果你不需要写 type,那么你可以用简写模式:

{
xb : { name: 'XiaoBai'    }
}

值可以不仅是字符串

是的,它还可以是

布尔

{
    xb : { dead: true }
}

数字

{
    xb : { age: 24 }
}

内部对象

{
    xb : {
        friend: {
            type : 'nutz.demo.ioc.book.Pet',
            fields : {name : 'XiaoHei'}
        }
    }
}

关于内部对象 请看这里

引用

{
    xb : { friend: {refer: 'XiaoBai' } }
}

{refer : '另外一个对象在容器中的名称'} 将会得到容器中另外一个对象

容器自身

{
    xb : { myIoc : {refer: '$Ioc'} }
}

一种特殊的引用,大小写不敏感,值就是 Ioc 容器本身

对象的名称

{
    xb : { myIoc : {refer: '$Name'} }
}

一种特殊的引用,大小写不敏感,值就是对象的名称,即 "xb"

容器上下文

{
    xb : { myIoc : {refer: '$Context'} }
}

一种特殊的引用,大小写不敏感,值就是当前容器的上下文环境接口 org.nutz.ioc.IocContext

环境变量

{
    xb : { name : {env : "JAVA_HOME"} }
}

{env : '环境变量名'} 将会得到系统中环境变量的值

从1.b.53开始, env及sys支持数组了, 例如需要JAVA_HOME下面的/bin/java的路径,可以写为

{
    xb : { name : {env : ["JAVA_HOME", "/bin/java"]} }
}

注入的属性值类似于 /opt/jdk8/bin/java

如果某个环境变量不存在的时候当成空字符串,那么,在前面加个感叹号

{
    xb : { name : {env : ["!JAVA_HOME", "/bin/java"]} }
}

当JAVA_HOME不存在时,就会输出 /bin/java

同时也支持默认值哦,用冒号分割

{
    xb : { name : {env : ["!JAVA_HOME:/opt/jdk6", "/bin/java"]} }
}

文件

{
    xb : { profile : {file : "/home/zozoh/tmp/name.txt"} }
}

{file : '文件路径'} 可以是绝对路径,也可以是 CLASSPATH 中的路径
注意: 如果是CLASSPATH路径,这个文件就不能打包进一个jar文件里面

数组或容器

如果你对象某个字段是数组,集合,或者 Map, 用 JSON 可以很自然为其设置值,不是吗?

Java 调用

这是个极度灵活的注入方式,它几乎可以让你 做任何事情。 因为它允许你直接调用一个 JAVA 函数。

更详细的说明,请参看 org.nutz.ioc.val.JavaValue Git@OSC镜像的 JDoc

下面只是列出主要的几种应用方式

静态属性

{
    xb : { oneField : {java: 'com.my.SomeClass.staticPropertyName'} }
}

静态函数

{
    xb : { oneField : {java: 'com.my.SomeClass.someFunc'} }
}

带参数的静态函数

{
    xb : { oneField : {java: 'com.my.SomeClass.someFunc("p1",true)'} }
}

参数可以是任何种类的值

容器中的对象

{
    xb : { oneField : {java: '$xh'} } ,
    xh : { name : 'XiaoHei'}
}

容器对象某个属性

{
    xb : { oneField : {java: '$xh.name'} } ,
    xh : { name : 'XiaoHei'}
}

容器对象某个方法的返回值

{
    xb : { oneField : {java: '$xh.getXXX()'} } ,
    xh : { name : 'XiaoHei'}
}

容器对象某个方法的返回值,带参数

{
    xb : { oneField : {java: '$xh.getXXX("some string", true, 34)'} } ,
    xh : { name : 'XiaoHei'}
}

参数可以是任何种类的值

你可以增加自己的特殊类型

从上面你可以看到 JSON 语法的好处,非常轻巧

  • 文件 -- {file: '路径'}
  • 环境变量 -- {env: '环境变量名'}
  • 引用 -- {refer: '对象名'}
  • JAVA -- {java: '$对象名.方法名(参数1, 参数2)'}

还可以更多吗?

是的,你完全可以扩展,比如你如果想支持一种新的类型:

oneField : {scan : '扫描仪地址'}

如何支持这种新的值的类型呢?

实现一个扩展接口

实现 org.nutz.ioc.ValueProxyMaker 接口:

package nutz.demo.ioc.book;

import org.nutz.ioc.IocMaking;
import org.nutz.ioc.ValueProxy;
import org.nutz.ioc.ValueProxyMaker;
import org.nutz.ioc.meta.IocValue;
import org.nutz.lang.Lang;

public class ScanValueProxyMaker implements ValueProxyMaker {

    public ValueProxy make(IocMaking ing, IocValue iv) {
        if ("scan".equals(iv.getType())) {
            final String address = iv.getValue().toString();

            return new ValueProxy() {
                public Object get(IocMaking ing) {
                    // 根据 address 创建一个对象
                    throw Lang.noImplement();
                }

            };
        }
        return null;
    }
    
    public String[] supportedTypes() {
        return new String[]{"scan"};
    }
}

添加到 Ioc 容器中

Ioc2 ioc = new NutIoc(new JsonLoader("path/path/name.js"));
ioc.addValueProxyMaker(new ScanValueProxyMaker());

// 下面,你就可以正常使用 Ioc 接口了

注意,这里使用的是 Ioc2 接口,它继承自 Ioc 接口,提供了更高级的方法