AutoLoader - 仅按需加载子例程
package Foo;
use AutoLoader 'AUTOLOAD'; # import the default AUTOLOAD subroutine
package Bar;
use AutoLoader; # don't import AUTOLOAD, define our own
sub AUTOLOAD {
...
$AutoLoader::AUTOLOAD = "...";
goto &AutoLoader::AUTOLOAD;
}
AutoLoader 模块与 AutoSplit 模块和 __END__
标记一起使用,以推迟加载某些子例程,直到使用它们,而不是一次性加载所有子例程。
要使用 AutoLoader,模块的作者必须将要自动加载的子例程的定义放在 __END__
标记之后。(请参阅 perldata。)然后可以手动运行 AutoSplit 模块,将定义提取到各个文件中 auto/funcname.al。
AutoLoader 实现一个 AUTOLOAD 子例程。当在 AutoLoader 的客户端模块中调用一个未定义的子例程时,AutoLoader 的 AUTOLOAD 子例程会尝试在与客户端模块读取位置相关联的文件中找到该子例程。例如,如果 POSIX.pm 位于 /usr/local/lib/perl5/POSIX.pm,AutoLoader 将在 /usr/local/lib/perl5/auto/POSIX/*.al 中查找 perl 子例程 POSIX,其中 .al
文件与子例程同名,不带包。如果存在这样的文件,AUTOLOAD 将读取并评估它,从而(大概)定义所需的子例程。然后,AUTOLOAD 将 goto
新定义的子例程。
一旦此过程针对给定函数完成,该函数即被定义,因此对该子例程的未来调用将绕过 AUTOLOAD 机制。
为了让对象方法查找和/或原型检查在方法尚未定义时也能正常运行,有必要对每个子例程进行“前向声明”(如 sub NAME;
)。请参阅 perlsub 中的“SYNOPSIS”。此类前向声明会创建“子例程存根”,它们是没有代码的占位符。
AutoSplit 和 AutoLoader 模块会自动创建前向声明。AutoSplit 模块会创建一个“索引”文件,其中包含所有 AutoSplit 子例程的前向声明。当“use” AutoLoader 模块时,它会将这些声明加载到其调用者包中。
由于此机制,因此始终 use
AutoLoader 而不是 require
它非常重要。
为了使用 AutoLoader 的 AUTOLOAD 子例程,必须 显式导入它
use AutoLoader 'AUTOLOAD';
一些模块(主要是扩展)提供自己的 AUTOLOAD 子例程。它们通常需要检查一些特殊情况(例如常量),然后回退到 AutoLoader 的 AUTOLOAD 以处理其余情况。
此类模块不应 导入 AutoLoader 的 AUTOLOAD 子例程。相反,它们应该沿着以下思路定义自己的 AUTOLOAD 子例程
use AutoLoader;
use Carp;
sub AUTOLOAD {
my $sub = $AUTOLOAD;
(my $constname = $sub) =~ s/.*:://;
my $val = constant($constname, @_ ? $_[0] : 0);
if ($! != 0) {
if ($! =~ /Invalid/ || $!{EINVAL}) {
$AutoLoader::AUTOLOAD = $sub;
goto &AutoLoader::AUTOLOAD;
}
else {
croak "Your vendor has not defined constant $constname";
}
}
*$sub = sub { $val }; # same as: eval "sub $sub { $val }";
goto &$sub;
}
如果任何模块自己的 AUTOLOAD 子例程不需要回退到 AutoLoader 的 AUTOLOAD 子例程(因为它没有任何 AutoSplit 子例程),那么该模块根本不应该使用 AutoLoader。
使用 my
在包的主块中声明的包词法在使用 AutoLoader 的自动加载子例程中不可见,因为给定范围在 __END__
标记处结束。将此类变量用作包全局变量的模块在 AutoLoader 下无法正常工作。
vars
pragma(请参见 "vars" in perlmod)可以用在这种情况下,作为显式限定包命名空间中所有全局变量的替代方案。使用此 pragma 预先声明的变量对任何自动加载的例程都是可见的(但不幸的是,在包外部不可见)。
你可以通过以下简单方法停止使用 AutoLoader
no AutoLoader;
AutoLoader 在用途上类似于 SelfLoader:两者都延迟加载子例程。
SelfLoader 使用 __DATA__
标记而不是 __END__
。虽然这避免了使用磁盘文件层次结构和为每个加载的例程关联的打开/关闭,但 SelfLoader 在 __DATA__
之后的一次性解析行时启动速度较慢,之后例程被缓存。SelfLoader 还可以处理文件中的多个包。
AutoLoader 仅在请求时才读取代码,在许多情况下应该更快,但需要使用类似 AutoSplit 的机制来创建各个文件。如果在模块源文件中使用 AutoLoader,ExtUtils::MakeMaker 将自动调用 AutoSplit。
有时,确保 AutoLoader 完全加载某个函数可能是必要或有用的。例如,当您需要包装一个函数以注入调试代码时,就是这种情况。在分叉之前强制提前加载代码也有助于尽可能多地利用写时复制。
从 AutoLoader 5.73 开始,您可以使用 AutoLoader::autoload_sub
函数,其中包含要从其 .al 文件加载的函数的全限定名称。行为与您调用函数完全相同,触发常规 AUTOLOAD
机制,但它实际上不会执行自动加载的函数。
Perl 5.002 之前的 AutoLoader 具有略微不同的界面。任何使用 AutoLoader 的旧模块都应更改为新的调用样式。通常,这仅意味着将 require 更改为 use,在需要时添加显式 'AUTOLOAD'
导入,并从 @ISA
中删除 AutoLoader。
在对文件名长度有限制的系统上,与子例程相对应的文件可能比例程本身具有更短的名称。这可能导致文件名冲突。AutoSplit 包在用于拆分模块时会警告这些潜在冲突。
在 @INC
包含相对路径并且程序执行 chdir
的情况下,AutoLoader 可能无法找到自动拆分文件(甚至找到错误的文件)。
SelfLoader - 不使用外部文件的一个自动加载器。
AutoLoader
由 perl5-porters 维护。请将任何问题直接发送到规范邮件列表。但是,任何适用于 CPAN 版本的问题都可以发送给它的维护者。
作者和维护者:Perl5-Porters <[email protected]>
CPAN 版本的维护者:Steffen Mueller <[email protected]>
自 perl5 首次发布以来,此包一直是 perl 核心的一部分。它已单独发布到 CPAN,以便旧安装可以受益于错误修复。
此包具有与 perl 核心相同的版权和许可证
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2011, 2012, 2013
by Larry Wall and others
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of either:
a) the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any
later version, or
b) the "Artistic License" which comes with this Kit.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either
the GNU General Public License or the Artistic License for more details.
You should have received a copy of the Artistic License with this
Kit, in the file named "Artistic". If not, I'll be glad to provide one.
You should also have received a copy of the GNU General Public License
along with this program in the file named "Copying". If not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301, USA or visit their web page on the internet at
http://www.gnu.org/copyleft/gpl.html.
For those of you that choose to use the GNU General Public License,
my interpretation of the GNU General Public License is that no Perl
script falls under the terms of the GPL unless you explicitly put
said script under the terms of the GPL yourself. Furthermore, any
object code linked with perl does not automatically fall under the
terms of the GPL, provided such object code only adds definitions
of subroutines and variables, and does not otherwise impair the
resulting interpreter from executing any standard Perl script. I
consider linking in C subroutines in this manner to be the moral
equivalent of defining subroutines in the Perl language itself. You
may sell such an object file as proprietary provided that you provide
or offer to provide the Perl source, as specified by the GNU General
Public License. (This is merely an alternate way of specifying input
to the program.) You may also sell a binary produced by the dumping of
a running Perl script that belongs to you, provided that you provide or
offer to provide the Perl source as specified by the GPL. (The
fact that a Perl interpreter and your code are in the same binary file
is, in this case, a form of mere aggregation.) This is my interpretation
of the GPL. If you still have concerns or difficulties understanding
my intent, feel free to contact me. Of course, the Artistic License
spells all this out for your protection, so you may prefer to use that.