获取某个接口的所有实现类并且初始化
日前项目中遇到一个问题:有一个接口,这个接口定义了一种规范和标志,接口中只有一个初始化方法,接口的实现类可能会有非常多,需要在容器启动过程中我们去手动初始化这个接口的所有实现类,虽然在spring中我们可以直接配置,但是维护与使用时却不够优雅。1. 以一个Config接口为例:Java代码publicinterfaceConfig{...
日前项目中遇到一个问题:
有一个接口,这个接口定义了一种规范和标志,接口中只有一个初始化方法,接口的实现类可能会有非常多,需要在容器启动过程中我们去手动初始化这个接口的所有实现类,虽然在spring中我们可以直接配置,但是维护与使用时却不够优雅。
1. 以一个Config接口为例:
Java代码
- public interface Config {
- /**
- * 初始化
- */
- void initialize();
- }
接口很简单,只有一个初始化方法。
2.然后Config接口可能会有很多种实现,比如:
Java代码
- public class RedisConfig implements Config {
- @Override
- public void initialize() {
- // 初始化实现
- }
- }
然而像这种实现可能会非常多且不受控制,但是我们又想对这些实现统一进行初始化,第一步我们就会想到利用ClassLoader来实现,但是如果这些实现类在不同的包中就非常麻烦,随后我们又想到了ServiceLoader,但是需要配置且不同包下也失败了。
在这里我选择了Reflections类库,Reflections使用起来非常简单比Java自身的反射要简便的多,而且好用的多。
3.导入Maven配置
Xml代码
- <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.编写相关工具
Java代码
- 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);方法进行了初始化。
注意: @Configuration这个注解具有全局化的作用
@Bean 这个注解当类启动的时候就加入到了SpringIOC容器中
这两个注解合到一起构成了xml配置的配置文件
更多推荐
所有评论(0)