VOOZH about

URL: https://deepwiki.com/hypervel/container/6.1-aspect-scanning

⇱ Aspect Scanning | hypervel/container | DeepWiki


Loading...
Menu

Aspect Scanning

Purpose and Scope

This document describes the aspect scanning system in Hypervel Container, specifically the Scanner class and its role in discovering and loading aspects for aspect-oriented programming (AOP). The scanner extends Hyperf's annotation scanner to load aspect configurations from multiple sources and register them with AspectCollector for runtime weaving.

For general AOP concepts and overview, see Aspect-Oriented Programming. For scan configuration details, see Scan Configuration. For how aspects integrate with the container system, see Container System.


Overview

The Scanner class is responsible for:

  • Loading aspect configurations from multiple file sources
  • Merging aspect definitions with proper precedence rules
  • Detecting changes and removals in aspect configurations
  • Dynamically loading/unloading aspects to/from AspectCollector
  • Integrating with Hyperf's aspect loading infrastructure

The scanner operates during the container initialization phase as part of the scanning process documented in Diagram 3 of the high-level architecture.

Sources: src/Scanner.php1-73


Scanner Class Architecture


Sources: src/Scanner.php12 src/Scanner.php7-10


Aspect Loading Process

The Scanner class overrides the loadAspects() method from HyperfScanner to implement custom aspect loading logic. The process follows these steps:

Step 1: Configuration Directory Resolution

The scanner first obtains the configuration directory from ScanConfig:

$configDir = $this->scanConfig->getConfigDir();

If no configuration directory is set, the loading process terminates early.

Sources: src/Scanner.php19-22

Step 2: Load Aspects from Multiple Sources

The scanner loads aspect configurations from three sources in this order:

SourceFile PathPriority (Lowest to Highest)
ProviderConfigClass-based configuration1 (Base)
config.php{configDir}/config.php under aspects key2 (Override)
aspects.php{configDir}/autoload/aspects.php3 (Final)

The loading code:


Sources: src/Scanner.php24-31

Step 3: Configuration Normalization and Merging

The scanner ensures all aspect arrays are valid and properly structured:


Then merges them with proper precedence (later sources override earlier ones):


Sources: src/Scanner.php32-41


Change Detection and Dynamic Updates

The scanner implements change detection to avoid reloading unchanged aspects, which improves performance during cache-enabled scanning.


Handling Removed Aspects

When aspects are removed from configuration, they are cleared from AspectCollector:


This ensures that removed aspects no longer participate in aspect weaving.

Sources: src/Scanner.php43-47

Loading Changed Aspects

For aspects that have been added or modified, the scanner performs the following:

  1. Parse aspect configuration format - Aspects can be specified as:

    • Simple array values: ['AspectClass'] (no priority)
    • Key-value pairs: ['AspectClass' => 100] (with priority)
  2. Load aspect metadata using AspectLoader::load():

    • Instance classes to intercept
    • Annotations to intercept
    • Priority value
  3. Register with AspectCollector using AspectCollector::setAround()


Sources: src/Scanner.php49-71


Aspect Configuration Format

Aspects can be configured in two formats:

Format 1: Simple Array (No Priority)


Format 2: Associative Array (With Priority)


Higher priority values execute first in the aspect chain. If no priority is specified in configuration, the aspect's internal priority (from annotations) is used.

Sources: src/Scanner.php49-56


Integration with AspectCollector

The scanner interacts with AspectCollector through two primary operations:

AspectCollector::clear()

Removes an aspect's metadata from the collector. Called when an aspect is removed from configuration.

AspectCollector::clear($aspect);

Sources: src/Scanner.php46

AspectCollector::setAround()

Registers aspect metadata with the collector. Stores:

ParameterTypeDescription
$aspectstringAspect class name
$classesarrayTarget classes to intercept
$annotationsarrayTarget annotations to intercept
$priorityint|nullExecution priority
AspectCollector::setAround($aspect, $classes, $annotations, $priority);

Sources: src/Scanner.php70


AspectLoader Integration

The scanner delegates aspect metadata extraction to AspectLoader::load(), which returns a tuple:

[$instanceClasses, $instanceAnnotations, $instancePriority] = AspectLoader::load($aspect);

Return Value:

  • $instanceClasses: Array of fully-qualified class names to intercept
  • $instanceAnnotations: Array of annotation class names to intercept
  • $instancePriority: Default priority from aspect annotations (if specified)

This metadata is then used to register the aspect with AspectCollector.

Sources: src/Scanner.php62


Configuration Source Precedence

The aspect configuration follows this precedence order (later overrides earlier):


This allows:

  • Package providers to define default aspects via ProviderConfig
  • Base configuration to override package defaults in config.php
  • Dedicated aspect file to have final say in autoload/aspects.php

Sources: src/Scanner.php41


Usage in Container Initialization

The Scanner is typically used during container initialization as part of the scanning phase (see Diagram 3 in the high-level architecture). The initialization flow:

  1. Container is initialized with DefinitionSource
  2. If scanning is required, ScanConfig is loaded
  3. Scanner instance processes annotations and aspects
  4. loadAspects() is called with cache modification timestamp
  5. Aspects are registered to AspectCollector
  6. Container becomes ready for aspect weaving during runtime

Sources: src/Scanner.php17


Key Classes and Methods Reference

Class/MethodPurposeLocation
ScannerExtends Hyperf scanner with aspect loadingsrc/Scanner.php12
Scanner::loadAspects()Main aspect loading methodsrc/Scanner.php17-72
AspectLoader::load()Extracts aspect metadatasrc/Scanner.php62
AspectCollector::clear()Removes aspect metadatasrc/Scanner.php46
AspectCollector::setAround()Registers aspect metadatasrc/Scanner.php70
ScanConfig::getConfigDir()Returns configuration directorysrc/Scanner.php19
ProviderConfig::load()Loads provider configurationssrc/Scanner.php30

Sources: src/Scanner.php1-73