前言
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<292462859@qq.com>
*/
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<292462859@qq.com>
*/
@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<292462859@qq.com>
*/
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<292462859@qq.com>
*/
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<292462859@qq.com>
*/
@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: chenzhao@viomi.com.cn
* @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));
}
}
- 启动应用,访问接口,返回如下,证明依赖注入已经成功:
总结
Quarkus的上下文依赖注入使用的是CDI标准规范,实现依赖注入可以避免从Spring框架切换到Quarkus框架的使用上的不习惯,因为本人还没特别深入地使用Quarkus框架,特别是并没有在真实生产环境中使用过Quarkus框架,所以说Quarkus Arc能否达到Spring IOC的高度,还需要时间验证。
示例源码
参考文章
来源:oschina
链接:https://my.oschina.net/u/2460702/blog/3051161