You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CDI中自动注入同版本包下RequestDataProvider至VersionInfo的方法

Feasible Solutions to Auto-Inject Matching RequestDataProvider into VersionInfo

Yes, absolutely! In Java EE, you can leverage CDI (Contexts and Dependency Injection) features to make this work seamlessly. Below are two practical approaches tailored to your package structure:


Approach 1: Use Qualifiers to Group Cohesive Service/Provider Pairs

This is the most idiomatic Java EE solution, as it explicitly marks which RequestDataProvider belongs to which MainService set, keeping your code type-safe and maintainable.

Step 1: Define Custom Qualifier Annotations

Create qualifiers to distinguish between V1 and V2 component groups:

// com/common/qualifiers/V1.java
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
public @interface V1 {}
// com/common/qualifiers/V2.java
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
public @interface V2 {}

Step 2: Annotate Your Components

Apply the qualifiers to your MainService and RequestDataProvider classes in each package:

// com/V1/MainService.java
@V1
@Stateless // Or @ApplicationScoped, based on your scope needs
public class MainService {
    @Inject
    @V1
    private RequestDataProvider dataProvider;
    
    @Inject
    private VersionInfo versionInfo;
    
    // Your service business logic here
}
// com/V1/RequestDataProvider.java
@V1
@ApplicationScoped
public class RequestDataProvider {
    // Provider-specific logic here
}

Repeat this pattern for the V2 package, replacing @V1 with @V2.

Step 3: Inject the Matching Provider in VersionInfo

In VersionInfo, use Instance<RequestDataProvider> to dynamically select the provider that matches the qualifier of the active MainService:

// com/common/VersionInfo.java
@ApplicationScoped
public class VersionInfo {
    @Inject
    private Instance<RequestDataProvider> dataProviderInstance;
    
    @Inject
    private BeanManager beanManager;
    
    public RequestDataProvider getMatchingProvider(MainService mainService) {
        // Get the qualifiers attached to the calling MainService
        Set<Annotation> serviceQualifiers = beanManager.getBeans(mainService.getClass())
                .iterator().next().getQualifiers();
        
        // Find the RequestDataProvider with identical qualifiers
        for (RequestDataProvider provider : dataProviderInstance) {
            Set<Annotation> providerQualifiers = beanManager.getBeans(provider.getClass())
                    .iterator().next().getQualifiers();
            if (providerQualifiers.equals(serviceQualifiers)) {
                return provider;
            }
        }
        throw new IllegalStateException("No matching RequestDataProvider found for this MainService");
    }
}

Then in your MainService, call versionInfo.getMatchingProvider(this) to retrieve the correct provider.


Approach 2: Programmatic Lookup by Package Using BeanManager

If you prefer to avoid qualifiers, you can directly look up the RequestDataProvider by constructing its fully qualified class name from the MainService's package:

// com/common/VersionInfo.java
@ApplicationScoped
public class VersionInfo {
    @Inject
    private BeanManager beanManager;
    
    public RequestDataProvider getPackageMatchingProvider(MainService mainService) {
        String servicePackage = mainService.getClass().getPackageName();
        String providerClassName = servicePackage + ".RequestDataProvider";
        
        try {
            Class<?> providerClass = Class.forName(providerClassName);
            Bean<?> providerBean = beanManager.getBeans(providerClass).iterator().next();
            CreationalContext<?> ctx = beanManager.createCreationalContext(providerBean);
            return (RequestDataProvider) beanManager.getReference(providerBean, providerClass, ctx);
        } catch (ClassNotFoundException e) {
            throw new IllegalStateException("RequestDataProvider not found in package: " + servicePackage, e);
        }
    }
}

This method relies on consistent naming conventions between your MainService and RequestDataProvider packages, which works well if your structure is stable.


Both approaches are valid, but Approach 1 is recommended because it follows CDI best practices, avoids hardcoded package names, and makes component relationships explicit.

内容的提问来源于stack exchange,提问作者carbolymer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:34:32