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


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

        return null;
    }
}

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

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

@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");
    }
}

当返回新对象时UdeployEvent我得到模板的空指针异常。我相信这样做的原因是因为它不是指春天启动时产生的豆子。如何在运行时为新创建的对象注入依赖项。

不应手动创建组件。让春天来做这件事。使用 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;
    }
}

要使 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");
    }
    ...
}

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

手动创建对象时,不会在创建的对象中执行依赖项注入,并且字段为 null。

最简单的方法是使用AutowireCapableBeanFactory autowireBean()例:

@Component
public class PlatformEventFactory {
    @Autowired  
    private AutowireCapableBeanFactory beanFactory;
    public PlatformEvent createEvent(String eventType) {
        if (eventType.equals("deployment_activity")) {
            PlatformEvent platformEvent = new UdeployEvent();
            beanFactory.autowireBean(platformEvent);
            return platformEvent;
        }
        return null;
    }
}

beanFactory.autowireBean(platformEvent)应该注入您的田地,它应该可以正常工作。

@Configuration有更多的扩展解决方案,但它们会产生大量样板代码,并且不会提供太多回报。

春天没有看到更清洁的解决方案(如Guice的@AssistedInject(。

源:http://www.kubrynski.com/2013/09/injecting-spring-dependencies-into-non.html

你应该把你的豆子注释为SCOPE_PROTOTYPE,正如@ken-bekov指出的那样。

要获得原型 Bean 的实例,您可以使用注入(自动连线(org.springframework.beans.factory.ObjectProvider<T> ,而不是 ApplicationContext 。此提供程序的类型参数应为 UdeployEvent
此外,还可以get方法中为类构造函数或工厂方法提供参数。这种方法的一个缺点是不会静态检查对get的调用。

解决问题的另一种方法是尝试使用Google的AutoFactory。

最新更新