10

我正在寻找active_support.rb尝试了解它使用的加载过程。它使用三种加载方法load_all!autoloadrequire。为什么在同一个文件中使用三种不同的加载方式?

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"
4

2 回答 2

16

我不知道为什么 Rails 使用三种不同的加载方法(实际上是两种 - 见下文)。但我知道,总的来说,为什么有人会。

Require意思是“立即加载”。autoload意思是“当你需要使用它时加载它”。使用两者的通常原因是您有一些文件,您几乎认为这些文件将在每个程序调用中使用;和其他可选的。例如,在没有使用过时方法的 Rails 应用程序中,您永远不需要Deprecation; 那么为什么要通过加载该文件来减慢初始设置呢?

在其他情况下,您可能会区分程序执行早期需要的文件和可以等待的文件。例如,Gzip在第一个请求到来之前您可能不需要。因此,通过使用自动加载,您可以减少初始设置的一些时间,但代价是第一个请求会稍微变慢。

您可能会问,为什么不只autoload用于所有内容?为什么在绝对需要之前加载任何东西?一个原因是自动加载仅适用于常量。因此,例如,active_support/core_ext向 Numeric 添加一堆方法,这样您就可以编写类似3.days6.minutes16.seconds.ago. 中没有常量3.days,因此您无法在该表达式上触发自动加载。(而且你不能 autoload 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.

我不知道细节,也不知道为什么要预加载这些特定模块(而不是其他模块)。但由于这是为了支持特定环境,您可以看到为什么它可能需要与默认加载机制分开的代码。

于 2009-06-18T16:32:28.793 回答
1

autoloadruby 方法可用于将常量与将在您第一次引用该常量时加载的文件名相关联。这使您不必在启动时加载整个框架。

看起来该load_all!方法是从 rails 调用的initializer.rb,用于预加载所有配置为预加载的框架。这通过调用每个框架load_all!方法来工作,该方法只是引用一个常量数组......这将触发自动加载。

根据initializer.rb评论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是为特定框架加载核心所需的文件。

于 2009-06-18T16:33:29.340 回答