A proper way to avoid explicit dependency on an API, while still using it if it's present
While I was digging an issue in spring's sources, I found the following:
public abstract class RequestContextHolder {
private static final boolean jsfPresent =
ClassUtils.isPresent("javax.faces.context.FacesContext",
RequestContextHolder.class.getClassLoader());
and then in a method:
if (jsfPresent) {
attributes = FacesRequestAttributesFactory.getFacesRequestAttributes();
}
Where the factory is defined as :
/**
* Inner class to avoid hard-coded JSF dependency.
*/
private static class FacesRequestAttributesFactory
This works obviously, as the inner class is not 'touched' until it is required, and at that moment it is certain that JSF exists on the classpath.
Now, I wonder if this is a good approach to apply in a other cases. For example this method means a compile time dependency.
So, two questions:
- are there any drawbacks to this approach, other than the compile time dependency
- are there better ways to prevent explicit dependency on an API开发者_如何学Python, while still using it.
The code in the question looks quite clean to me. The only way I can think of to avoid compile time dependancy is to use reflection. Try and load the class by name, if present search for the method you are after.
Reflection sounds worse to me.
are there better ways to prevent explicit dependency on an API, while still using it.
Other than creating a wrapper API for the dependency, I don't think so. Creating a wrapper API works well enough when you're only using a small portion of the API.
If you only have a runtime-dependency (your program check the existence of the library and takes different code paths) you simply can code and deliver without the library. The compile-time dependency stays, but Java links the objects at runtime as needed.
精彩评论