ResolverUtil is used to locate classes that implement an interface or extend a given base
class. It does this in two different ways. The first way is by accessing the
Thread.getContextClassLoader Context ClassLoader and attempting to discover the set
of URLs that are used for classloading. The second mechanism uses the
ServletContext to discover classes under
/WEB-INF/classes/ and jar files under
/WEB-INF/lib/ .
The first mechanism is generally preferred since it can usually discover classes in more
locations, but it requires that the context class loader be a subclass of
URLClassLoader .
Most containers use class loaders that extend URLClassloader, but not all do. Since accessing
resources through the ServletContext is mandated to work in the Servlet specification this should
work in all containers.
Since scanning all classpath entries and/or jars under
/WEB-INF/lib/ can take a
non-trivial amount of time, it is possible to filter the set of locations and packages that
are examined. This is done by supplying Collections of filter patterns. The
locationFilters are used to match the locations (directories, jar files, etc.) examined.
The
packageFilters restricts the set of classes loaded by package. In both cases a
simple sub-string match is used. For example if location patterns of ["project1", project2"] are
supplied, you would see the following:
lib/project1/dependencies/dep1.jar -> scanned
lib/project3/dependencies/dep79.jar -> not scanned
WEB-INF/lib/project1-web.jar -> scanned
WEB-INF/classes -> not scanned
lib/project2/project2-business.jar -> scanned
If no location filters are supplied, all discovered locations will be scanned for classes.
If no package filters are supplied, all classes discovered will be checked.
At first glance it may seem redundant to provide the class type being searched for at
instantiation time, and again when invoking one of the
load() methods. However,
this allows for certain usages that would not otherwise be possible. For example, the
following is used to find all collections that support ordering of some kind:
ResolverUtil<Collection> resolver = new ResolverUtil<Collection>();
resolver.loadImplementationsFromContextClassloader(List.class);
resolver.loadImplementationsFromContextClassloader(SortedSet.class);
Set<Class<? extends Collection>> classes = resolver.getClasses();
author: Tim Fennell |