DI Container & @inject (& property injection)
- juzna.cz
- Member | 248
New DI Container looks great, but I still miss some features which have been available in Java world for some time already, e.g. in Spring framework or EJB. The most obvious for me is @Inject annotation, which makes it even easier to define services.
In Java, I've got two ways, which translated into PHP would look like:
1/ setter injection – cleaner, longer
class X {
protected $a;
/** @inject */
public function setA(\Ns1\A $a) { $this->a = $a; }
}
2/ property injection – shorter, not that clean
class X {
/**
* @var \Ns1\A
* @inject
*/
protected $a;
}
Container looks for methods/properties with @inject
annotation and automatically injects them.
I don't need to write too much code, and in case of setter injection I don't
need to specify setA()
in config file.
Wouldn't it be nice to have such support as well?
- David Grudl
- Nette Core | 8228
I believe that this goes against the spirit od DI. No class except the DI container should not know about DI.
- Patrik Votoček
- Member | 2221
David Grudl wrote:
I believe that this goes against the spirit od DI. No class except the DI container should not know about DI.
I believe too… :-)
- juzna.cz
- Member | 248
Thanks for your comments.
David Grudl wrote:
I believe that this goes against the spirit od DI. No class except the DI container should not know about DI.
Somehow you're right, but I still consider it an appropriate way. When defining a service/class, you specify in constructor what it needs. Setter with @inject can be additional info from the class saying “and in addition to what I said in constructor, I also need this (these)”.
It says nothing explicitly about container, the class just says what it wants. Container just understands it and behaves appropriately.
Property injection is just a convenient way, so that one doesn't have to write a setter.
Magic?
The magic ™ starts with private/protected methods/properties, as they are not accessible normally and thus cannot be injected by normal user code. This surely goes against the spirit of DI (but just makes life easier once you get used to container so much that you forget it).
Outcome
I'll try to implement it and provide some examples, so we'll see how it would work in real life.
- HosipLan
- Moderator | 4668
It's pretty obviouse how it works, but as it was said, this doesn't belong to DI. Because you're moving the configuration from config/extensions to code. That is not OK. It may be handy, but it's not OK.
As I've said, you can implement this in
CompilerExtension::beforeCompile()
and provide it as an addon to
Nette, if you wish :)
- pekelnik
- Member | 462
I agree with juzna that the @inject
annotations are basically the same information as typehint in the
constructor.
I agree with hosiplan that we are moving configuration to code.
Is it bad?
I thing not really.
We are already using annotations for many “configuration” purposes – so why not for mark injected dependecies.
- David Grudl
- Nette Core | 8228
What is the difference between required parameter in constructor and setter with @inject annotation?