使用JSR330提供程序时,Threaded Bean在Spring中不会自动获得环境@Autowired [英] Threaded Beans doesn't get Environment @Autowired to them in Spring when using JSR330 Provider
问题描述
希望这个问题可以自我解释
Hope the Question is self explanatory
ClassA.java
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ClassA implements InterB {
private static int counter=0;
private int objectid = 0;
@Autowired
InterA abcd;
public ClassA() {
super();
this.objectid = ++counter;
}
@Override
public void dododo() {
System.out.println("instance number "+objectid++);
abcd.doit();
}
}
ClassB.java
@Component
@Conditional(OracleDBEngineCondition.class)
public class ClassB extends DummyParent implements InterA {
@Autowired
private Environment env;
@Override
public void doit() {
System.out.println("hoo hoo" +" -- "+env.getProperty("DBENGINE"));
}
}
ClassC.java
@Component("classc")
public class ClassC implements Runnable {
@Autowired
Provider<InterB> classAPrototypeobj;
public void doFromAbove() {
InterB cls = (InterB) classAPrototypeobj.get();
InterB cls1 = (InterB) classAPrototypeobj.get();
cls.dododo();
cls1.dododo();
System.out.println(cls);
System.out.println(cls1);
}
@Override
public void run() {
this.doFromAbove();
}
}
ClassConfig.java
@Configuration
@ComponentScan
public class ClassConfig {
}
主要方法
public static void main(String[] args) {
ClassC obj;
try(AbstractApplicationContext appctx = new AnnotationConfigApplicationContext(ClassConfig.class)) {
obj = (ClassC) appctx.getBean("classc");
}
Thread objThread = new Thread(obj);
objThread.start();
}
更新的主要方法(仍然存在相同的问题)
public static void main(String[] args) {
try(AbstractApplicationContext appctx = new AnnotationConfigApplicationContext(ClassConfig.class)) {
ClassC obj = (ClassC) appctx.getBean("classc");
Thread objThread = new Thread(obj);
objThread.start();
}
}
执行时,这会导致NoSuchBeanDefinitionException
豆的环境"
When Executed, This Causes NoSuchBeanDefinitionException
for the bean 'environment'
但是,当我们在Config类中定义以下内容时,该错误将消失而无任何痕迹. 这是解决方法(但应该由Spring自动注入环境,我们不应该这样做).不知道有多少豆没有被注入/@Autowired
But when we define the following in our Config Class, the error vanishes without a trace. This is the Workaround(but Spring's supposed to inject Environment automagically we shouldn't do this). Not sure how many such beans are not injected/@Autowired
@Bean
public Environment environment(ApplicationContext context) {
return context.getEnvironment();
}
我怀疑这是一个Spring Framework错误...不是吗?
I Suspect this is a Spring Framework Bug... Is it not?
StackTrace:
Exception in thread "Thread-1" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'classA': Unsatisfied dependency expressed through field 'abcd'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'classB': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' available
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:325)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
at org.springframework.beans.factory.support.DefaultListableBeanFactory$DependencyObjectProvider.getObject(DefaultListableBeanFactory.java:1630)
at org.springframework.beans.factory.support.DefaultListableBeanFactory$Jsr330DependencyProvider.get(DefaultListableBeanFactory.java:1699)
at tpt.verifypoc.ClassC.doFromAbove(ClassC.java:28)
at tpt.verifypoc.ClassC.run(ClassC.java:39)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'classB': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' available
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
... 14 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1207)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$ShortcutDependencyDescriptor.resolveShortcut(AutowiredAnnotationBeanPostProcessor.java:740)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1077)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.resolvedCachedArgument(AutowiredAnnotationBeanPostProcessor.java:548)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.access$200(AutowiredAnnotationBeanPostProcessor.java:117)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:577)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
... 25 more
注意:
- 春季:4.3.9.发布
- JSR330:javax.inject版本1
推荐答案
在开始使用要关闭ApplicationContext
的对象之前,我想说这不是Spring中查看代码的错误.或者实际上,您拥有的try-with-resources块可以做到这一点.
I would say this isn't a bug in Spring looking at your code before you start to use the objects you are closing the ApplicationContext
. Or actually the try-with-resources block you have does that.
public static void main(String[] args) {
ClassC obj;
try(AbstractApplicationContext appctx = new AnnotationConfigApplicationContext(ClassConfig.class)) {
obj = (ClassC) appctx.getBean("classc");
}
Thread objThread = new Thread(obj);
objThread.start();
}
与
public static void main(String[] args) {
ClassC obj;
AbstractApplicationContext appctx = new AnnotationConfigApplicationContext(ClassConfig.class)) {
obj = (ClassC) appctx.getBean("classc");
appctx.close();
Thread objThread = new Thread(obj);
objThread.start();
}
在使用对象之前,您要关闭ApplicationContext
.剩下的是ClassC
的实例,其中包含Provided<ClassB>
的半备份代理,需要上下文来查找某些bean.但是,当您从注册表下面提取注册表时,它无法查找这些bean.
You are closing the ApplicationContext
before you are using the objects. What remains is an instanceof ClassC
with a half backed proxy of Provided<ClassB>
which needs to context to lookup certain beans. However it has no-way of looking up those beans as you pulled the registry from underneath it.
当您关闭ApplicationContext
时,您正在关闭您的应用程序.我希望您仍然存在的对象现在无效,因为属于该对象的容器被破坏了.
When you are closing the ApplicationContext
you are shutting down your application. I would expect that your objects that still live are now invalid, because the container the belong to is destroyed.
将代码与JDBC代码进行比较.您正在打开Connection
,关闭连接,然后尝试在关闭的连接上准备语句. JDBC不允许这样做,因为Connection
已关闭,因此无效.
Compare the code to JDBC code. You are opening a Connection
, close the connection and afterwards try to prepare a statement on a closed connection. JDBC won't allow this because the Connection
is closed and thus invalid.
将其与Microsoft Excel进行比较,将其打开,在Sheet中工作,编写宏.关闭excel并期望宏仍然运行.
Compare it to Microsoft Excel, you open it, work in a Sheet, write a macro. Close excel and expect the macro still to run.
这篇关于使用JSR330提供程序时,Threaded Bean在Spring中不会自动获得环境@Autowired的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!