I recently asked a question about some code of mine where I used reflection and one who wanted to help me with this problem mentioned that I shouldn't use reflection like this and that there is a better way doing it.
So I have an Interface for searching in external Systems:
public interface ReferenceController {
public Map<String, ReferenceElement> searchElements(String searchField, List<String> searchItems, SystemStage systemStage) throws Exception;
public String getStateMapping(String value);
public Boolean isAvailable(SystemStage systemStage) throws Exception;
}
And I have an ENUM where I declare which external systems I have and how their class is named which uses this interface. So if any other programmer want's to implement a new external system he has only to fill the interface and put two values in this ENUM and tada it should work.
So the part where I used the reflection was
public static void performSingleSearch(ReferenceSystem referenceSystem, String searchField, List<String> searchValues, SystemStage systemStage) throws Exception {
if(!isAvailable(referenceSystem, systemStage)) return;
Map<String, ReferenceElement> result = new HashMap<>();
try {
Class<?> classTemp = Class.forName(referenceSystem.getClassname());
Method method = classTemp.getMethod("searchElements", String.class , List.class, SystemStage.class);
result = (Map<String, ReferenceElement>) method.invoke(classTemp.newInstance(), searchField, searchValues, systemStage);
} catch (Exception e) {
return;
}
if(result != null) orderResults(result, referenceSystem);
}
In the ENUM ther is a function getClassname, which answers with the fqcn. The Enum looks like this:
public enum ReferenceSystem {
UCMDB (refSystems.ucmdb.UcmdbFunctions.class),
PROIPS (refSystems.proips.ProIPSFunctions.class),
KV (refSystems.kv.KvFunctions.class),
FISERVICE(refSystems.fiservice.FiServiceFunctions.class),
COMMAND (refSystems.command.CommandFunctions.class),
FII (refSystems.fii.FiiFunctions.class);
private Class<?> clazz;
private ReferenceSystem(Class<?> controllerClass) {
this.clazz = controllerClass;
}
public String displayName() {
ResourceBundle bundle = ResourceBundle.getBundle("EnumI18n", Locale.GERMAN);
return bundle.getString(toString());
}
public String localizedDisplayName(Locale locale) {
ResourceBundle bundle = ResourceBundle.getBundle("EnumI18n", locale);
return bundle.getString(toString());
}
public Class<?> getClassname() { return clazz; }
}
I've already altered it according to @jhamon 's answer.
But I get an error when I try
classTemp.newInstance().searchElemets(...)
Because it doesn't know about searchElemts().
So the other user here said there would be the possibility of implementing the interface into the enum and then I don't have to reflect. Could anyone tell me how, because I don't know and I don't know where or what to search. Thanks
It seems all your search engines have a common method searchElements
and it's defined in the interface
Knowing that, why not call this method directly, and not by looking for it first. -> no more reflection to find the method.
public interface ReferenceController {
public Map<String, ReferenceElement> searchElements(String searchField, List<String> searchItems, SystemStage systemStage) throws Exception;
public String getStateMapping(String value);
public Boolean isAvailable(SystemStage systemStage) throws Exception;
}
Instead of storing the class name as String in the Enum, store the .class -> no more reflection to find the class.
public static void performSingleSearch(ReferenceSystem referenceSystem, String searchField, List<String> searchValues, SystemStage systemStage) throws Exception {
if(!isAvailable(referenceSystem, systemStage)) return;
Map<String, ReferenceElement> result = new HashMap<>();
try {
Class<?> classTemp = referenceSystem.getClazz();
result = ((ReferenceController) classTemp.newInstance()).searchElements(searchField, searchValues, systemStage);
} catch (Exception e) {
return;
}
if(result != null) orderResults(result, referenceSystem);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.