如何在 spring 中为运行时动态创建的对象注入依赖项?

mad*_*l10 4 java spring dependency-injection factory-pattern spring-boot

public class PlatformEventFactory {

    public PlatformEvent createEvent(String eventType) {
        if (eventType.equals("deployment_activity")) {
            return new UdeployEvent();
        }


        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一个工厂类,它PlatformEvent根据 eventType创建类型对象。

在创建对象private RedisTemplate<String, Object> template后,UdeployEvent 类依赖于我要注入的UdeployEvent对象。

@Component
public class UdeployEvent implements PlatformEvent {

    private RedisTemplate<String, Object> template;
    private UDeployMessage uDeployMessage;

    private static final Logger logger = LoggerFactory.getLogger(UdeployEvent.class);

    public UdeployEvent() {
        uDeployMessage = new UDeployMessage();
    }


    /*public void sendNotification() {

    }*/

    public RedisTemplate<String, Object> getTemplate() {
        return template;
    }

    @Autowired
    public void setTemplate(RedisTemplate<String, Object> template) {
        this.template = template;
        System.out.println("Injection done");
    }
}
Run Code Online (Sandbox Code Playgroud)

当为UdeployEvent我返回新对象时,模板出现空指针异常。我相信这是因为它不是指在 spring 启动时创建的同一个 bean。如何在运行时为新创建的对象注入依赖项。

Ken*_*kov 6

您不应手动创建组件。让 Spring 来做这件事。使用ApplicationContext获得组件的实例。所有字段将被自动注入:

@Component
public class PlatformEventFactory {

    @Autowired
    private ApplicationContext context;

    public PlatformEvent createEvent(String eventType) {
        if (eventType.equals("deployment_activity")) {                
            return context.getBean(UdeployEvent.class);
        }

        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

要使 Spring 在UdeployEvent每次请求时创建组件的新实例,请将组件的范围指定为SCOPE_PROTOTYPE

@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class UdeployEvent implements PlatformEvent {

    private RedisTemplate<String, Object> template;

    public RedisTemplate<String, Object> getTemplate() {
        return template;
    }

    @Autowired
    public void setTemplate(RedisTemplate<String, Object> template) {
        this.template = template;
        System.out.println("Injection done");
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

现在,每次调用context.getBean(UdeployEvent.class)Spring 时,都会创建具有完全初始化依赖项的新组件实例。