在rails的initialize代码中经常能看到方法 ActiveSupport.on_load
,这个代码是起什么用的引起了我很大的好奇,于是看了看源码,觉得这个功能还是挺好玩而且有用的。
ActiveSupport.on_load
方法为rails提供了一种叫做 lazy_load_hooks的功能,这个功能可以使很多组件在被用到时才被加载,而不是启动即全部加载,这样大大加快了rails app 的启动速度。
lazy_load_hooks的代码很短,只有不到30行,文件名: activesupport-3.2.x/lib/active_suport/lazy_load_hooks.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
代码中会初始化两个Hash变量 @load_hooks
和 @loaded
, @load_hooks
用来存放还没有被执行的blocks, @loaded用来存放已经被加载的载体类。
让我们看看一个ActiveRecord的例子来了解一下lazy_load_hooks的使用方法,在activerecord-3.2.x/lib/active_record/railtie.rb
文件中有很多的initializer块,这些内容在rails启动的时候都会被调用到,像下面这个加载logger的:
1 2 3 |
|
这时候 ActiveSupport.run_load_hooks
还没有执行,所以 on_load方法中@loaded[:active_record]
是空的,里面的each循环不会执行,执行到的是
1
|
|
把block放进@load_hooks[:active_record]
里面去,所以在railtie里的所有on_load的block都先被存放了起来。
最后的执行是在activerecord-3.2.x/lib/active_record/base.rb
文件中,代码的最下面执行到了run_load_hooks
方法,
1
|
|
当加载ActiveRecord::Base执行到该方法,并且把ActiveRecord::Base
作为载体类传了进去。所以在ActiveRecord::Base被加载的时候所有的lazy_load block才会被执行到,同样的其他模块中的railite里也有很多lazy_load block,他们都是在需要的时候才被执行,这样又节省运行资源,又节省启动时间,我们自己写Gem的时候也可以用上啦。