你都可以注入什么

Jul 10, 2017 10:38:44 AM

作者:zozoh

从哪里注入?

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

  • 构造函数参数
  • 属性

向构造函数里注入参数

你的 JSON 配置文件会是这样

  1. {
  2. xb : {
  3. type : 'nutz.demo.ioc.book.Pet',
  4. args : ['XiaoBai']
  5. }
  6. }

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

向属性注入参数

你的 JSON 配置文件会是这样

  1. {
  2. xb : {
  3. type : 'nutz.demo.ioc.book.Pet',
  4. fields : {
  5. name : 'XiaoBai'
  6. }
  7. }
  8. }

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

  1. {
  2. xb : { name: 'XiaoBai' }
  3. }

值可以不仅是字符串

是的,它还可以是

布尔

  1. {
  2. xb : { dead: true }
  3. }

数字

  1. {
  2. xb : { age: 24 }
  3. }

内部对象

  1. {
  2. xb : {
  3. friend: {
  4. type : 'nutz.demo.ioc.book.Pet',
  5. fields : {name : 'XiaoHei'}
  6. }
  7. }
  8. }

关于内部对象 请看这里

引用

  1. {
  2. xb : { friend: {refer: 'XiaoBai' } }
  3. }

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

容器自身

  1. {
  2. xb : { myIoc : {refer: '$Ioc'} }
  3. }

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

对象的名称

  1. {
  2. xb : { myIoc : {refer: '$Name'} }
  3. }

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

容器上下文

  1. {
  2. xb : { myIoc : {refer: '$Context'} }
  3. }

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

环境变量

  1. {
  2. xb : { name : {env : "JAVA_HOME"} }
  3. }

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

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

  1. {
  2. xb : { name : {env : ["JAVA_HOME", "/bin/java"]} }
  3. }

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

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

  1. {
  2. xb : { name : {env : ["!JAVA_HOME", "/bin/java"]} }
  3. }

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

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

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

文件

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

{file : '文件路径'} 可以是绝对路径,也可以是 CLASSPATH 中的路径

数组或容器

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

Java 调用

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

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

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

静态属性

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

静态函数

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

带参数的静态函数

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

参数可以是任何种类的值

容器中的对象

  1. {
  2. xb : { oneField : {java: '$xh'} } ,
  3. xh : { name : 'XiaoHei'}
  4. }

容器对象某个属性

  1. {
  2. xb : { oneField : {java: '$xh.name'} } ,
  3. xh : { name : 'XiaoHei'}
  4. }

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

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

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

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

参数可以是任何种类的值

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

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

  • 文件 — {file: '路径'}
  • 环境变量 — {env: '环境变量名'}
  • 引用 — {refer: '对象名'}
  • JAVA — {java: '$对象名.方法名(参数1, 参数2)'}
    还可以更多吗?

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

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

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

实现一个扩展接口

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

  1. package nutz.demo.ioc.book;
  2. import org.nutz.ioc.IocMaking;
  3. import org.nutz.ioc.ValueProxy;
  4. import org.nutz.ioc.ValueProxyMaker;
  5. import org.nutz.ioc.meta.IocValue;
  6. import org.nutz.lang.Lang;
  7. public class ScanValueProxyMaker implements ValueProxyMaker {
  8. public ValueProxy make(IocMaking ing, IocValue iv) {
  9. if ("scan".equals(iv.getType())) {
  10. final String address = iv.getValue().toString();
  11. return new ValueProxy() {
  12. public Object get(IocMaking ing) {
  13. // 根据 address 创建一个对象
  14. throw Lang.noImplement();
  15. }
  16. };
  17. }
  18. return null;
  19. }
  20. public String[] supportedTypes() {
  21. return new String[]{"scan"};
  22. }
  23. }

添加到 Ioc 容器中

  1. Ioc2 ioc = new NutIoc(new JsonLoader("path/path/name.js"));
  2. ioc.addValueProxyMaker(new ScanValueProxyMaker());
  3. // 下面,你就可以正常使用 Ioc 接口了

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

本页面的文字允许在知识共享 署名-相同方式共享 3.0协议GNU自由文档许可证下修改和再使用。

原文: http://nutzam.com/core/ioc/injecting.html