【问题标题】:Spring Boot @Autowired creating instances on a runtimeSpring Boot @Autowired 在运行时创建实例
【发布时间】:2016-02-17 20:30:09
【问题描述】:

作为大多数 Spring Boot 新用户,我对 @Autowired 有疑问:D

我在这里阅读了大量关于此注释的主题但仍然无法找到适合我的问题的解决方案。

假设我们有这个 Spring Boot 层次结构:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

类,我们想在每次调用时实例化它:

@Service
public class TestWire {
    public TestWire() {
        System.out.println("INSTANCE CREATED: " + this);
    }
}

Out get 控制器,每个请求都会创建新的 SomeRepo 对象:

@RestController
public class CreatingRepo {
    @RequestMapping("/")
    public void postMessage() {
        SomeRepo repo = new SomeRepo();
    }
}

最后,使用@Autowired 创建TestWire 实例的类:

public class SomeRepo {
    @Autowired
    private TestWire testWire;

    public SomeRepo() {
        System.out.println(testWire.toString());
    }
}

假设我们多次向“/”发出 GET 请求。

因此,TestWire 类仅在项目构建时才会实例化,并且 @Scope(value = "prototype")proxyMode = ScopedProxyMode.TARGET_CLASS 都不会帮助。

任何想法如何在运行时创建新实例?我的意思是,我们如何以“春天的方式”做到这一点?没有工厂和其他东西,只有 Spring DI 通过注解和配置。

更新。一段堆栈跟踪,其中创建了实例:

2015-11-16 20:30:41.032  INFO 17696 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
INSTANCE CREATED: com.example.TestWire@56c698e3
2015-11-16 20:30:41.491  INFO 17696 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@12f41634: startup date [Mon Nov 16 20:30:37 MSK 2015]; root of context hierarchy
2015-11-16 20:30:41.566  INFO 17696 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public void com.example.CreatingRepo.postMessage()

【问题讨论】:

  • 问题是您使用的是new SomeRepo(),因此SomeRepo 的实例不是由Spring 管理的。如果您希望/需要每次执行 CreatingRepo#postMessage 并使用 new 运算符并让 Spring 管理 bean 的实例(即启用自动装配功能和其他 Spring 产品)时获取 SomeRepo 的新实例,您可以使用@Configurable.
  • @LuiggiMendoza 我已经更改了我的控制器,现在它使用@Autowire 来注入 SomeRepo 类,该类使用@Configurable@Service 进行注释。看来我使用 SomeRepo 的注入是错误的,因为它仍然使用相同的 TestWire 实例。您有任何示例或链接吗?
  • 您可以尝试对@Configurable 的工作原理进行一些研究,例如您需要启用方面编织。
  • @LuiggiMendoza,感谢您的信息。现在对我来说有点棘手,但我想,我很快就会回来详细审查)

标签: java spring dependency-injection spring-boot autowired


【解决方案1】:

如果我理解你的正确,你需要像这样注释SomeRepo

@Service
@Scope(value = "prototype")
public class SomeRepo { 
// ...
}

选项 A:

您无需使用new SomeRepo(); 来实例化该类,而是向BeanFactory.getBean(...) 索取。

@RestController
public class CreatingRepo {
    @Autowired
    BeanFactory beanFactory;

    @RequestMapping("/")
    public void postMessage() {
        // instead of new SomeBean we get it from the BeanFactory
        SomeRepo repo = beanFactory.getBean(SomeRepo.class);
    }
}

选项 B:

您也应该能够像这样获得 Bean(在没有beanFactory 的参数上):

@RestController
public class CreatingRepo {

    @RequestMapping("/")
    public void postMessage(SomeRepo repo) {
        // instead of the BeanFactory and using new SomeRepo you can get it like this.
    }
}

【讨论】:

  • @Supo 奇怪的是,这与您的要求相矛盾:我们如何以“春天的方式”做到这一点?没有工厂和其他东西,只有 Spring DI 通过注解和配置.
  • @LuiggiMendoza,不幸的是我现在没有时间做更好的研究(截止日期还有 5 小时 :)),但这对我来说是分叉的。在工厂下,我的意思有点不同(每次我们调用工厂方法时,我们都会显式调用new Bean)。我不知道这种类型的 bean 创建(我的意思是在 xml 配置之外)。谢谢你的帮助,无论如何,我下周末回家试试:D
  • 我已经更新了帖子以展示如何避免 BeanFactory。
猜你喜欢
  • 1970-01-01
  • 2019-09-13
  • 2019-12-24
  • 1970-01-01
  • 2020-02-09
  • 1970-01-01
  • 1970-01-01
  • 2020-12-21
  • 2019-02-20
相关资源
最近更新 更多