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

如何在CDI与Spring中注入带特定初始值的对象?

需求可行性分析与实现方案

你的需求完全可以通过依赖注入实现,核心思路是为不同场景提供不同的InjectedClass实例,并通过限定符或生产者Bean区分注入逻辑。结合你当前Spring+CDI混合的环境,以下是具体实现方案:

先修正代码中的基础问题

首先得把原代码里的几个错误改了,否则后续逻辑无法正常运行:

  1. InjectedClass的getSomeAttribute()方法返回值类型写错了,应该是SomeEnum而非void
  2. MiddleLayer的middleLayerMethod()是private,外部无法调用,需要改为public
  3. InjectedClass同时加了@RequestScoped和@Scope("request"),属于重复注解,保留一个即可

修正后的基础代码:

@Service
@RequestScoped
public class InjectedClass {
     private SomeEnum someAttribute;

     public SomeEnum getSomeAttribute() {
          return someAttribute;
     }

     public void setSomeAttribute(SomeEnum someAttribute) {
          this.someAttribute = someAttribute;
     }
}

@Service
public class MiddleLayer {
         private final InjectedClass injectedClass;

         @Inject
         public MiddleLayer(InjectedClass injectedClass) {
                this.injectedClass = injectedClass;
         }

         public MethodResult middleLayerMethod() {
             if (injectedClass.getSomeAttribute() == SomeEnum.Y) {
                  // 处理请求场景逻辑
             } else if (injectedClass.getSomeAttribute() == SomeEnum.X) {
                  // 处理定时任务场景逻辑
             }
             // 返回结果
         }
}

具体实现方案:用CDI限定符区分实例

这种方案最灵活,能精准控制不同场景下的注入实例:

1. 定义限定符注解

创建一个自定义限定符,标记定时任务专用的实例:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
public @interface PeriodicInstance {
}

2. 编写生产者Bean,生成定时任务专用的InjectedClass实例

专门为定时场景创建一个属性固定为X的InjectedClass单例:

@Component
public class InjectedClassProducer {

    @Produces
    @PeriodicInstance
    @Singleton
    public InjectedClass createPeriodicInjectedClass() {
        InjectedClass instance = new InjectedClass();
        instance.setSomeAttribute(SomeEnum.X);
        return instance;
    }
}

3. 为MiddleLayer配置多场景注入

因为MiddleLayer在请求场景用请求作用域的InjectedClass,定时场景用专用实例,我们可以通过生产者Bean生成不同的MiddleLayer实例:

@Component
public class MiddleLayerProducer {

    // 生成请求场景用的MiddleLayer,使用默认的请求作用域InjectedClass
    @Produces
    @RequestScoped
    public MiddleLayer createRequestMiddleLayer(InjectedClass injectedClass) {
        return new MiddleLayer(injectedClass);
    }

    // 生成定时任务用的MiddleLayer,使用带PeriodicInstance限定符的InjectedClass
    @Produces
    @PeriodicInstance
    @Singleton
    public MiddleLayer createPeriodicMiddleLayer(@PeriodicInstance InjectedClass injectedClass) {
        return new MiddleLayer(injectedClass);
    }
}

4. 修改控制器和定时任务的注入逻辑

  • 控制器保持默认注入,使用请求场景的MiddleLayer:
public class SomeController { 
         private final MiddleLayer middleLayer;

         @Inject
         public SomeController(MiddleLayer middleLayer) {
                this.middleLayer = middleLayer;
         }

         public void someMethod () {
               MethodResult result = middleLayer.middleLayerMethod();
               // 后续逻辑不变
         }
}
  • 定时任务通过限定符注入专用的MiddleLayer:
@Component
public class PeriodicActivity {
        private final MiddleLayer middleLayer;

        @Inject
        public PeriodicActivity(@PeriodicInstance MiddleLayer middleLayer) {
                this.middleLayer = middleLayer;
        }

        public void method () {
               MethodResult result = middleLayer.middleLayerMethod();
               // 后续逻辑不变
        }
}

替代方案:拆分MiddleLayer为两个Bean

如果不想用生产者Bean,也可以直接创建两个MiddleLayer的变体,分别对应不同场景:

// 请求场景专用MiddleLayer
@Service
public class RequestMiddleLayer extends MiddleLayer {
    @Inject
    public RequestMiddleLayer(InjectedClass injectedClass) {
        super(injectedClass);
    }
}

// 定时任务专用MiddleLayer
@Service
public class PeriodicMiddleLayer extends MiddleLayer {
    @Inject
    public PeriodicMiddleLayer(@PeriodicInstance InjectedClass injectedClass) {
        super(injectedClass);
    }
}

然后控制器注入RequestMiddleLayer,定时任务注入PeriodicMiddleLayer即可,这种方式更直观,适合逻辑差异较大的场景。

关键注意点

  • 定时任务属于无请求上下文的场景,直接注入@RequestScoped的InjectedClass会抛出作用域异常,必须为定时场景单独创建非请求作用域的实例
  • 如果你的Spring版本较低,可能需要调整CDI注解的兼容性,确保@Qualifier和@Produces能被Spring正确识别

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:10:18