使用dropwizard(3)-加入DI-dagger2

前言

习惯了Spring全家桶,对spring的容器爱不释手。使用dropwizard,看起来确实很轻,然而,真正使用的时候不得不面临一个问题。我们不可能一个resource就能把所有的业务逻辑囊括!那么,必然就要有负责处理逻辑的代码,有要提取的公共的代码,要做面向接口开发等等。按照简单的用法,Java Bean就自己new,只要通过Jersey提供的web能力发出去就好。这样写下来,到处都需要new,难以测试等等。目前我最care的是,每个request过来都要new一堆重复的对象,垃圾回收频繁。写个单例不就解决了?是的,当然要想到单例,然后发现几乎所有的类都是设计成单例的。然后,一堆单例的代码写的死。这就是样板代码。于是,想到提取工具类,算了,不如用Dagger好了。

什么是Dagger

Dagger是Java里开源的DI框架中最火的之一,主要用在Android领域,很多特性也多针对Android开发的。因为Android开发对省电,性能之类的要求比较高,因此抛弃了反射,直接在编译级别生成工厂。详细学习测试:Dagger2之helloworld原理探究

Demo Source

https://github.com/Ryan-Miao/l4dropwizard

structure

.
├── pom.xml
├── readme.md
└── src
    └── main
        ├── java
        │   └── com
        │       └── test
        │           ├── HelloWorldApplication.java
        │           ├── bundles
        │           │   └── ConnectivityBundle.java
        │           ├── configuration
        │           │   ├── HelloWorldConfiguration.java
        │           │   └── modules
        │           │       ├── ConnectAndReadConfig.java
        │           │       └── GithubApiConfig.java
        │           └── domain
        │               ├── connect
        │               │   ├── FeignClientBuilder.java
        │               │   ├── GithubClient.java
        │               │   └── GithubConnector.java
        │               ├── entiry
        │               │   ├── GithubUser.java
        │               │   └── Saying.java
        │               ├── exception
        │               │   └── UpstreamException.java
        │               ├── health
        │               │   └── TemplateHealthCheck.java
        │               ├── ioc
        │               │   ├── component
        │               │   │   └── GithubComponent.java
        │               │   └── module
        │               │       ├── ConfigurationModule.java
        │               │       ├── ConnectorModule.java
        │               │       └── ServiceModule.java
        │               ├── resource
        │               │   ├── GithubResource.java
        │               │   └── HelloWorldResource.java
        │               └── service
        │                   ├── IGithubService.java
        │                   └── impl
        │                       └── GithubService.java
        └── resources
            └── config
                └── dev.yml

本文基于之前的dropwizard入门演进.

添加dagger依赖

properties结点下新增

<dagger.verion>2.12</dagger.verion>

在dependencies下新增

<dependency>
    <groupId>com.google.dagger</groupId>
    <artifactId>dagger</artifactId>
    <version>${dagger.verion}</version>
</dependency>

build.plugins下新增plugin

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.6.1</version>
    <configuration>
        <source>${java.version}</source>
        <target>${java.version}</target>
        <encoding>UTF-8</encoding>
        <annotationProcessorPaths>
            <path>
                <groupId>com.google.dagger</groupId>
                <artifactId>dagger-compiler</artifactId>
                <version>${dagger.verion}</version>
            </path>
        </annotationProcessorPaths>
    </configuration>
</plugin>

在IDEA设置中,找到Build>Compiler>Annotation Processors, 选择Enable annotation processing.

创建一个Component

下面创建Component,用来包容Resource类,对外提供Resource类。新建com.test.domain.ioc.component.GithubComponent

package com.test.domain.ioc.component;

import com.test.domain.ioc.module.ServiceModule;
import com.test.domain.resource.GithubResource;
import dagger.Component;

import javax.inject.Singleton;

/**
 * Created by Ryan Miao on 10/26/17.
 */
@Singleton
@Component(modules = {ServiceModule.class})
public interface GithubComponent {
     GithubResource gitHubResource();
}

显然,这个GithubResource需要注入一个service,于是声明一个ServiceModule, 创建com.test.domain.ioc.module.ServiceModule

package com.test.domain.ioc.module;

import com.test.domain.service.IGithubService;
import com.test.domain.service.impl.GithubService;
import dagger.Module;
import dagger.Provides;

import javax.inject.Singleton;

/**
 * Created by Ryan Miao on 10/26/17.
 */
@Module(includes = ConnectorModule.class)
public class ServiceModule {

    @Singleton
    @Provides
    public IGithubService githubService(GithubService service) {
        return service;
    }
}

ServiceModule用来提供service注入,service接着依赖connector层,新建com.test.domain.ioc.module.ConnectorModule

package com.test.domain.ioc.module;

import com.test.domain.connect.FeignClientBuilder;
import dagger.Module;
import dagger.Provides;

import javax.inject.Singleton;

/**
 * Created by Ryan Miao on 10/26/17.
 */
@Module(includes = ConfigurationModule.class)
public class ConnectorModule {

    @Provides
    @Singleton
    public FeignClientBuilder feignClientBuilder(){
        return new FeignClientBuilder();
    }
    
}

connecttor层中,需要调用GlobalConfiguration的配置项,所以,单独把配置提出来,引入。新增com.test.domain.ioc.module.ConfigurationModule

package com.test.domain.ioc.module;

import com.test.configuration.HelloWorldConfiguration;
import dagger.Module;
import dagger.Provides;

import javax.inject.Singleton;

/**
 * Created by Ryan Miao on 11/20/17.
 */
@Module
public class ConfigurationModule {
    private final HelloWorldConfiguration configuration;

    public ConfigurationModule(HelloWorldConfiguration configuration) {
        this.configuration = configuration;
    }


    @Provides
    @Singleton
    public HelloWorldConfiguration helloWorldConfiguration(){
        return configuration;
    }
}

这是依赖的最底层,我们通过手动构造函数的方式注入configuration,这样可以在dropwizard启动时生成module,并且得到configuration。

引入我们的Component

这时候,build一下,dagger就会自动生成我们的工厂。

mvn clean install

然后,在IDEA里的maven plugin里,右键,reimport。防止IDEA不认识dagger自动生成的类。dagger自动生成的类位于target/generated-sources/annotations. 点击刷新按钮,刷新下maven依赖。

然后,在com.test.HelloWorldApplication中,新增

private void registerResources(HelloWorldConfiguration configuration, Environment environment) {
    GithubComponent component = DaggerGithubComponent.builder()
            .configurationModule(new ConfigurationModule(configuration))
            .build();
    environment.jersey().register(component.gitHubResource());
}

DaggerGithubComponent要在maven install之后,dagger生成的。完整启动类如下:

public class HelloWorldApplication extends Application<HelloWorldConfiguration> {

    public static void main(String[] args) throws Exception {
        new HelloWorldApplication().run(args);
    }

    @Override
    public String getName() {
        return "hello-world";
    }

    @Override
    public void initialize(Bootstrap<HelloWorldConfiguration> bootstrap) {
        bootstrap.addBundle(new ConnectivityBundle());
    }

    @Override
    public void run(HelloWorldConfiguration configuration, Environment environment) throws Exception {
        final HelloWorldResource resource = new HelloWorldResource(
                configuration.getTemplate(),
                configuration.getDefaultName()
        );
        final TemplateHealthCheck healthCheck =
                new TemplateHealthCheck(configuration.getTemplate());
        environment.healthChecks().register("template", healthCheck);
        environment.jersey().register(resource);
        environment.jersey().register(healthCheck);

        registerResources(configuration, environment);

    }

    private void registerResources(HelloWorldConfiguration configuration, Environment environment) {
        GithubComponent component = DaggerGithubComponent.builder()
                .configurationModule(new ConfigurationModule(configuration))
                .build();
        environment.jersey().register(component.gitHubResource());
    }
}

当然,我们的Resource也要改成Inject模式

public class GithubResource {

    private IGithubService service;

    @Inject
    public GithubResource(IGithubService service) {
        this.service = service;
    }

    @GET
    @Timed
    @Path("/users/{username}")
    public GithubUser getUserProfile(@PathParam("username") final String username) {
        return service.getUserProfile(username);
    }

}

启动,运行。一切OK。以后就可以在需要注入的类的构造器上声明@Inject, 或者在module里@Provide,就可以实现构造解耦。测试不要太方便.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我和未来有约会

Kit 3D 更新

Kit3D is a 3D graphics engine written for Microsoft Silverlight. Kit3D was inita...

2636
来自专栏我和未来有约会

Silverlight第三方控件专题

这里我收集整理了目前网上silverlight第三方控件的专题,若果有所遗漏请告知我一下。 名称 简介 截图 telerik 商 RadC...

4095
来自专栏Ceph对象存储方案

Luminous版本PG 分布调优

Luminous版本开始新增的balancer模块在PG分布优化方面效果非常明显,操作也非常简便,强烈推荐各位在集群上线之前进行这一操作,能够极大的提升整个集群...

3265
来自专栏转载gongluck的CSDN博客

cocos2dx 打灰机

#include "GamePlane.h" #include "PlaneSprite.h" #include "BulletNode.h" #include...

5686
来自专栏落花落雨不落叶

canvas画简单电路图

66111
来自专栏张善友的专栏

Silverlight + Model-View-ViewModel (MVVM)

     早在2005年,John Gossman写了一篇关于Model-View-ViewModel模式的博文,这种模式被他所在的微软的项目组用来创建Expr...

3038
来自专栏张善友的专栏

Miguel de Icaza 细说 Mix 07大会上的Silverlight和DLR

Mono之父Miguel de Icaza 详细报道微软Mix 07大会上的Silverlight和DLR ,上面还谈到了Mono and Silverligh...

2747
来自专栏陈仁松博客

ASP.NET Core 'Microsoft.Win32.Registry' 错误修复

今天在发布Asp.net Core应用到Azure的时候出现错误InvalidOperationException: Cannot find compilati...

4878
来自专栏闻道于事

js登录滑动验证,不滑动无法登陆

js的判断这里是根据滑块的位置进行判断,应该是用一个flag判断 <%@ page language="java" contentType="text/html...

7218
来自专栏C#

DotNet加密方式解析--非对称加密

    新年新气象,也希望新年可以挣大钱。不管今年年底会不会跟去年一样,满怀抱负却又壮志未酬。(不过没事,我已为各位卜上一卦,卦象显示各位都能挣钱...)...

4988

扫码关注云+社区