NutIoc的执行过程
越来越多人阅读Nutz的源码,很是欣慰.
首先,什么是Ioc呢? Ioc本质上就是一个有状态的Map
先上一段代码,通过一个js配置一个Ioc容器,并获取一个bean
public static void main(String[] args) {
IocLoader loader = new JsonLoader("ioc.js");
Ioc ioc = new NutIoc(loader);
Pet pet = ioc.get(Pet.class, "pet");
System.out.println(pet.getName());
}
ioc的js配置文件(ioc.js,名字是随意的)
var ioc = {
pet : {
type : "net.wendal.test.Pet",
fields : {
name : "wendal"
}
}
}
Ioc第一步,读取bean的配置信息 : 任何bean,都有其对应的配置信息,都必须通过一个IocLoader来读取
IocLoader loader = new JsonLoader("ioc.js");
从ioc.js中读取配置信息
ioc.js中,有个前缀”var ioc =“字符串,这是为了方便Eclipse进行语法提示而已, 写不写都可以,但只能写这个字符串,这是JsonLoader所约定的
ioc.js仅定义了一个bean,名叫pet,任何bean都必须有唯一的名字, 因为Ioc实质上就是一个Map
,其中的key就是bean的名字 这个bean的信息,会保存在IocObject中, 注意,这是配置信息, 真正的对象并未生成
第二步,生成Ioc容器
Ioc ioc = new NutIoc(loader);
//只是进行一些必要的初始化,并完成与Aop的连接点
第三步,获取对象
Pet pet = ioc.get(Pet.class, "pet");
这时候, 具体的Pet实例要准备生成了
首先,需要生成IocLoading –> createLoading()
然后通过 iocloader的load方法,拿到IocObject, 即bean的配置信息
接着IocMaker实例,通过IocObject和IocMaking实例, 新建实际的bean对象
下一步,就是为刚刚生成的bean注入字段, 因为当前的bean对象,仅仅是new之后的全新状态
收尾的一步, 看看这个bean,是否为单例,是否需要保存到app作用域–大部分的bean都是单例的
// 每一作用域(IocContext),都管理着符合其生命周期的bean – 默认情况下,bean都是app作用域的,单例的
// 如果bean还定义了create/fetch等IocEvent的话,那么,这时候也会触发
将bean作为返回值,交给用户
==补充一句,整个流程,等价于:
Pet pet = new Pet();
pet.setName("wendal");
延伸一下:
1. 注解式Ioc
IocLoader loader = AnnotationIocLoader("net.wendal.test");
//而bean需要定义为
@IocBean
public class Pet {
@Inject("wendal") //这里只是演示,正常情况下,不可能这样写死
private String name;
}
就是注解–>IocObject这一步
2. MVC中的Ioc 是通过IocProvider提供的. 不妨看看JsonIocProvider的代码:
public class JsonIocProvider implements IocProvider {
public Ioc create(NutConfig config, String[] args) {
//可以看到,就跟我们在main中写的差不多呢
return new NutIoc(new JsonLoader(args), new ScopeContext("app"), "app");
}
}
然后,是谁调用了ioc.get(XXX.class, “xxx”)呢? 是ModuleProcessor,摘取一部分源码看看:
Object obj;
/*
* 如果 Ioc 容器实现了高级接口,那么会为当前请求设置上下文对象
*/
if (ioc instanceof Ioc2) {
reqContext = new RequestIocContext(ac.getRequest());
SessionIocContext sessionContext = new SessionIocContext(Mvcs.getHttpSession());
IocContext myContext = new ComboContext(reqContext, sessionContext);
Mvcs.setIocContext(myContext);
//看上去比main方法里面写得复杂,事实上还是一个样!!多个上下文而已!
obj = ((Ioc2) ioc).get(moduleType, injectName, myContext);
}
/*
* 否则,则仅仅简单的从容器获取
*/
else
obj = ioc.get(moduleType, injectName);
延展阅读: Mirror类,封装了Nutz中大部分的反射操作
blog comments powered by Disqus