I am using java ServiceLoader to load the instances of an SPI. ServiceLoader uses the public default no-args constructor to load the service providers.
I want to load the instances using a parameterized constructor instead for my requirements.
Here’s a sample provider interface
package com.myOrg.check.access;
public interface IRuleValidator{
void validate();
}
Sample provider
package com.myModule.myService.check.access;
public class MyRuleValidatorProvider{
private MyDto myDto;
public MyRuleValidatorProvider() {
}
public MyRuleValidatorProvider(MyDto myDto) {
this.myDto = myDto;
}
@Override
void validate() {
//Here I am using this.Dto to validate some rules
}
}
Provider Loader
ServiceLoader<IRuleValidator> loader = ServiceLoader.load(IRuleValidator.class);
while(loader.iterator().hasNext()) {
IRuleValidator myImpl = loader.iterator().next(); // This will load myImpl Variable using default no-args constructor
}
As, shown in Sample Provider, I am using MyDto object to validate some rules but serviceLoader only loads the instances using default no-args constructor whereas I require the one with parameterized constructor.
So, far to overcome this issue I am using something like this:
Provider Loader
// part of a method, which get myDto as an argument
getValidator(MyDto myDto) {
...
ServiceLoader<IRuleValidator> loader = ServiceLoader.load(IRuleValidator.class);
while(loader.iterator().hasNext()) {
IRuleValidator myImpl = loader.iterator().next();
Constructor<?>[] constructors = myImpl.getClass().getDeclaredConstructors();
for (Constructor<?> constructorIter : constructors) {
Class<?>[] parameterTypes = constructorIter.getParameterTypes();
if (parameterTypes.length == 1) {
if (myDto!= null && parameterTypes[0].equals(myDto.getClass())) {
constructor = myImpl.getClass().getConstructor(Class.forName(myDto.getClass().getName()));
} else {
constructor = myImpl.getClass().getConstructor(Class.forName(IMyDto));
}
}
}
}
IRuleValidator newImpl = (IRuleValidator) constructor.newInstance(myDto);
...
}
This works perfectly but in peer review I have got opinions that this is not at all performance friendly. I haven’t got any solution and hence want to know if there is a way to load an instance using parameterized constructor?
What is wrong with my solution? how does it impact the performance and is there any other shortcomings in this approach?