获取某接口的所有实现类并初始化
程序员文章站
2022-07-04 09:15:32
...
日前项目中遇到一个问题:
有一个接口,这个接口定义了一种规范和标志,接口中只有一个初始化方法,接口的实现类可能会有非常多,需要在容器启动过程中我们去手动初始化这个接口的所有实现类,虽然在spring中我们可以直接配置,但是维护与使用时却不够优雅。
1. 以一个Config接口为例:
public interface Config { /** * 初始化 */ void initialize(); }
接口很简单,只有一个初始化方法。
2.然后Config接口可能会有很多种实现,比如:
public class RedisConfig implements Config { @Override public void initialize() { // 初始化实现 } }
然而像这种实现可能会非常多且不受控制,但是我们又想对这些实现统一进行初始化,第一步我们就会想到利用ClassLoader来实现,但是如果这些实现类在不同的包中就非常麻烦,随后我们又想到了ServiceLoader,但是需要配置且不同包下也失败了。
在这里我选择了Reflections类库,Reflections使用起来非常简单比Java自身的反射要简便的多,而且好用的多。
3.导入Maven配置
<dependency> <groupId>org.reflections</groupId> <artifactId>reflections-spring</artifactId> <version>0.9.9-RC1</version> <exclusions> <exclusion> <groupId>javassist</groupId> <artifactId>javassist</artifactId> </exclusion> </exclusions> </dependency>
注意不要选错了。
4.编写相关工具
public class ConfigUtil { // 初始化方法名称 private static final String INIT_METHOD_NAME = "initialize"; // 要扫描的包名 private static final String PACKAGE_NAME = "com.xxxx"; public static void main(String[] args) { List<String> list = getConfigNameList(); for (String name : list) { System.out.println(name); //初始化 manualInitialize(name); } } /** * 获取所有模块名称 * * @return */ public static List<String> getConfigNameList() { List<String> nameList = new ArrayList<String>(); Reflections reflections = new Reflections(PACKAGE_NAME); Set<Class<? extends Config>> classes = reflections.getSubTypesOf(Config.class); if (monitorClasses != null) { for (Class<? extends Config> config: classes) { boolean isAbstract = Modifier.isAbstract(config.getModifiers()); //过滤抽象类 if (!isAbstract) { nameList.add(config.getName()); } } } return nameList; } /** * 获取所有实现 * * @return */ public static List<Class> getConfigList() { List<Class> configList= new ArrayList<Class>(); Reflections reflections = new Reflections(PACKAGE_NAME); Set<Class<? extends Config>> classes = reflections.getSubTypesOf(Config.class); if (monitorClasses != null) { for (Class<? extends Config> config : classes) { boolean isAbstract = Modifier.isAbstract(config.getModifiers()); if (!isAbstract) { configList.add(config); } } } return moduleList; } /** * 调用初始化方法 * * @param fullClassName 全限定名 */ @SuppressWarnings("unchecked") public static void manualInitialize(String fullClassName) { try { Class clazz = Class.forName(fullClassName); Constructor[] constructors = clazz.getDeclaredConstructors(); AccessibleObject.setAccessible(constructors, true); for (Constructor con : constructors) { if (con.isAccessible()) { Object classObject = con.newInstance(); Method method = clazz.getMethod(INIT_METHOD_NAME); method.invoke(classObject); } } } catch (Exception e) { e.printStackTrace(); } } }
最终我们调用manualInitialize(name);方法进行了初始化。