为啥都是autoload,load_all!并要求所有在active_support.rb 中使用?
Posted
技术标签:
【中文标题】为啥都是autoload,load_all!并要求所有在active_support.rb 中使用?【英文标题】:Why are autoload, load_all! and require all used in active_support.rb?为什么都是autoload,load_all!并要求所有在active_support.rb 中使用? 【发布时间】:2010-11-03 23:51:15 【问题描述】:我查看了active_support.rb
,试图了解它使用的加载过程。它使用三种加载方式:load_all!
、autoload
和require
。
为什么要在同一个文件中使用三种不同的加载方式?
module ActiveSupport
def self.load_all!
[Dependencies, Deprecation, Gzip, MessageVerifier, Multibyte, SecureRandom, TimeWithZone]
end
autoload :BacktraceCleaner, 'active_support/backtrace_cleaner'
autoload :Base64, 'active_support/base64'
autoload :BasicObject, 'active_support/basic_object'
autoload :BufferedLogger, 'active_support/buffered_logger'
autoload :Cache, 'active_support/cache'
autoload :Callbacks, 'active_support/callbacks'
autoload :Deprecation, 'active_support/deprecation'
autoload :Duration, 'active_support/duration'
autoload :Gzip, 'active_support/gzip'
autoload :Inflector, 'active_support/inflector'
autoload :Memoizable, 'active_support/memoizable'
autoload :MessageEncryptor, 'active_support/message_encryptor'
autoload :MessageVerifier, 'active_support/message_verifier'
autoload :Multibyte, 'active_support/multibyte'
autoload :OptionMerger, 'active_support/option_merger'
autoload :OrderedHash, 'active_support/ordered_hash'
autoload :OrderedOptions, 'active_support/ordered_options'
autoload :Rescuable, 'active_support/rescuable'
autoload :SecureRandom, 'active_support/secure_random'
autoload :StringInquirer, 'active_support/string_inquirer'
autoload :TimeWithZone, 'active_support/time_with_zone'
autoload :TimeZone, 'active_support/values/time_zone'
autoload :XmlMini, 'active_support/xml_mini'
end
require 'active_support/vendor'
require 'active_support/core_ext'
require 'active_support/dependencies'
require 'active_support/json'
I18n.load_path << "#File.dirname(__FILE__)/active_support/locale/en.yml"
【问题讨论】:
【参考方案1】:我不知道为什么 Rails 使用三种不同的加载方法(实际上是两种 - 见下文)。但总的来说,我知道为什么有人会这样做。
Require
表示“立即加载”。 autoload
表示“在需要使用时加载它”。使用两者的通常原因是您有一些文件,您几乎认为这些文件将在每个程序调用中使用;和其他可选的。例如,在没有使用过时方法的 Rails 应用程序中,您永远不需要Deprecation
;那么为什么要通过加载该文件来减慢初始设置的速度呢?
在其他情况下,您可能会区分程序执行早期需要的文件和可以等待的文件。例如,在第一个请求到来之前,您不太可能需要 Gzip
。因此,通过使用自动加载,您可以缩短初始设置的一些时间,但代价是第一个请求会稍微变慢。
您可能会问,为什么不对所有内容都使用autoload
?为什么在绝对需要之前加载任何东西?一个原因是自动加载仅适用于常量。因此,例如,active_support/core_ext
向 Numeric 添加了一堆方法,因此您可以编写像 3.days
、6.minutes
和 16.seconds.ago
这样的代码。 3.days
中没有常量,因此您无法在该表达式上触发自动加载。 (而且你不能自动加载Numeric
,因为已经加载了基类——它只是你要添加的扩展。)
最后,这个类实际上并没有使用三种加载方法;它使用两个,并提供一个(某种)。 load_all!
被Rails::Initializer
用于
# Preload all frameworks specified by the Configuration#frameworks. # Used by Passenger to ensure everything's loaded before forking and # to avoid autoload race conditions in JRuby.
我不知道细节,也不知道为什么要预加载这些特定模块(而不是其他模块)。但由于这是为了支持特定环境,您可以了解为什么它可能需要与默认加载机制分开的代码。
【讨论】:
【参考方案2】:autoload
ruby 方法可用于将常量与文件名相关联,该文件名将在您第一次引用该常量时加载。这使您不必在启动时加载整个框架。
看起来load_all!
方法是从rails initializer.rb
调用的,用于预加载所有配置为预加载的框架。这通过调用每个框架load_all!
方法来工作,该方法只是引用一个常量数组......这将触发自动加载。
根据initializer.rb
中的cmets对于preload_frameworks
...
# Preload all frameworks specified by the Configuration#frameworks.
# Used by Passenger to ensure everything's loaded before forking and
# to avoid autoload race conditions in JRuby.
require
用于加载特定框架所需的核心文件。
【讨论】:
以上是关于为啥都是autoload,load_all!并要求所有在active_support.rb 中使用?的主要内容,如果未能解决你的问题,请参考以下文章
要求(供应商/autoload.php):无法打开流:没有这样的文件或目录