如何更好的在dropWizard使用IOC容器

来源:互联网 发布:公寓租房软件 编辑:程序博客网 时间:2024/04/30 20:17

如何更好的在dropWizard使用IOC容器

dropwizard介绍

dropWizard是由Yammer开发团队贡献的一个后台服务开发框架,其集成了Java生态系统中各个问题域中最优秀的组件,帮助开发者快速的打造一个Rest风格的后台服务。

对开发者来说,使用DropWizard有如下好处:

  • 和Maven集成良好,也就是说和Gradle集成也很良好;
  • 开发迅速,部署简单;
  • 代码结构好,可读性高;
  • 自动为服务提供OM框架;
  • 让开发者自然的把一个应用拆分为一个个的小服务

dropwizard的缺点

在实际的使用过程中,也遇到了一些使用上的不便,特别是在现在由微服务所构成的系统中,往往需要使用到各种中间件,如:mq,分布式缓存和分布式数据库等,但是各个中间件客户端的初始化过程却存在着很大的差别,如初始化activemq的(参考https://github.com/mbknor/dropwizard-activemq-bundle)

    private ActiveMQBundle activeMQBundle;    @Override    public void initialize(Bootstrap<Config> configBootstrap) {        // Create the bundle and store reference to it        this.activeMQBundle = new ActiveMQBundle();        // Add the bundle        configBootstrap.addBundle(activeMQBundle);    }    @Override    public void run(Config config, Environment environment) throws Exception {        final String queueName = config.getQueueName();        // Set up the sender for our queue        ActiveMQSender sender = activeMQBundle.createSender( queueName, false);        // Set up a receiver that just logs the messages we receive on our queue        activeMQBundle.registerReceiver(                queueName,                (animal) -> log.info("\n*****\nWe received an animal from activeMq: \n{}\n*****", animal),                Animal.class,                true);        // Create our resource        environment.jersey().register( new AnimalResource(sender) );    }

如果只是一个中间件的初始化,可能还会觉得没有太大的问题,但是如果要使用多个中间件,如果依赖的中间件客户端的初始化过程发现改变,虽然其使用接口并没有改变,则相关的微服务模块也都需要进行修改。而理想情况下,我们所开发的微服务,应该只会受其接口变化的影响。

将dropwizard与IOC容器结合

目前dropwizard已经有了可以和spring和guice这两个著名的ioc容器相关结合的开源实现,但是由于dropwizard使用到了Jersey,而Jersey中就已经含有了一个HK2的IOC容器,dw-hk2-autoconf就是这样的一个项目,但是直接使用这个项目的实现,并不能完全达到实现一种“微内核+插件”的架构模式,其根本原因就是没有将dropwizard的Configuration对象进行相关的拆解,注入到HK2的IOC容器中,已经将dw-hk2-autoconf fork出来,增加了将Configuration进行分析的过程,基本就能实现“微内核+插件”的架构模式,主要的修改是在AutoConfigBundle.java中增加了registerSubConfigurationProvider方法

private void registerSubConfigurationProvider(final T configuration, final Environment environment) {        final List<Field> subDeclaredFields = Arrays.asList(configuration.getClass().getDeclaredFields());        final List<Field> subConfigFields = filterOutSubConf(subDeclaredFields);        environment.jersey().register(new AbstractBinder() {            @Override            protected void configure() {                for(Field subConfField:subConfigFields){                    Object subConfig;                    try {                        subConfField.setAccessible(true);                        subConfig = subConfField.get(configuration);                        if(subConfig!=null){                            bind(subConfig);                        }                    } catch (IllegalArgumentException | IllegalAccessException e) {                        e.printStackTrace();                    }                }            }        });    }    private List<Field> filterOutSubConf(List<Field> subDeclaredFields) {        List<Field> parentDeclaredFields = Arrays.asList(Configuration.class.getDeclaredFields());        List<Field> resultFields = new ArrayList<>();        for(Field subField:subDeclaredFields){            if(subField.getType().isPrimitive()){                continue;            }            if(subField.getType().equals(String.class)){                continue;            }            if(parentDeclaredFields.contains(subField)){                continue;            }            resultFields.add(subField);        }        return resultFields;    }
0 0