如何从运行时创建的非bean对象自动关联Springbean?

如何从运行时创建的非bean对象自动关联Springbean?,spring,autowired,configurable,Spring,Autowired,Configurable,我有一些Jpa存储库和几个实体类。我需要为我的一个实体创建一个辅助对象。在该助手中,我使用@Autowire访问Jpa存储库 @Entity class A { @Transient Helper helper; ... } class Helper { A a; @Autowired CRepository repo; public Helper(A a) { this.a = a; } } 但是,回购协

我有一些Jpa存储库和几个实体类。我需要为我的一个实体创建一个辅助对象。在该助手中,我使用@Autowire访问Jpa存储库

@Entity
class A {
    @Transient
    Helper helper;

    ...

}

class Helper {
    A a;
    @Autowired
    CRepository repo;

    public Helper(A a) {
        this.a = a;
    }
}
但是,回购协议始终为空。我尝试过使用SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this)和@Configurable,但都失败了。有人能给我一些提示吗

顺便说一句,在rest控制器中实例化了一个


谢谢

您不能在助手类中自动关联任何内容,因为它不是由Spring管理的。 您可以使用以下方法:

public class HelperManager {
  @Autowired
  private ApplicationContext context;

  public Helper getHelper(A a) {
    return context.getBean(Helper.class, a);
}
将Helper配置为原型bean:

@Configuration
public class MyConfiguration {
  @Bean
  public HelperManager helperManager() {
    return new HelperManager();
  }

  @Bean
  @Scope("prototype")
  public Helper helper(A a) {
    return new Helper(a);
  }
}
最后在控制器中:

@Controller
public class MyController {
  @Autowired
  private HelperManager helperManager;

  public someMethodWhereToInstanceYourHelper(A a) {
    ...
    Helper helper = helperManager.getHelper(a);
    ...
  }
}

使用构造函数注入而不是字段注入;不管怎样,这始终是一个最佳实践。然后,将
A
注入控制器并将其作为构造函数参数传递是很简单的

@可配置注释可以正常工作,但您需要在任何配置类中使用@EnableSpringConfigured注释才能使其正常工作。请阅读我在其他stackoverflow帖子中的回答:

实体类不应包含任何帮助程序,即使是暂时的。对于干净的设计,您需要分离关注点,因此实体不应该知道您的业务逻辑。我无法帮助您更多,因为我不知道该助手的目标是什么,但您还有其他选择:

备选方案1(根据您的描述,helper似乎是一个有状态bean,所以它不是@Service的候选者,我个人认为它应该是)

备选方案2(使您的Helper类成为无状态的,这样spring就可以知道您的bean,而不需要额外的东西,比如@configurable/@enablespringconfiguration)


您可以使用BeanUtil类来获取在Springl中创建的任何bean

@Service
public class BeanUtil implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static <T> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }
}

可配置允许您准确地执行此操作。
@Controller
public MyController {
     @Autowired Helper helper;  // CRepository is correctly autowired

    @RequestMapping(...)
    public void processRequest() {
        A a = new A();
        ...
        helper.doSomething(a);
    }
}

@Service
public class Helper {
    // A a;  remove dependency to A to make it stateless
    @Autowired
    CRepository repo;

    public Helper() {
    }

    public void doSomething(A a) {
        ...
        repo.save(a);
    }
}
@Service
public class BeanUtil implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static <T> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }
}
MyBean obj = BeanUtil.getBean(MyBean.class);