java 在动态创建的类中实例化 spring bean

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2867997/
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-10-29 23:13:08  来源:igfitidea点击:

Instantiating spring beans in dynamically created classes

javaspring

提问by Xetius

I am dynamically creating classes which contain spring beans, however the beans are not getting instantiated or initialised, leaving them as null.

我正在动态创建包含 spring bean 的类,但是 bean 没有被实例化或初始化,将它们保留为 null。

How do I make sure that a dynamically created class creates all of its spring beans properly?

我如何确保动态创建的类正确创建了它的所有 spring bean?

This is how I am dynamically creating the class:

这就是我动态创建类的方式:

Class ctransform;
try {
    ctransform = Class.forName(strClassName);
    Method handleRequestMethod = findHandleRequestMethod(ctransform);
    if (handleRequestMethod != null) {
        return (Message<?>) handleRequestMethod.invoke(ctransform.newInstance(), message);
            }
    }

This leaves all spring bean objects within ctransform (of type strClassName) as null.

这将 ctransform(类型为 strClassName)中的所有 spring bean 对象保留为 null。

回答by Bozho

Whenever you instantiate classes, they are notspring-managed. Spring has to instantiate classes so that it can inject their dependencies. This with the exception of the case when you use @Configurableand <context:load-time-weaver/>, but this is more of a hack and I'd suggest against it.

当你实例化类,它们是不是春天的管理。Spring 必须实例化类,以便它可以注入它们的依赖项。除了您使用@Configurableand的情况外<context:load-time-weaver/>,这更像是一种黑客行为,我建议不要这样做。

Instead:

反而:

  • make the bean of scope prototype
  • obtain the ApplicationContext(in a web-app this is done via WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext))
  • if the classes are not registered (and I assume they are not), try casting to StaticApplicationContext(I'm not sure this will work), and call registerPrototype(..)to register your classes in the context. If this doesn't work, use GenericContextand its registerBeanDefinition(..)
  • get all the instances that match your type, using appContext.getBeansOfType(yourclass); or if you just registered it and know its name - use just appContext.getBean(name)
  • decide which one is applicable. Usually you will have only one entry in the Map, so use it.
  • 制作作用域的bean prototype
  • 获取ApplicationContext(在网络应用程序中,这是通过WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)
  • 如果类未注册(我假设它们没有注册),请尝试强制转换为StaticApplicationContext(我不确定这是否可行),然后调用registerPrototype(..)在上下文中注册您的类。如果这不起作用,请使用GenericContext及其registerBeanDefinition(..)
  • 使用appContext.getBeansOfType(yourclass);获取与您的类型匹配的所有实例;或者,如果您刚刚注册并知道它的名称 - 只需使用appContext.getBean(name)
  • 决定哪一个适用。通常您在 中只有一个条目Map,因此请使用它。

But I would generally avoid reflection on spring beans - there should be another way to achieve the goal.

但我通常会避免对春豆的反思 - 应该有另一种方式来实现目标。



Update:I just thought of an easier solution, that will work if you don't need to register the beans - i.e. that your dynamically generated classes won't be injected in any other dynamically generated class:

更新:我只是想到了一个更简单的解决方案,如果您不需要注册 bean,它将起作用 - 即您的动态生成的类不会被注入到任何其他动态生成的类中:

// using WebApplicationContextUtils, for example
ApplicationContext appContext = getApplicationContext(); 
Object dynamicBeanInstance = createDyamicBeanInstance(); // your method here
appContext.getAutowireCapableBeanFactory().autowireBean(dynamicBeanInsatnce);

And you will have your dependencies set, without having your new class registered as a bean.

并且您将设置依赖项,而无需将新类注册为 bean。

回答by Snehal

You need Spring container to instantiate the class than using reflection to instantiate. To make a bean scoped to prototype use the following syntax:

您需要 Spring 容器来实例化类,而不是使用反射来实例化。要使 bean 范围限定为原型,请使用以下语法:

<bean id="prototypeBean" class="xyz.PrototypeBean" scope="prototype">
  <!-- inject dependencies here as required -->
</bean>

Then instantiate prototype bean using the following code:

然后使用以下代码实例化原型 bean:

ApplicationContext applicationContext = new ClassPathXmlApplicationContext ( "applicationContext.xml" );

PrototypeBean prototypeBean = ( PrototypeBean ) applicationContext.getBean ( "prototypeBean" );