2009-06-18 2 views
10

Я искал active_support.rb, чтобы попытаться понять процесс загрузки, который он использует. Он использует три метода загрузки: load_all!, autoload и require. Зачем использовать три разных способа загрузки в одном файле?Почему автозагрузка, load_all! и требуют, чтобы все они использовались в active_support.rb?

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" 

ответ

16

Я не знаю точно, почему Rails использует три разных метода загрузки (фактически два - см. Ниже). Но я знаю, в общем, почему кто-то может.

Require означает «загрузить это прямо сейчас». autoload означает «загрузить это, когда вам нужно его использовать». Обычная причина использования обоих заключается в том, что у вас есть некоторые файлы, которые вы в значительной степени предполагаете, будут использоваться в каждом вызове программы; и другие, которые являются необязательными. Например, в приложении Rails, которое не использует устаревшие методы, вам никогда не понадобится Deprecation; поэтому зачем замедлять первоначальную настройку, загружая этот файл?

В других случаях вы можете различать файлы, которые понадобятся на ранней стадии выполнения программы, и файлы, которые могут подождать. Например, вам вряд ли понадобится Gzip, пока не поступит первый запрос. Таким образом, используя автозагрузку, вы можете отрезать некоторое время от первоначальной настройки за счет небольшого замедления для первого запроса.

Вы могли бы спросить, ну, почему бы просто не использовать autoload для всего? Зачем загружать что-нибудь прежде, чем это будет необходимо? Одна из причин заключается в том, что автозагрузка работает только для констант. Так, например, active_support/core_ext добавляет кучу методов в числовой, поэтому вы можете написать код, например 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. 

Я не знаю подробностей, и я не знаю, почему эти конкретные модули предварительно загружаются (а не другие). Но поскольку это предназначено для поддержки определенных сред, вы можете понять, почему для этого может потребоваться отдельный код отдельно от механизма загрузки по умолчанию.

1

Метод ruby ​​autoload можно использовать для связывания константы с именем файла, которое будет загружено при первом обращении к указанной константе. Это не позволяет загружать всю структуру при запуске.

Похоже, что метод load_all! вызывается из рельсов 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 является загрузки ядра, необходимые файлы для конкретной структуры.