Perhaps this is a terrible idea, but if it is then please tell me why and then pretend that it\'s an academic exercise that won\'t see the light of day in production.
The answer is: no.
$provide.decorator
is used to intercept service creation -- that is why it is called from .config
block, when there is still time to configure all services, as none of them has been created. $provide.decorator
basically gets the Provider
of the service and swaps its $get
with newly delivered decorFn
.
$injector
is not like other services. It is created, as the very first step of bootstrapping
an application -- way before app.config
is called. [look at functions: bootstrap
and createInjector
in angular source code]
But hey, you can achieve your goal quite easily by tweaking the source code just a bit :-) Particularly look at function invoke(fn, self, locals)
.
UPDATE I got some inspiration from @KayakDave. You actually do not have to dig in the source-code itself. You can use the following pattern to observe each call to any of $injector
methods:
app.config(['$injector', function ($injector) {
$injector.proper =
{
get : $injector.get,
invoke : $injector.invoke,
instantiate : $injector.instantiate,
annotate : $injector.annotate,
has : $injector.has
}
function getDecorator(serviceName)
{
console.log("injector GET: ", serviceName);
return this.proper.get(serviceName);
}
function invokeDecorator(fn, self, locals)
{
console.log("injector INVOKE: ", fn, self, locals);
return this.proper.invoke(fn, self, locals);
}
function instantiateDecorator(Type, locals)
{
console.log("injector INSTANTIATE: ", Type, locals);
return this.proper.instantiate(Type, locals);
}
function annotateDecorator (fn)
{
console.log("injector ANNOTATE: ", fn);
return this.proper.annotate(fn);
}
function hasDecorator(name)
{
console.log("injector HAS: ", name);
return this.proper.has(name);
}
$injector.get = getDecorator;
$injector.invoke = invokeDecorator;
$injector.instantiate = instantiateDecorator;
$injector.annotate = annotateDecorator;
$injector.has = hasDecorator;
}]);
PLNKR
You can't use the Angular decorator service on $injector. As Artur notes $injector
is a bit different from other services. But we can create our own decorator.
At the code level the issue is that $injector
doesn't have a constructor function- there's no $injectorProvider
.
For example both of these return true:
$injector.has('$location');
$injector.has('$locationProvider')
However, while this returns true:
$injector.has('$injector')
this returns false:
$injector.has('$injectorProvider')
We see the importance when we look at the Angular decorator function:
function decorator(serviceName, decorFn) {
var origProvider = providerInjector.get(serviceName + providerSuffix),
orig$get = origProvider.$get;
origProvider.$get = function() {
var origInstance = instanceInjector.invoke(orig$get, origProvider);
return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
};
}
And
providerSuffix = 'Provider'
So the Angular decorator expects to operate on the service's constructor (serviceName + providerSuffix
). Pragmatically, since we don't have an $injectorProvider
we can't use decorator.
What we can do is override the Angular injector's get function ourselves by replacing the injector's default get
with one that calls the original, Angular defined, get
followed by our function.
We'll apply this to $injector
rather than the nonexistent $injectorProvider
like so:
app.config(['$provide','$injector', function ($provide,$injector) {
// The function we'll add to the injector
myFunc = function () {
console.log("injector called ", arguments);
};
// Get a copy of the injector's get function
var origProvider = $injector,
origGet = origProvider.get;
//Override injector's get with our own
origProvider.get = function() {
// Call the original get function
var returnValue = origGet.apply(this, arguments);
// Call our function
myFunc.apply(this,arguments);
return returnValue;
}
}]);
You'll see the provider being injected is the first augment, so app.value('aValue', 'something');
yields the following log statement:
injector called ["aValueProvider"]
Demo fiddle