【问题标题】:How to inject a prototype bean in a Spring singleton Controller如何在 Spring 单例控制器中注入原型 bean
【发布时间】:2016-01-02 05:19:59
【问题描述】:

我有一个用于原型 bean 的 FactoryBean,如下所示:

@Component
public class ApplicationConfigurationMergedPropertiesFactoryBean implements SmartFactoryBean<Properties>{

    @Autowired
    protected ApplicationConfigurationInitializer initializer;

    @Override
    public Properties getObject() throws Exception {
        return XXXXXXXXXX;
    }

    @Override
    public Class<?> getObjectType() {
        return Properties.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }

    @Override
    public boolean isPrototype() {
        return true;
    }

我想在控制器中自动装配它,并且每当我尝试访问属性时(通过p.get(),从ApplicationConfigurationMergedPropertiesFactoryBean.getObject() 获得一个新原型实例:

@Controller
@RequestMapping("/home")
public class HomeController {

  @Autowired
  @Qualifier("applicationConfig")
  private Properties p;

  @RequestMapping(method = { RequestMethod.GET, RequestMethod.POST })
  public String home() {
        System.out.println(p.get("something"));
  }

但是这从不调用 getObject()。如果我注入 ApplicationContext 并直接访问 bean,它就可以工作,提供一个全新的 Properties bean:

@Controller
@RequestMapping("/home")
public class HomeController {

    @Autowired
    @Qualifier("applicationConfig")
    private Properties p;

    @Autowired
    private ApplicationContext ac;

    @RequestMapping(method = { RequestMethod.GET, RequestMethod.POST })
    public String home() {
        System.out.println(p.get("something"));  //WRONG!!!!
        System.out.println(ac.getBean("applicationConfig", Properties.class).getProperty("something")); //OK!!!!

如何使用@Autowired 注入直接实现这一点?

【问题讨论】:

标签: java spring spring-mvc dependency-injection


【解决方案1】:

您是否考虑过将控制器类也设为原型范围?

@Controller
@Scope("prototype")
@RequestMapping("/home")
public class HomeController {

【讨论】:

  • 我宁愿它是一个单例,我真的不需要为每个请求创建一个新的控制器实例......
  • 知道了,是的,这是我知道的唯一方法,您可以在不为每个请求明确调用您的工厂的情况下完成您想要的事情。我曾经有同样的感觉,不需要为每个请求创建控制器,但你可能想考虑如果它实现了你想要的行为并让 Spring 处理你不处理的事情,是否真的那么糟糕想要明确。您可能会发现,如果您测量每次创建控制器的性能,它增加的开销可以忽略不计。
【解决方案2】:

直接注入工厂:

@Controller
@RequestMapping("/home")
public class HomeController {

    @Autowired
    @Qualifier("applicationConfig")
    private SmartFactoryBean p;

    @Autowired
    private ApplicationContext ac;

    @RequestMapping(method = { RequestMethod.GET, RequestMethod.POST })
    public String home() {
        System.out.println(p.getObject()); 
   ....
   }

【讨论】:

  • 是的,这是一个解决方案。我想知道是否有比直接调用工厂更少的手动操作。就像当你有一个 @Scoped("session" 或 "request") bean 时,它会在控制器中为每个请求自动刷新
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-14
相关资源
最近更新 更多