java Spring Boot @Autowired 在运行时创建实例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33740510/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 22:04:04  来源:igfitidea点击:

Spring Boot @Autowired creating instances on a runtime

javaspringdependency-injectionspring-bootautowired

提问by Supo

As most of Spring Boot new users I have a problem with @Autowired :D

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

I've readed a big amount of topics about this annotation here But still can't find proper solution for my problem.

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

Let's suppose that we have this Spring Boot hierarchy:

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

@SpringBootApplication
public class DemoApplication {

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

Class, that we wanna instantiate every time it's called:

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

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

Out get controller, that creates new SomeRepo object every request:

取出控制器,它会在每个请求中创建新的 SomeRepo 对象:

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

Finally, class, that uses @Autowired to create TestWire instances:

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

public class SomeRepo {
    @Autowired
    private TestWire testWire;

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

Let's assume, that we make GET request to "/" several times.

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

So, as a result, TestWire class will isntantiate only when project builds and neither @Scope(value = "prototype"), nor proxyMode = ScopedProxyMode.TARGET_CLASSwont help.

因此,因此,TestWire 类仅在项目构建时才会生效,@Scope(value = "prototype")proxyMode = ScopedProxyMode.TARGET_CLASS 都无济于事。

Any ideas how to create new instances at runtime? I mean, how can we do it in "Spring way"? Without factories and other things, only Spring DI through annotation and configuration.

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

Upd. A piece of stack trace, where instance created:

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

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()

回答by d0x

If I understood you correct you need to annotate the SomeRepolike this:

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

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

Option A:

选项A:

Instead of instantiating the class with new SomeRepo();you ask the BeanFactory.getBean(...)for it.

而不是用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);
    }
}

Option B:

选项 B:

You should also be able to get the Bean like this (over paramters without the beanFactory):

您还应该能够像这样获得 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.
    }
}