定义:
惰性加载:一个类只有在使用的时候才include(require)进来。
优点:减少内存占用,提高系统整体速度。
在tp3.2.3的时候,核心的文件是统一加载的。
在think.class.php的start方法中可以看到:
foreach ($mode['core'] as $file){
if(is_file($file)) {
include $file;
if(!APP_DEBUG) $content .= compile($file);
}
}而变量$mode为应用模式:
$mode = include is_file(CONF_PATH.'core.php')?CONF_PATH.'core.php':MODE_PATH.APP_MODE.'.php';
所以一般情况下,他是读取ThinkPHP/Mode目录下的common.php这个文件,该文件返回一个数组,其中便包含有core这个成员。
return array(
// 配置文件
'config' => array(...),
// 别名定义
'alias' => array(...),
// 函数和类文件
'core' => array(
THINK_PATH.'Common/functions.php',
COMMON_PATH.'Common/function.php',
CORE_PATH . 'Hook'.EXT,
CORE_PATH . 'App'.EXT,
CORE_PATH . 'Dispatcher'.EXT,
//CORE_PATH . 'Log'.EXT,
CORE_PATH . 'Route'.EXT,
CORE_PATH . 'Controller'.EXT,
CORE_PATH . 'View'.EXT,
BEHAVIOR_PATH . 'BuildLiteBehavior'.EXT,
BEHAVIOR_PATH . 'ParseTemplateBehavior'.EXT,
BEHAVIOR_PATH . 'ContentReplaceBehavior'.EXT,
),
// 行为扩展定义
'tags' => array(...),
);
但是在tp5.0,包括这些核心文件都使用了懒惰加载,也就是使用到了才加载进来。
主要策略是:
1、自动加载类先行
2、核心文件配置在一个文件中
加载类先行:由于核心文件也使用了懒惰加载,因此在框架运行起来之前,自动加载方法必须依据被注册好。因此可以看到在tp5中,自动加载方法单处成一个loader.php类。并且在base.php中可以看到,loader.php是第一个被加载进来的类方法。
核心文件配置:同tp3.2.3一样,tp5的核心文件也配置在一个文件中,不过现在不是通过应用模式了,而是直接定义在classmap.php中,该文件同样会返回一个包含核心文件的数组。
// 注册自动加载机制
public static function register($autoload = '')
{
// 注册系统自动加载
spl_autoload_register($autoload ?: 'think\\Loader::autoload');
// 注册命名空间定义
self::addNamespace([
'think' => LIB_PATH . 'think' . DS,
'behavior' => LIB_PATH . 'behavior' . DS,
'traits' => LIB_PATH . 'traits' . DS,
]);
// 加载类库映射文件
self::addClassMap(include THINK_PATH . 'classmap' . EXT);
...
}
addClassMap方法会把classmap.php返回的数组合并到self:$map中,方便autoload方法的查询使用。 当有一个类文件还没有包含进来的时候,Loader:autoload方法就会被调用:
// 自动加载
public static function autoload($class)
{
// 检测命名空间别名
if (!empty(self::$namespaceAlias)) {
$namespace = dirname($class);
if (isset(self::$namespaceAlias[$namespace])) {
$original = self::$namespaceAlias[$namespace] . '\\' . basename($class);
if (class_exists($original)) {
return class_alias($original, $class, false);
}
}
}
//这里使用了self::$map变量
if (!empty(self::$map[$class])) {
// 类库映射
include self::$map[$class];
} elseif (...) {
} else {
...
}
return true;
}
综上,tp5.0使用了懒惰加载,虽然单单在这一点上,系统的性能提升不明显(tp3.x性能实际上已经胜过其他框架),因为核心文件不管在tp3.2.3还是tp5中,大多数情况都需要全部包含进来的,晚包含和早包含都得包含的。但是胜在什么地方呢?
1、遵守规范(PSR-4)
2、代码更加简洁
1、遵循规范。限制了自由度,换来了规范化和工程化。对于底层架构,遵守规范还是比较好的。比如如果两个不同框架使用了不同的规范,那么我为他开发第三方库的时候,可能就需要读取两种不同的规范。但是如果他们都使用同一种规范的话,那么我了解这一种规范后,同样也可以用于另外一个框架,这就方便多了。对于规范,我觉得用到才查吧~~~
2、代码更加简洁
核心文件代码不需要额外代码实现,直接让自动加载方法加载便可。