1. 程式人生 > >Quarkus框架入門之二:依賴注入

Quarkus框架入門之二:依賴注入

前言

Spring框架最開始被我熟知就是AOP和IOC,其中IOC在開發過程中更是被廣泛使用,如果切換到一個新的框架沒有了依賴注入和控制反轉,那麼可以說一夜回到解放前了。那麼,Quarkus框架中有沒有對應的功能呢? 當然也有,Quarkus基於CDI規範提供了依賴注入的相關功能,本文將進行簡單介紹。

CDI-Contexts and Dependency Injection

簡單介紹

CDI(Contexts and Dependency Injection),即上下文依賴注入,是J2EE6釋出的一個標準規範,用於對上下文依賴注入的標準規範化,思想應該是來源於Spring的IOC,存在的年頭已經挺久遠。但是之前一直沒怎麼關注這個規範,都是用Spring Framework打天下。 以前以為只能在J2EE中使用,但是在寫這篇文章的時候,發現在J2SE8.0已經可以使用CDI了,只需要明確引導CDI容器即可。

簡單使用示例(J2SE)

以下以在一個簡單的Java專案中使用weld實現依賴注入進行簡單示例,依賴包如下:

<dependency>
            <groupId>org.jboss.weld.se</groupId>
            <artifactId>weld-se-core</artifactId>
            <version>3.1.0.Final</version>
        </dependency>
  • 首先,編寫介面類和實現類;

HelloService.class

/**
 * Created at 2019/5/18 by centychen<[email protected]>
 */
public interface HelloService {
    /**
     * example method.
     *
     * @return
     */
    String sayHello();
}

HelloServiceImpl.class

import cn.centychen.examples.j2se.cdi.service.HelloService;

import javax.enterprise.inject.Default;

/**
 * Created at 2019/5/18 by centychen<[email protected]>
 */
@Default
public class HelloServiceImpl implements HelloService {

    /**
     * Example method implement.
     *
     * @return
     */
    @Override
    public String sayHello() {
        return "Hello,This is an example for CDI.";
    }
}
  • 其次,新增beans.xml定義檔案,內容如下: 實際上新增一個空白檔案也可以正常執行。
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://xmlns.jcp.org/xml/ns/javaee
       http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="all">
</beans>
  • 最後,編寫測試啟動類
import cn.centychen.examples.j2se.cdi.service.HelloService;

import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;

/**
 * Created at 2019/5/18 by centychen<[email protected]>
 */
public class Application {

    /**
     * main method.
     *
     * @param args
     */
    public static void main(String[] args) {
        SeContainer container = SeContainerInitializer.newInstance().initialize();
        HelloService helloService = container.select(HelloService.class).get();
        System.out.println(helloService.sayHello());
    }
}
  • 執行測試,輸入日誌如下,HelloService的實現類已經正確注入。
objc[13831]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/bin/java (0x10d96e4c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10e9934e0). One of the two will be used. Which one is undefined.
五月 18, 2019 12:37:36 下午 org.jboss.weld.bootstrap.WeldStartup <clinit>
INFO: WELD-000900: 3.1.0 (Final)
五月 18, 2019 12:37:36 下午 org.jboss.weld.bootstrap.WeldStartup startContainer
INFO: WELD-000101: Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
五月 18, 2019 12:37:37 下午 org.jboss.weld.environment.se.WeldContainer fireContainerInitializedEvent
INFO: WELD-ENV-002003: Weld SE container 3f7714f9-0cea-48a0-b217-1147420967e0 initialized
Hello,This is an example for CDI.
Weld SE container 3f7714f9-0cea-48a0-b217-1147420967e0 shut down by shutdown hook

Quarkus依賴注入

Quarkus的依賴注入管理使用的是io.quarkus:arc,實際上就是CDI的一種實現。以下上一篇文章示例進行簡單改造,實現依賴注入。

  • 編寫業務介面HelloService及其實現類HelloServiceImpl,參考程式碼如下:

HelloService.class:

/**
 * Created at 2019/5/18 by centychen<[email protected]>
 */
public interface HelloService {

    /**
     * Say hello method.
     *
     * @param name
     * @return
     */
    String sayHello(String name);
}

HelloServiceImpl.class:

import cn.centychen.quarkus.example.service.HelloService;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Default;

/**
 * Created at 2019/5/18 by centychen<[email protected]>
 */
@ApplicationScoped //標誌Bean的作用域為一個應用一個例項。
@Default //預設,介面多實現時必須
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        return String.format("Hello,%s!", name);
    }
}
  • 改造GreetingResource類,增加依賴注入以及業務介面呼叫,參考如下:
import cn.centychen.quarkus.example.service.HelloService;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

/**
 * @author: cent
 * @email: [email protected]
 * @date: 2019/5/4.
 * @description:
 */
@Path("/hello")
public class GreetingResource {

    @Inject
    private HelloService helloService;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/{name}")
    public CompletionStage<String> hello(@PathParam("name") String name) {
        //使用非同步響應
        return CompletableFuture.supplyAsync(() -> helloService.sayHello(name));
    }
}
  • 啟動應用,訪問介面,返回如下,證明依賴注入已經成功: image.png

總結

Quarkus的上下文依賴注入使用的是CDI標準規範,實現依賴注入可以避免從Spring框架切換到Quarkus框架的使用上的不習慣,因為本人還沒特別深入地使用Quarkus框架,特別是並沒有在真實生產環境中使用過Quarkus框架,所以說Quarkus Arc能否達到Spring IOC的高度,還需要時間驗證。

示例原始碼

參考文章