日前项目中遇到一个问题:

        有一个接口,这个接口定义了一种规范和标志,接口中只有一个初始化方法,接口的实现类可能会有非常多,需要在容器启动过程中我们去手动初始化这个接口的所有实现类,虽然在spring中我们可以直接配置,但是维护与使用时却不够优雅。

       1. 以一个Config接口为例:

Java代码 

 收藏代码

  1. public interface Config {  
  2.   
  3.     /** 
  4.      * 初始化 
  5.      */  
  6.     void initialize();  
  7. }  

        接口很简单,只有一个初始化方法。

        2.然后Config接口可能会有很多种实现,比如:

Java代码 

 收藏代码

  1. public class RedisConfig implements Config {  
  2.   
  3.     @Override  
  4.     public void initialize() {  
  5.         // 初始化实现  
  6.     }  
  7.   
  8. }  

        然而像这种实现可能会非常多且不受控制,但是我们又想对这些实现统一进行初始化,第一步我们就会想到利用ClassLoader来实现,但是如果这些实现类在不同的包中就非常麻烦,随后我们又想到了ServiceLoader,但是需要配置且不同包下也失败了。

        在这里我选择了Reflections类库,Reflections使用起来非常简单比Java自身的反射要简便的多,而且好用的多。

        3.导入Maven配置

Xml代码 

 收藏代码

  1. <dependency>  
  2.     <groupId>org.reflections</groupId>  
  3.     <artifactId>reflections-spring</artifactId>  
  4.     <version>0.9.9-RC1</version>  
  5.     <exclusions>  
  6.         <exclusion>  
  7.             <groupId>javassist</groupId>  
  8.             <artifactId>javassist</artifactId>  
  9.         </exclusion>  
  10.     </exclusions>  
  11. </dependency>  

        注意不要选错了。

        4.编写相关工具

Java代码 

 收藏代码

  1. public class ConfigUtil {  
  2.   
  3.     // 初始化方法名称  
  4.     private static final String INIT_METHOD_NAME = "initialize";  
  5.     // 要扫描的包名  
  6.     private static final String PACKAGE_NAME     = "com.xxxx";  
  7.   
  8.     public static void main(String[] args) {  
  9.         List<String> list = getConfigNameList();  
  10.         for (String name : list) {  
  11.             System.out.println(name);  
  12.             //初始化  
  13.         manualInitialize(name);  
  14.         }  
  15.     }  
  16.   
  17.     /** 
  18.      * 获取所有模块名称 
  19.      * 
  20.      * @return 
  21.      */  
  22.     public static List<String> getConfigNameList() {  
  23.         List<String> nameList = new ArrayList<String>();  
  24.         Reflections reflections = new Reflections(PACKAGE_NAME);  
  25.         Set<Class<? extends Config>> classes = reflections.getSubTypesOf(Config.class);  
  26.         if (monitorClasses != null) {  
  27.             for (Class<? extends Config> config: classes) {  
  28.                 boolean isAbstract = Modifier.isAbstract(config.getModifiers());  
  29.         //过滤抽象类  
  30.                 if (!isAbstract) {  
  31.                     nameList.add(config.getName());  
  32.                 }  
  33.             }  
  34.         }  
  35.         return nameList;  
  36.     }  
  37.   
  38.     /** 
  39.      * 获取所有实现 
  40.      * 
  41.      * @return 
  42.      */  
  43.     public static List<Class> getConfigList() {  
  44.         List<Class> configList= new ArrayList<Class>();  
  45.         Reflections reflections = new Reflections(PACKAGE_NAME);  
  46.         Set<Class<? extends Config>> classes = reflections.getSubTypesOf(Config.class);  
  47.         if (monitorClasses != null) {  
  48.             for (Class<? extends Config> config : classes) {  
  49.                 boolean isAbstract = Modifier.isAbstract(config.getModifiers());  
  50.                 if (!isAbstract) {  
  51.                     configList.add(config);  
  52.                 }  
  53.             }  
  54.         }  
  55.         return moduleList;  
  56.     }  
  57.   
  58.     /** 
  59.      * 调用初始化方法 
  60.      * 
  61.      * @param fullClassName 全限定名 
  62.      */  
  63.     @SuppressWarnings("unchecked")  
  64.     public static void manualInitialize(String fullClassName) {  
  65.         try {  
  66.             Class clazz = Class.forName(fullClassName);  
  67.             Constructor[] constructors = clazz.getDeclaredConstructors();  
  68.             AccessibleObject.setAccessible(constructors, true);  
  69.             for (Constructor con : constructors) {  
  70.                 if (con.isAccessible()) {  
  71.                     Object classObject = con.newInstance();  
  72.                     Method method = clazz.getMethod(INIT_METHOD_NAME);  
  73.                     method.invoke(classObject);  
  74.                 }  
  75.             }  
  76.         } catch (Exception e) {  
  77.             e.printStackTrace();  
  78.         }  
  79.     }  
  80. }  

        最终我们调用manualInitialize(name);方法进行了初始化。

注意: @Configuration这个注解具有全局化的作用

         @Bean 这个注解当类启动的时候就加入到了SpringIOC容器中

       这两个注解合到一起构成了xml配置的配置文件

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐