【Java万花筒】解析Java依赖注入:从Spring到CDI的全方位比较

探索Java依赖注入:框架、实践与比较

前言

在当今的软件开发中,依赖注入已经成为了一种不可或缺的设计模式。Java作为一种广泛应用的编程语言,在依赖注入领域也有着丰富的框架和实践。本文将探索Java中几种常用的依赖注入框架,包括Spring IoC、Google Guice、PicoContainer、Dagger、HK2和CDI,介绍它们的特点、用法以及适用场景,帮助读者更好地理解和选择合适的依赖注入框架。

欢迎订阅专栏:Java万花筒

文章目录

  • 探索Java依赖注入:框架、实践与比较
    • 前言
      • 1. Spring IoC
        • 1.1 概述
        • 1.2 核心功能
          • 1.2.1 Bean 定义
          • 1.2.2 依赖注入
        • 1.3 Spring Bean 的生命周期管理
          • 1.3.1 Bean 的实例化
        • 1.4 应用场景
          • 1.4.1 Web 应用
          • 1.4.2 企业级应用
        • 1.5 Spring IoC的高级特性
          • 1.5.1 切面编程
          • 1.5.2 事件驱动编程
        • 1.6 使用注解配置Bean
        • 1.7 集成测试支持
      • 2. Google Guice
        • 2.1 简介
        • 2.2 核心特性
          • 2.2.1 绑定
          • 2.2.2 依赖注入
        • 2.3 模块化
        • 2.4 配置与扩展
        • 2.5 应用示例
        • 2.6 高级特性:Guice AOP
        • 2.7 高级特性:Guice扩展
        • 2.8 Guice与其他框架集成
      • 3. PicoContainer
        • 3.1 简介
        • 3.2 核心概念
          • 3.2.1 容器
          • 3.2.2 注册
          • 3.2.3 分解器
        • 3.3 生命周期管理
        • 3.4 嵌套容器
        • 3.5 应用案例
        • 3.6 自定义组件实例化策略
        • 3.7 生命周期管理器
        • 3.8 配置文件与注解
      • 4. Dagger
        • 4.1 简介
        • 4.2 编译时生成代码
          • 4.2.1 注解处理器
          • 4.2.2 生成的依赖注入代码
        • 4.3 优势与适用场景
          • 4.3.1 性能优化
          • 4.3.2 安全性增强
        • 4.4 使用示例
        • 4.5 模块化设计
        • 4.6 生命周期管理
        • 4.7 组件化设计
        • 4.8 Android开发中的应用
      • 5. HK2
        • 5.1 概述
        • 5.2 特性与功能
          • 5.2.1 依赖注入
          • 5.2.2 生命周期管理
        • 5.3 与Java EE集成
          • 5.3.1 在GlassFish服务器上的应用
          • 5.3.2 Jersey框架中的使用
        • 5.5 事件管理
        • 5.6 定制化扩展
        • 5.7 HK2与Spring集成
        • 5.8 HK2在MicroProfile中的应用
      • 6. CDI (Contexts and Dependency Injection for Java)
        • 6.1 简介
        • 6.2 核心概念
          • 6.2.1 上下文
          • 6.2.2 依赖注入
        • 6.3 生命周期管理
          • 6.3.1 Bean的生命周期
          • 6.3.2 作用域
        • 6.4 应用示例
        • 6.5 事件管理
        • 6.6 定制化扩展
        • 6.7 CDI与其他Java EE技术集成
        • 6.8 CDI在Java SE中的应用
    • 总结

1. Spring IoC

Spring IoC(控制反转)是一个用于管理Java对象的框架,它通过将对象之间的依赖关系交给容器来管理,实现了松耦合和可测试性。以下是Spring IoC的详细介绍和示例代码:

1.1 概述

Spring IoC的核心思想是将对象的创建和依赖关系的维护交给容器管理,而不是在代码中硬编码。通过IoC容器,我们可以将各个组件解耦,降低它们之间的依赖性,从而提高代码的灵活性和可维护性。

1.2 核心功能
1.2.1 Bean 定义

在Spring中,我们可以通过XML配置文件、Java注解或者Java代码来定义Bean。下面是一个XML配置文件中定义Bean的示例:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");// 获取定义的BeanHelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");helloWorld.setMessage("Hello World!");helloWorld.getMessage();}
}

beans.xml:

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="helloWorld" class="com.example.HelloWorld"><property name="message" value="Hello, Spring IoC!" /></bean></beans>
1.2.2 依赖注入

Spring IoC容器会自动装配Bean之间的依赖关系,我们无需手动实例化或者管理这些依赖对象。以下是一个依赖注入的示例:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class TextEditor {private SpellChecker spellChecker;@Autowiredpublic TextEditor(SpellChecker spellChecker) {this.spellChecker = spellChecker;}public void spellCheck() {spellChecker.checkSpelling();}
}
1.3 Spring Bean 的生命周期管理

Spring IoC容器管理Bean的完整生命周期,包括实例化、初始化、使用和销毁。我们可以通过实现特定接口或者使用特定注解来控制Bean的生命周期。

1.3.1 Bean 的实例化

在Spring中,Bean的实例化可以通过构造函数、工厂方法或者静态工厂方法来进行。以下是一个通过构造函数实例化Bean的示例:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");helloWorld.getMessage();}
}
1.4 应用场景

Spring IoC广泛应用于各种Java应用程序中,特别是在企业级应用开发和Web应用开发中。其优点包括降低耦合性、提高代码的可测试性和可维护性。#### 1.4 应用场景

1.4.1 Web 应用

在Web应用中,Spring IoC容器通常用于管理控制器、服务层和持久层组件,实现了业务逻辑的解耦和灵活配置。例如,在Spring MVC框架中,控制器可以通过注解 @Controller@Autowired 来实现依赖注入,从而与其他组件解耦。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class HelloWorldController {@Autowiredprivate HelloWorldService helloWorldService;@RequestMapping("/hello")@ResponseBodypublic String hello() {return helloWorldService.getMessage();}
}
1.4.2 企业级应用

在企业级应用中,Spring IoC容器常用于整合各种框架和技术,实现复杂业务逻辑的管理和调度。例如,Spring与Hibernate集成可以实现数据访问层的管理,Spring与Spring Security集成可以实现安全权限控制,Spring与JMS集成可以实现消息队列的管理等等。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {@Autowiredprivate UserDAO userDAO;public void saveUser(User user) {userDAO.save(user);}public User getUserById(int id) {return userDAO.findById(id);}
}

以上是Spring IoC的简要介绍和示例代码,Spring IoC通过依赖注入和控制反转的机制,实现了松耦合、可测试和可维护的代码编写,是Java开发中的重要组成部分。

1.5 Spring IoC的高级特性
1.5.1 切面编程

Spring IoC框架支持切面编程,可以通过AOP(面向切面编程)方式实现诸如日志记录、性能监控、事务管理等横切关注点的功能。以下是一个简单的AOP示例:

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {@Before("execution(public * com.example.*.*(..))")public void logBefore() {System.out.println("Logging before method execution...");}
}
1.5.2 事件驱动编程

Spring IoC框架支持事件驱动编程,可以通过事件机制实现组件之间的解耦和通信。以下是一个简单的事件驱动示例:

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;@Component
public class MyEventListener implements ApplicationListener<MyEvent> {@Overridepublic void onApplicationEvent(MyEvent event) {System.out.println("Received event: " + event.getMessage());}
}public class MyEvent extends ApplicationEvent {private String message;public MyEvent(Object source, String message) {super(source);this.message = message;}public String getMessage() {return message;}
}
1.6 使用注解配置Bean

除了XML配置外,Spring IoC还支持使用注解来配置Bean,使得配置更加简洁和方便。以下是一个使用注解配置Bean的示例:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic HelloWorld helloWorld() {return new HelloWorld();}
}
1.7 集成测试支持

Spring IoC框架提供了强大的集成测试支持,可以方便地编写和执行集成测试用例。以下是一个简单的集成测试示例:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import static org.junit.jupiter.api.Assertions.assertEquals;@SpringBootTest
public class IntegrationTest {@Autowiredprivate HelloWorldService helloWorldService;@Testpublic void testGetMessage() {assertEquals("Hello, Spring IoC!", helloWorldService.getMessage());}
}

以上是Spring IoC框架的高级特性和使用方法,通过了解和掌握这些内容,开发者可以更好地利用Spring IoC框架进行应用开发和测试。

2. Google Guice

Google Guice是一个轻量级的依赖注入框架,它提供了一种简洁而优雅的方式来管理Java应用程序中的对象依赖关系。以下是Guice的详细介绍和示例代码:

2.1 简介

Guice是由Google开发的一个开源项目,它允许开发者通过注解和Java配置来声明对象之间的依赖关系,从而实现依赖注入。相比于Spring IoC,Guice更加轻量级,没有XML配置文件的繁琐,更加注重Java代码的纯粹性和可读性。

2.2 核心特性
2.2.1 绑定

在Guice中,通过Module来配置对象之间的绑定关系。下面是一个简单的绑定示例:

import com.google.inject.AbstractModule;public class MyModule extends AbstractModule {@Overrideprotected void configure() {bind(Service.class).to(ServiceImpl.class);bind(Dao.class).to(DaoImpl.class);}
}
2.2.2 依赖注入

Guice通过构造函数、方法参数和字段注入等方式实现依赖注入。以下是一个构造函数注入的示例:

import com.google.inject.Inject;public class TextEditor {private SpellChecker spellChecker;@Injectpublic TextEditor(SpellChecker spellChecker) {this.spellChecker = spellChecker;}public void spellCheck() {spellChecker.checkSpelling();}
}
2.3 模块化

Guice支持模块化的配置方式,允许开发者将不同的依赖关系配置放在不同的模块中,从而使配置更加清晰和可维护。下面是一个简单的模块化配置示例:

import com.google.inject.AbstractModule;public class MyModule extends AbstractModule {@Overrideprotected void configure() {install(new ServiceModule());install(new DaoModule());}
}
2.4 配置与扩展

Guice支持通过扩展AbstractModule类来定义自定义的绑定和配置规则,使得框架更加灵活和可扩展。以下是一个自定义绑定的示例:

import com.google.inject.AbstractModule;public class MyModule extends AbstractModule {@Overrideprotected void configure() {bind(Service.class).to(AnotherServiceImpl.class);}
}
2.5 应用示例

Guice可以应用于各种Java应用程序中,包括Web应用、桌面应用和命令行应用等。以下是一个简单的Guice在Web应用中的示例:

import com.google.inject.Guice;
import com.google.inject.Injector;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class MyServlet extends HttpServlet {private MyService myService;@Overridepublic void init() throws ServletException {super.init();Injector injector = Guice.createInjector(new MyModule());myService = injector.getInstance(MyService.class);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().println(myService.sayHello());}
}

以上是Google Guice的简要介绍和示例代码,Guice通过简洁的API和灵活的配置方式,为Java开发者提供了一种优雅而轻量级的依赖注入解决方案。

2.6 高级特性:Guice AOP

除了基本的依赖注入功能之外,Google Guice还提供了AOP(面向切面编程)的支持,可以通过AspectJ等方式实现横切关注点的功能。以下是一个简单的Guice AOP示例:

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.matcher.Matchers;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;public class MyModule extends AbstractModule {@Overrideprotected void configure() {bind(Service.class).to(ServiceImpl.class);bind(Dao.class).to(DaoImpl.class);bindInterceptor(Matchers.any(), Matchers.annotatedWith(MyAnnotation.class), new MyInterceptor());}
}@Aspect
class MyInterceptor {@Before("@annotation(MyAnnotation)")public void beforeMyMethod() {System.out.println("Executing before MyMethod...");}
}public class MyService {@MyAnnotationpublic void myMethod() {System.out.println("Executing MyMethod...");}
}
2.7 高级特性:Guice扩展

Guice允许开发者通过扩展AbstractModule类来自定义绑定和配置规则,实现框架的灵活扩展。以下是一个自定义绑定的示例:

import com.google.inject.AbstractModule;
import com.google.inject.name.Names;public class MyModule extends AbstractModule {@Overrideprotected void configure() {bind(Service.class).to(ServiceImpl.class);bind(Dao.class).to(AnotherDaoImpl.class);bindConstant().annotatedWith(Names.named("timeout")).to(1000);}
}
2.8 Guice与其他框架集成

Guice可以与其他框架集成,例如Servlet、JUnit、Jersey等,实现更强大的功能。以下是一个Guice与Servlet集成的示例:

import com.google.inject.servlet.GuiceServletContextListener;
import com.google.inject.servlet.ServletModule;public class MyGuiceServletConfig extends GuiceServletContextListener {@Overrideprotected Injector getInjector() {return Guice.createInjector(new ServletModule() {@Overrideprotected void configureServlets() {serve("/myServlet").with(MyServlet.class);}});}
}

3. PicoContainer

PicoContainer是一个用于构建可嵌套的Java容器的轻量级框架,它提供了简单而灵活的方式来管理对象之间的依赖关系。以下是PicoContainer的详细介绍和示例代码:

3.1 简介

PicoContainer致力于提供简单的依赖注入功能,同时保持框架本身的轻量级和易用性。它通过容器的层次化和嵌套来管理对象的依赖关系,使得应用程序的组件更加模块化和可维护。

3.2 核心概念
3.2.1 容器

PicoContainer中的容器是对象的容纳者,它负责管理对象的生命周期和依赖关系。PicoContainer支持嵌套容器,使得对象的依赖关系可以以层次化的方式进行管理。

3.2.2 注册

在PicoContainer中,我们可以通过注册组件来告诉容器如何创建和管理对象。组件的注册可以通过API调用或者配置文件来进行。

3.2.3 分解器

PicoContainer使用分解器来解决对象之间的循环依赖关系,确保对象能够被正确地创建和注入。

3.3 生命周期管理

PicoContainer管理对象的完整生命周期,包括对象的创建、初始化、使用和销毁。开发者可以通过自定义的生命周期管理器来控制对象的生命周期。

3.4 嵌套容器

PicoContainer支持嵌套容器,允许开发者将不同层次的组件分别放置在不同的容器中,从而实现更加清晰和模块化的依赖管理。

3.5 应用案例

PicoContainer适用于各种Java应用程序,特别是那些需要模块化设计和灵活配置的应用。以下是一个简单的PicoContainer在插件化应用程序中的示例:

import org.picocontainer.DefaultPicoContainer;
import org.picocontainer.MutablePicoContainer;public class PluginManager {private MutablePicoContainer container;public PluginManager() {container = new DefaultPicoContainer();}public void registerPlugin(Class<?> pluginClass) {container.addComponent(pluginClass);}public <T> T getPlugin(Class<T> pluginClass) {return container.getComponent(pluginClass);}
}

以上是PicoContainer的简要介绍和示例代码,PicoContainer通过轻量级和简单的API,为Java开发者提供了一种灵活而可靠的对象依赖管理解决方案。

3.6 自定义组件实例化策略

除了使用默认的组件实例化策略外,PicoContainer还允许开发者定义自定义的组件实例化策略,以满足特定需求。以下是一个自定义组件实例化策略的示例:

import org.picocontainer.ComponentAdapter;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.defaults.DefaultPicoContainer;public class CustomComponentAdapter {public static void main(String[] args) {MutablePicoContainer container = new DefaultPicoContainer();container.addAdapter(new CustomComponentAdapterImpl(MyComponent.class));MyComponent component = container.getComponent(MyComponent.class);component.doSomething();}
}class MyComponent {public void doSomething() {System.out.println("Doing something...");}
}class CustomComponentAdapterImpl implements ComponentAdapter<MyComponent> {private final Class<? extends MyComponent> componentClass;public CustomComponentAdapterImpl(Class<? extends MyComponent> componentClass) {this.componentClass = componentClass;}@Overridepublic MyComponent getComponentInstance() {try {return componentClass.getDeclaredConstructor().newInstance();} catch (Exception e) {throw new RuntimeException("Failed to instantiate component", e);}}// 其他实现方法...
}
3.7 生命周期管理器

PicoContainer允许开发者自定义生命周期管理器,以便更精细地控制对象的生命周期。以下是一个自定义生命周期管理器的示例:

import org.picocontainer.MutablePicoContainer;
import org.picocontainer.lifecycle.DefaultLifecycleState;
import org.picocontainer.lifecycle.LifecycleState;public class CustomLifecycleManager {public static void main(String[] args) {MutablePicoContainer container = new DefaultPicoContainer();container.addComponent(MyComponent.class);container.addComponent(CustomLifecycleManager.class);LifecycleState lifecycleState = new DefaultLifecycleState();container.start();lifecycleState.start();}
}class MyComponent {public void start() {System.out.println("MyComponent started.");}public void stop() {System.out.println("MyComponent stopped.");}
}
3.8 配置文件与注解

PicoContainer支持使用配置文件和注解来进行组件的注册和配置,使得开发者可以选择更适合自己项目的方式进行组件管理。以下是一个使用注解配置的示例:

import org.picocontainer.annotations.Inject;public class TextEditor {private SpellChecker spellChecker;@Injectpublic TextEditor(SpellChecker spellChecker) {this.spellChecker = spellChecker;}public void spellCheck() {spellChecker.checkSpelling();}
}

4. Dagger

Dagger是一个静态依赖注入框架,它在编译时生成依赖注入代码,从而提高了性能和安全性。以下是Dagger的详细介绍和示例代码:

4.1 简介

Dagger是由Google开发的一个轻量级的依赖注入框架,它利用Java的注解处理器技术,在编译时生成依赖注入的代码,从而避免了运行时的反射,提高了性能和安全性。

4.2 编译时生成代码
4.2.1 注解处理器

Dagger通过注解处理器在编译时扫描和处理标记了注解的类和接口,生成对应的依赖注入代码。

4.2.2 生成的依赖注入代码

生成的依赖注入代码会在编译时插入到目标类中,实现了对依赖对象的自动注入,从而避免了手动编写依赖注入的代码。

4.3 优势与适用场景
4.3.1 性能优化

由于依赖注入代码是在编译时生成的,而不是在运行时通过反射来获取,因此Dagger能够提高应用程序的性能。

4.3.2 安全性增强

Dagger通过静态分析依赖关系,能够在编译时检测到依赖关系的错误和不一致,从而提高了代码的安全性。

4.4 使用示例

Dagger适用于各种Java应用程序,特别是那些对性能和安全性要求较高的应用。以下是一个简单的Dagger在Android开发中的示例:

import dagger.Component;@Component
public interface CarComponent {Car getCar();
}public class Car {private Engine engine;@Injectpublic Car(Engine engine) {this.engine = engine;}public void start() {engine.start();System.out.println("Car started!");}
}

以上是Dagger的简要介绍和示例代码,Dagger通过静态依赖注入的方式,在编译时生成依赖注入的代码,从而提高了应用程序的性能和安全性。

4.5 模块化设计

Dagger支持模块化的设计,通过使用@Module注解和@Provides注解,开发者可以将依赖关系的配置和提供分离开来,使得代码更加清晰和可维护。以下是一个简单的模块化配置示例:

import dagger.Module;
import dagger.Provides;@Module
public class EngineModule {@ProvidesEngine provideEngine() {return new Engine();}
}
4.6 生命周期管理

Dagger提供了生命周期管理的支持,开发者可以通过@Singleton注解来标记单例对象,从而实现对单例对象的管理。以下是一个生命周期管理的示例:

import javax.inject.Singleton;@Singleton
public class Engine {public void start() {System.out.println("Engine started!");}
}
4.7 组件化设计

Dagger支持组件化的设计,通过@Component注解和@Inject注解,开发者可以将不同模块的依赖关系组合在一起,形成一个完整的组件。以下是一个组件化设计的示例:

import javax.inject.Inject;@Component(modules = {EngineModule.class})
public interface CarComponent {Car getCar();
}public class Car {private Engine engine;@Injectpublic Car(Engine engine) {this.engine = engine;}public void start() {engine.start();System.out.println("Car started!");}
}
4.8 Android开发中的应用

Dagger在Android开发中有着广泛的应用,它能够帮助开发者更好地管理Activity、Fragment、ViewModel等组件之间的依赖关系,提高了应用程序的可维护性和扩展性。

5. HK2

HK2是GlassFish服务器上的轻量级容器,它提供了依赖注入和生命周期管理等功能。以下是HK2的详细介绍和示例代码:

5.1 概述

HK2是一个开源的依赖注入框架,它是Jersey项目的一部分,被广泛用于GlassFish服务器上的应用程序开发。HK2提供了轻量级的容器和依赖注入机制,使得开发者可以更加方便地管理对象之间的依赖关系。

5.2 特性与功能
5.2.1 依赖注入

HK2支持基于构造函数、字段和方法的依赖注入,开发者可以通过注解来标记需要注入的依赖对象。

5.2.2 生命周期管理

HK2提供了灵活的生命周期管理功能,开发者可以通过自定义生命周期管理器来控制对象的创建、初始化和销毁。

5.3 与Java EE集成
5.3.1 在GlassFish服务器上的应用

HK2被广泛应用于GlassFish服务器上的Java EE应用程序开发中,它与Java EE规范紧密集成,提供了完整的依赖注入和生命周期管理功能。

5.3.2 Jersey框架中的使用

作为Jersey项目的一部分,HK2被用作Jersey框架中的依赖注入容器,为RESTful Web服务的开发提供了便利。

#### 5.4 配置方式HK2提供了多种配置方式来定义和管理对象之间的依赖关系,包括注解、XML配置文件和编程式配置等。以下是一个使用XML配置文件的示例:```java
import org.glassfish.hk2.utilities.binding.AbstractBinder;public class MyBinder extends AbstractBinder {@Overrideprotected void configure() {bind(SpellChecker.class).to(SpellChecker.class);bind(TextEditor.class).to(TextEditor.class);}
}
5.5 事件管理

HK2支持事件管理功能,开发者可以通过触发和监听事件来实现对象之间的解耦和通信。以下是一个简单的事件管理示例:

import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.api.messaging.Topic;public class EventPublisher {private ServiceLocator locator;public EventPublisher(ServiceLocator locator) {this.locator = locator;}public void publishEvent(String message) {Topic<String> topic = locator.getService(Topic.class);topic.publish(message);}
}
5.6 定制化扩展

HK2允许开发者通过定制化扩展来满足特定需求,例如自定义注解、自定义依赖解析器等。以下是一个自定义注解的示例:

import javax.inject.Qualifier;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface Fancy {
}
5.7 HK2与Spring集成

虽然HK2和Spring都是依赖注入框架,但它们可以很好地集成在一起,开发者可以同时使用它们来管理对象的依赖关系。以下是一个HK2与Spring集成的示例:

import org.glassfish.hk2.api.ServiceLocator;
import org.springframework.context.ApplicationContext;public class SpringBridge {private ServiceLocator locator;private ApplicationContext context;public SpringBridge(ServiceLocator locator, ApplicationContext context) {this.locator = locator;this.context = context;}public <T> T getService(Class<T> clazz) {if (locator.hasService(clazz)) {return locator.getService(clazz);} else {return context.getBean(clazz);}}
}
5.8 HK2在MicroProfile中的应用

MicroProfile是一个开源的微服务框架,它提供了一系列标准化的API和规范,HK2作为MicroProfile的一部分,被广泛应用于微服务应用程序的开发中。
以上是HK2的简要介绍和示例代码,HK2作为一个轻量级的依赖注入框架,广泛应用于Java EE应用程序开发中,为开发者提供了方便和灵活的依赖管理机制。

6. CDI (Contexts and Dependency Injection for Java)

CDI是Java中的上下文和依赖注入框架,为Java EE应用程序提供了依赖注入和生命周期管理功能。以下是CDI的详细介绍和示例代码:

6.1 简介

CDI是Java EE 6引入的一个规范,它为Java EE应用程序提供了上下文和依赖注入的功能。CDI允许开发者在Java EE应用程序中使用依赖注入来管理对象之间的依赖关系,从而提高了应用程序的灵活性和可维护性。

6.2 核心概念
6.2.1 上下文

CDI定义了几种上下文,包括请求上下文、会话上下文和应用程序上下文等。不同的上下文对应着不同的生命周期,开发者可以根据需要选择合适的上下文来管理对象的生命周期。

6.2.2 依赖注入

CDI通过@Inject注解实现依赖注入,开发者可以将需要注入的依赖对象声明为@Inject注解的字段、构造函数参数或者方法参数,CDI容器会自动注入这些依赖对象。

6.3 生命周期管理

CDI定义了Bean的生命周期,包括创建、初始化、使用和销毁等阶段。开发者可以通过生命周期回调方法来控制Bean的初始化和销毁过程。

6.3.1 Bean的生命周期

CDI中的Bean可以声明为ApplicationScoped、RequestScoped、SessionScoped等不同的作用域,从而控制Bean的生命周期。

6.3.2 作用域

CDI支持多种作用域,包括应用程序作用域、请求作用域、会话作用域等,开发者可以根据需要选择合适的作用域来管理Bean的生命周期。

6.4 应用示例

以下是一个简单的CDI在Java EE应用程序中的示例:

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;@Named
@RequestScoped
public class HelloBean {@Injectprivate GreetingService greetingService;public String getGreeting() {return greetingService.sayHello();}
}
6.5 事件管理

CDI提供了事件管理功能,开发者可以通过触发和监听事件来实现对象之间的解耦和通信。以下是一个简单的事件管理示例:

import javax.enterprise.event.Event;
import javax.inject.Inject;public class EventProducer {@Injectprivate Event<String> event;public void produceEvent(String message) {event.fire(message);}
}
6.6 定制化扩展

CDI允许开发者通过扩展Bean管理器和事件管理器等方式来定制化扩展框架的功能。以下是一个自定义作用域的示例:

import javax.enterprise.context.NormalScope;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;@NormalScope
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomScope {
}
6.7 CDI与其他Java EE技术集成

CDI与其他Java EE技术如JPA、JSF和JAX-RS等紧密集成,开发者可以轻松地使用CDI来管理这些技术中的对象依赖关系。以下是一个CDI与JPA集成的示例:

import javax.inject.Inject;
import javax.persistence.EntityManager;public class BookService {@Injectprivate EntityManager entityManager;public void save(Book book) {entityManager.persist(book);}
}
6.8 CDI在Java SE中的应用

尽管CDI是Java EE的一部分,但它也可以在Java SE环境中使用,开发者可以通过使用Weld等CDI实现来在Java SE应用程序中实现依赖注入功能。
以上是CDI的简要介绍和示例代码,CDI作为Java EE的一部分,为Java EE应用程序提供了依赖注入和生命周期管理的功能,是Java EE应用程序开发中的重要组成部分。

总结

依赖注入是一种重要的设计模式,能够帮助我们管理对象之间的依赖关系,降低耦合度,提高代码的可测试性和可维护性。在Java领域,有许多优秀的依赖注入框架可供选择,每种框架都有着自己的特点和优势。通过本文的介绍和比较,读者可以更全面地了解Java中的依赖注入框架,选择适合自己项目需求的最佳解决方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/682141.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

three.js 细一万倍教程 从入门到精通(三)

目录 五、详解PBR材质纹理 5.1、详解PBR物理渲染 5.2、标准网格材质与光照物理效果 5.3、置换贴图与顶点细分设置 5.4、设置粗糙度与粗糙度贴图 5.5、设置金属度与金属贴图 5.6、法线贴图应用 5.7、如何获取各种类型纹理贴图 5.8、纹理加载进度情况 单张图片加载 多…

Windows 平台下NDK/CMAKE编译自己程序命令行

CMAKE_BUILD_TYPE 编译类型&#xff08;Debug、Release&#xff09; CMAKE_TOOLCHAIN_FILE 指定 Android 编译工具链文件 CMAKE_SYSTEM_NAME 系统名称&#xff1a;不要改变&#xff1a;值&#xff08;Android&#xff09; ANDROID_NATIVE_API_LEVEL 安卓原…

Transformer实战-系列教程17:DETR 源码解读4(Joiner类/PositionEmbeddingSine类/位置编码/backbone)

&#x1f6a9;&#x1f6a9;&#x1f6a9;Transformer实战-系列教程总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 点我下载源码 DETR 算法解读 DETR 源码解读1&#xff08;项目配置/CocoDetection类&#xff09; …

数据结构-并查集

并查集原理 在一些应用问题中&#xff0c;需要将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个 单元素集合&#xff0c;然后按一定的规律将归于同一组元素的集合合并。在此过程中要反复用到查询一 个元素归属于那个集合的运算。适合于描述这类…

Matplotlib Figure与Axes速成:核心技能一网打尽

Matplotlib Figure与Axes速成&#xff1a;核心技能一网打尽 &#x1f335;文章目录&#x1f335; &#x1f333;引言&#x1f333;&#x1f333; 一、Figure&#xff08;图形&#xff09;&#x1f333;&#x1f341;1. 创建Figure&#x1f341;&#x1f341;2. 添加Axes&#…

NARF关键点提取原理简介

一、NARF2D边缘点探测的矩形平面的边长s和计算点p和上邻域的距离所用的k值 二、障碍物边缘和阴影边缘 三、NARF边缘点探测 四、NARF借助边缘点信息进行关键点检测 本人也是参考其他博主&#xff0c;以及这份英文文献写的(毕竟是英文文献&#xff0c;部分翻译肯定有些误差&…

一探Lepton Search究竟

2024年1月25日&#xff0c;阿里巴巴原技术副总裁在 Twitter 上称用不到 500 行 Python 代码实现了 AI 对话搜索引擎&#xff0c;并在27日附上了开源地址&#xff1a;https://github.com/leptonai/search_with_lepton&#xff0c;截止春节期间已经5.8K的Star。 Twitter截图 Comm…

Spring Security学习(四)——登陆认证(包括自定义登录页)

前言 和前面的文章隔了很长时间才更新Spring Security系列&#xff0c;主要原因一个是之前太忙了&#xff0c;把项目都忙完了&#xff0c;赶上春节假期&#xff0c;就慢慢研究。Spring Security的体系非常复杂&#xff0c;一口吃不了热豆腐&#xff0c;没办法速成&#xff0c;…

第10讲投票创建页面实现

投票创建页面实现 文件选择上传组件 uni-file-picker 扩展组件 安装 https://ext.dcloud.net.cn/plugin?nameuni-file-picker 日期选择器uni-datetime-picker组件 安装 https://ext.dcloud.net.cn/plugin?nameuni-datetime-picker iconfont小图标 https://www.iconfont…

【数据结构与算法】判断二叉树是否完全二叉树

递归方式判断二叉树是否完全二叉树 bool TreeComplete(TreeNode* root) {if (root ! NULL) {if (root->left NULL && root->right ! NULL) {return false; // 左子树空}else if (root->left NULL && root->right NULL) {return true; // 左右子…

【力扣每日一题】力扣987二叉树的垂序遍历

题目来源 力扣987二叉树的垂序遍历 题目概述 给你二叉树的根结点 root &#xff0c;请你设计算法计算二叉树的 垂序遍历 序列。 对位于 (row, col) 的每个结点而言&#xff0c;其左右子结点分别位于 (row 1, col - 1) 和 (row 1, col 1) 。树的根结点位于 (0, 0) 。 二…

仰暮计划|“​他们艰苦半生,但真的希望祖国安祥,山河无恙”

自述&#xff0c;自赎 我没有在那个年代生活过&#xff0c;我一出生就是盛世中国&#xff0c;看遍了祖国的大好河山。但我没想到&#xff0c;走了这么远的路&#xff0c;吃了这么多的苦的爷爷会一直跟我说“不是国家不好&#xff0c;只是中国的钱拿去还债了&#xff0c;过了那…

代码随想录算法训练营Day56|583. 两个字符串的删除操作、72. 编辑距离

目录 583. 两个字符串的删除操作 前言 思路 算法实现 法二 72. 编辑距离 前言 思路 算法实现 总结 583. 两个字符串的删除操作 题目链接 文章链接 前言 本题与上一题不同的子序列相比&#xff0c;变化就是两个字符串都可以进行删除操作了。 思路 利用动规五部曲进…

【AI视野·今日Robot 机器人论文速览 第七十九期】Thu, 18 Jan 2024

AI视野今日CS.Robotics 机器人学论文速览 Thu, 18 Jan 2024 Totally 43 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers CognitiveDog: Large Multimodal Model Based System to Translate Vision and Language into Action of Quadruped Robot Aut…

哈希表 ?

哈希表 首先什么是 哈希表&#xff0c;哈希表&#xff08;英文名字为Hash table&#xff0c;国内也有一些算法书籍翻译为散列表&#xff0c;大家看到这两个名称知道都是指hash table就可以了&#xff09;。 哈希表是根据关键码的值而直接进行访问的数据结构。 这么这官方的解释…

【C++初阶:类和对象(下篇)】初始化列表 | static成员 | 友元

目录 一、构造函数构造函数体赋值&#x1f43e;初始化列表&#x1f43e;&#x1f4a6; explicit关键字 二、static成员&#x1f43e;概念**&#x1f4a6; 关于静态的特性** 三、友元&#x1f4a6; **友元函数**&#x1f4a6; **友元类** **四、内部类** 一、构造函数 构造函数…

Spark的timestamp 数据时间问题

使用Spark来处理国际业务数据&#xff0c;涉及到数据时区转换&#xff0c;在实际项目中出现时区转换问题。 使用代码&#xff1a; spark.conf.set("spark.sql.session.timeZone", "Asia/Hong_Kong") spark.selectExpr("date_format(eff_dt, yyyyMMdd…

VM和Linux安装

VM和Linux安装 一、下载VM 1.官网地址&#xff1a;https://www.vmware.com/cn.html 2.其他地址&#xff1a;http://ww7.nocmd.com/windows/740.html 许可证这个&#xff0c;大家可以自己上网搜索&#xff0c;很容易就搜索到就可以使用了 上面内容就是安装VM的步骤 安…

30. 异常

异常 1. 概述2. Throwable 方法2.1 概述2.2 代码示例 3. 异常分类4. 异常处理方式4.1 JVM默认处理异常4.2 自己处理&#xff08;捕获异常&#xff09;try...catch4.2.1 概述4.2.2 灵魂四问 4.3 抛出处理(throw和throws) 5. 自定义异常5.1 概述5.2 代码示例 6. 异常注意事项 文章…

代码随想录算法训练营第三十一天 |基础知识,455.分发饼干,376.摆动序列,53.最大子序和(已补充)

基础知识&#xff1a; 题目分类大纲如下&#xff1a; #算法公开课 《代码随想录》算法视频公开课(opens new window)&#xff1a;贪心算法理论基础&#xff01;(opens new window),相信结合视频再看本篇题解&#xff0c;更有助于大家对本题的理解。 #什么是贪心 贪心的本质…