Lazy loading of multiple aspects targeting woven class
mgechev opened this issue · comments
Problem
In case we lazy-load multiple aspects which aim to alter behavior to already woven target it will not work because we'll check the private flag __woven__
and in case it's set to true
we'll skip further woving.
Solution
A better idea is to keep the __woven__
property Set<Aspect>
so we can push new elements into the set, each time we wove it with another aspect. We can check if the target has been already woven by given aspect by checking if the aspect is into the set, which is an operation with a constant complexity.
With lazy loading, you mean lazy loading bundles with aspects?
Yes, lazy-loaded bundles which have definition of aspects.
Will have a look in the coming days if I can help you with that.
Going to take a swing at this one.
I created an Angular CLI example with lazy loading. I have an AppService
in the main bundle together with a simple LoggerAspect
.
import {beforeMethod, Wove, Metadata} from 'aspect.js';
class LoggerAspect {
@beforeMethod({
classNamePattern: /^AppService/,
methodNamePattern: /^(world)/
})
invokeBeforeMethod(meta: Metadata) {
console.log(`Inside of the logger. Called ${meta.className}.${meta.method.name}.`);
}
}
I created a lazy loaded bundle with a second logger aspect on the same AppService
.
import {beforeMethod, Wove, Metadata} from 'aspect.js';
class Logger2Aspect {
@beforeMethod({
classNamePattern: /^AppService/,
methodNamePattern: /^(world)/
})
invokeBeforeMethod(meta: Metadata) {
console.log(`Inside of logger 2. Called ${meta.className}.${meta.method.name}.`);
}
}
When I navigate to the route with the lazy bundle, it successfully attaches the aspect to the AppService
, the controller calls appService.world()
, and both loggers print their message. So I don't think we'd have to do anything for this anymore.
I've put it on GitHub in the lazy-aspect repository. Just check it out, install the dependencies and run npm start
.
Both routes are being lazy loaded (Home
and About
). Open the developer tools and take a look when at the home page. It has just one logger aspect and calls the AppService.world()
method.
Inside of `before` logger. Calling AppService.world.
world
Navigate to the About
page. It attaches a second after
logger aspect and also calls the AppService.world()
method.
Inside of `before` logger. Calling AppService.world.
world
Inside of the lazy loaded `after` logger. Called AppService.world.
Thanks for looking into it!