I am in the process of building a dependency injection system for a something that passes a varargs of "Object" through a series of classes that all implement some "execution" method backed by an interface.
class SomeProcessorComponent : AbstractProcessor {
@Override
fun execute(varag objects : Object) : Unit {
}
}
This system works well enough, but it has a really verbose way of pulling dependencies from objects, using some Utility in each class to look at objects and find class instances. These could either be optional or required to be in objects and when a required instance is missing, an Exception will be thrown.
This is an example of how this might look.
class SomeProcessorComponent : AbstractProcessor {
@Override
fun execute(varag objects : Object) : Unit {
val thingOne = Util.require(objects, SomeClass::class.java)
if(null == thingOne) {
throw SomeException
}
val thingTwo = Util.get(objects, SomeOtherClass::class.java)
val thingThree = Util.require(objects, SomeThirdClass::class.java)
if(null == thingThree) {
throw SomeException
}
}
}
As you might imagine, this can become quite verbose especially when classes have a lot of required dependencies.
My initial solution to this is to build out a DI system that essentially defines the scope of execute as a class with annotations that denote whether a field should be required, I imagine it would look something like this.
class SomeProcessorComponent : AbstractProcessor {
@Override
class Scope {
@Required
val thingOne: SomeClass
val thingTwo: SomeOtherClass
@Required
val thingThree: SomeThirdClass
}
@Override
fun execute(scope : Scope) : Unit {
//Nothing but business logic
}
}
After some conversations with other developers, I have come to understand that this could be fairly inefficient due to having to use Reflection to get the annotation metadata at runtime. I know that currently the Util is using "isAssignableFrom" along with iterating the collection to determine whether the Objects collection has the desired Class. I imagine because I can do all of this processing in one pass I should save some overhead in that regard at least.
Is it actually more expensive to check field annotations than to do this, or is there a better method I'm not seeing?
Also, as a bonus question I know that my @Override on the class field is not actually possible, but rather what I wish I was able to do in kotlin, the closes I have come to a syntactically correct solution is to add a Class getter to the Interface and override that pointing to the class itself, if anyone has ideas on a better / correct way to do that I would super appreciate your feedback.
Thank you!
(If you are more familiar with a java solution to this, I'm happy to look at that as well btw :)