ActiveSupport autoload源码分析
来源:互联网 发布:北平无战事知乎 编辑:程序博客网 时间:2024/05/29 18:36
在我们平常看一些gem或者开发中autoload用的还是很多的,闲的没事总结下这个方法的内部实现,分析一下源码。
在我们看源码的时候经常看到如下代码:
module ActiveRecord extend ActiveSupport::Autoload autoload :Attribute autoload :Base autoload :Callbacks autoload :Core autoload :ConnectionHandling autoload :CounterCache autoload :DynamicMatchers autoload :Enum autoload :InternalMetadata autoload :Explain autoload :Inheritance autoload :Integration autoload :Migration
那么在这里的autoload到底做了什么事??
看源码:
module Autoload def self.extended(base) # :nodoc: base.class_eval do @_autoloads = {} @_under_path = nil @_at_path = nil @_eager_autoload = false end end def autoload(const_name, path = @_at_path) unless path full = [name, @_under_path, const_name.to_s].compact.join("::") path = Inflector.underscore(full) end if @_eager_autoload @_autoloads[const_name] = path end super const_name, path end
我们来分析下这个方法取上面的ActiveRecord来分析:
第一步:
extend ActiveSupport::Autoload
这里相当把ActiveSupport::Autoload的方法引入进来了,相当于类方法,具体细节看extend的用法,不多说,好,继续向下看。
第二步:
autoload :Attribute
这里相当于调用了
ActiveRecord.autoload(:Attribute)
再来细看这个方法,这个方法接入了两个参数通过上面分析我们知道:
const_name=:Attributepath = @_at_path = nil
这里的@_at_path是extend钩子方法extended调用初始化的值,继续向下看:
unless path full = [name, @_under_path, const_name.to_s].compact.join("::") path = Inflector.underscore(full) end
path=nil这个方法会执行,我们先来确认几个值。
name = self.name = ActiveRecord.name = "ActiveRecord"@_under_path = nilconst_name.to_s = :Attribute.to_s = "Attribute"
好了我么知道这几个值那就简单了,把这几个值带到full里面执行下
full = ["ActiveRecord", nil, "Attribute"].compact.join("::") = "ActiveRecord::Attribute"
继续向下看:
path = Inflector.underscore(full)
其实是调用了Inflector里面的underscore方法只是把full传进来了,看源码:
def underscore(camel_cased_word) return camel_cased_word unless camel_cased_word =~ /[A-Z-]|::/ word = camel_cased_word.to_s.gsub('::'.freeze, '/'.freeze) word.gsub!(/(?:(?<=([A-Za-z\d]))|\b)(#{inflections.acronym_regex})(?=\b|[^a-z])/) { "#{$1 && '_'.freeze }#{$2.downcase}" } word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2'.freeze) word.gsub!(/([a-z\d])([A-Z])/, '\1_\2'.freeze) word.tr!("-".freeze, "_".freeze) word.downcase! word end
这个方法很长,不具体分析了,其实这个方法具体就做了一件事,就是把我们的full转化为我们需要的路径。
上面的
full = "ActiveRecord::Attribute"
经过这个方法转化后
"active_record/attribute"
继续向下看:
if @_eager_autoload @_autoloads[const_name] = path end super const_name, path end
@_eager_autoload = nil 所以最后只执行了:
super const_name, path
相当于:
super :Attribute, ""active_record/attribute""
其实分析到这里已经结束了,这里的super相当于调用了kernel下的autoload方法,这个是ruby的方法,执行这个方法成功返回nil,失败异常,简单提一下,其实就是懒加载,调用这个方法其实并没有require,只是把路径加到内存中了,当我们调用的时候回才去加载。
下面还需要提出一个小问题:为什么rails重写了ruby的这个方法而不是直接调用?
其实这个方法的目的就要还是为了Rails的约束,比如
A::B => rails 当然根据这个名字找到a/b文件,所以重写了这个方法
但是ruby不是这样的,没有这个规范,只要有路径就能找到,不符合rails的约束,人家当然要重写了。
- ActiveSupport autoload源码分析
- ActiveSupport eager_autoload源码分析
- PHP autoload性能分析
- autoload之composer分析
- CodeIgniter中autoload('database')源码部分
- Extjs4源码解释TreeStore的autoLoad无效
- PMON中autoload自动加载操作系统代码分析
- ActiveSupport源代码研究之 ActiveSupport::Concern
- autoload机制
- TinyMVC-Autoload
- Ruby autoload
- 94. autoload
- composer autoload
- CI框架源码阅读笔记9 CI的自动加载机制autoload
- CI框架源码阅读笔记9 CI的自动加载机制autoload
- Class: ActiveSupport::Multibyte::Chars:
- 强大的 ActiveSupport::Notifications
- ActiveSupport 工具函式庫
- 剖析 epoll ET/LT 触发方式的性能差异误解
- 集合划分问题
- USB命令(请求)和USB描述符详细
- Hibernate(一):了解Hibernate
- 字符编码 UTF-8、unicode、ASCII
- ActiveSupport autoload源码分析
- mac 苹果 安装git 及git常用命令示例
- mac 苹果电脑 本地php环境搭建
- mysql大数据迁移,简单步骤
- mac osx系统下 apache-php-mysql 简单配置 & 远程登录lnmp服务器简单操作
- 中文乱码问题汇总
- Sublime3 packagecontrol及插件安装
- Bootstrap 加载不出来解决
- SQL中使用WITH AS提高性能-使用公用表表达式(CTE)简化嵌套SQL