为啥都是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!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"

【问题讨论】:

【参考方案1】:

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

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

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

您可能会问,为什么不对所有内容都使用autoload?为什么在绝对需要之前加载任何东西?一个原因是自动加载仅适用于常量。因此,例如,active_support/core_ext 向 Numeric 添加了一堆方法,因此您可以编写像 3.days6.minutes16.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):无法打开流

autoload.php 在那里时丢失

要求(供应商/autoload.php):无法打开流:没有这样的文件或目录

到底为啥要写单元测试

在 Laravel 5 中打开 autoload.php 失败

BaseYii_autoload