Java Spring检查是否实例化了惰性bean
假设在自定义范围内有一个lazy Spring管理的beanJava Spring检查是否实例化了惰性bean,java,spring,Java,Spring,假设在自定义范围内有一个lazy Spring管理的beanMyBean,如下所示: @Configuration public class MyConfiguration { @Scope("custom") @Lazy @Bean MyBean myBean () { return new MyBean(); } } @Component class MyBeanCounter { @Autowired MyBea
MyBean
,如下所示:
@Configuration
public class MyConfiguration {
@Scope("custom")
@Lazy
@Bean
MyBean myBean () {
return new MyBean();
}
}
@Component
class MyBeanCounter {
@Autowired
MyBean myBean;
void checkIfMyBeanIsInstantiated () {
if (myBean != null) {// this doesn't trigger the bean creation
// there is an instance
}
}
}
还有另一个Spring管理的bean:
@Component
class MyBeanCounter{
void checkIfMyBeanIsInstantiated () {
// Check if there is an instance of MyBean within Spring context
}
}
在CheckIfMyBeanInstanced
中,我想检查Spring上下文中是否有MyBean实例,而不触发bean创建
显而易见的想法是像这样注入MyBean
:
@Configuration
public class MyConfiguration {
@Scope("custom")
@Lazy
@Bean
MyBean myBean () {
return new MyBean();
}
}
@Component
class MyBeanCounter {
@Autowired
MyBean myBean;
void checkIfMyBeanIsInstantiated () {
if (myBean != null) {// this doesn't trigger the bean creation
// there is an instance
}
}
}
上述解决方案的问题是,每当MyBean
实例根据其自定义范围更改时,我都必须刷新MyBeanCounter
上述解决方案不起作用,因为@Autowired-MyBean-MyBean代码>会实例化bean。将其替换为@Lazy@Autowired-MyBean-MyBean代码>仍然不起作用,因为我最终使用了注入代理
有什么解决方案吗?对于“刷新”问题,请确保您的作用域使用代理,这将帮助您检索正确的bean实例。您可以将proxyMode=ScopedProxyMode.TARGET\u CLASS
添加到@Scope
注释中。这样,您就不需要重新加载MyBeanCounter
,以便它使用新实例
@Component
class MyBeanCounter {
@Autowired
private ApplicationContext appContext;
void checkIfMyBeanIsInstantiated () {
String[] beans= appContext.getBeanDefinitionNames();
// now loop the beans and if it is Null it has not been Instantiated
// beans will contain all the beans name
}
}
至于检查bean是否初始化了bean,您可以直接检查它是否与null不同。未初始化的bean等于null
因此,您的CheckIfMyBeanisInstanced
可以如下所示:
void checkIfMyBeanIsInstantiated () {
if(myBean == null) {
// Not initialized
return;
}
// Initialized
}
还要确保将required=false
添加到@Autowired注释中:
@Autowired(required = false)
MyBean myBean;
如果required未设置为false(默认值为true),myBean
将立即实例化,因为Spring将其视为MyBeanCounter
的必需组件。通过将其设置为false并使用@Lazy
,Spring只会在调用它时初始化它。
但请确保始终测试它是否为null,以避免出现NullPointerException
对于“刷新”问题,请确保您的作用域使用代理,该代理将帮助您检索正确的bean实例。您可以将proxyMode=ScopedProxyMode.TARGET\u CLASS
添加到@Scope
注释中。这样,您就不需要重新加载MyBeanCounter
,以便它使用新实例
至于检查bean是否初始化了bean,您可以直接检查它是否与null不同。未初始化的bean等于null
因此,您的CheckIfMyBeanisInstanced
可以如下所示:
void checkIfMyBeanIsInstantiated () {
if(myBean == null) {
// Not initialized
return;
}
// Initialized
}
还要确保将required=false
添加到@Autowired注释中:
@Autowired(required = false)
MyBean myBean;
如果required未设置为false(默认值为true),myBean
将立即实例化,因为Spring将其视为MyBeanCounter
的必需组件。通过将其设置为false并使用@Lazy
,Spring只会在调用它时初始化它。
但请确保始终测试它是否为null,以避免出现NullPointerException
既然您似乎并不真正需要或想要检查中的实例,那么就这样做吧
@Configuration
public class MyConfiguration {
@Scope("custom")
@Lazy
@Bean
MyBean myBean (MyBeanCounter counter) {
counter.setBeanInstantiated();
return new MyBean();
}
}
@Component
class MyBeanCounter {
@Setter
private boolean beanInstantiated;
void checkIfMyBeanIsInstantiated () {
if (beanInstantiated) {
// there is an instance
}
}
}
因为您似乎并不真正需要或想要检查中的实例,所以只需这样做
@Configuration
public class MyConfiguration {
@Scope("custom")
@Lazy
@Bean
MyBean myBean (MyBeanCounter counter) {
counter.setBeanInstantiated();
return new MyBean();
}
}
@Component
class MyBeanCounter {
@Setter
private boolean beanInstantiated;
void checkIfMyBeanIsInstantiated () {
if (beanInstantiated) {
// there is an instance
}
}
}
如果需要刷新,则作用域已断开。该作用域应生成代理,并且代理应根据作用域获取正确的对象。您不需要刷新服务和其他组件中的任何内容。如果您构建了一个需要它的作用域,那么您的作用域实现错误。原型不是一个作用域bean。您可以创建一个范围化的原型,其结果是为在该bean上调用的每个方法创建一个新的bean实例,但是对于正在使用的bean(服务),这一切都是透明处理的。这同样适用于请求、会话、线程范围的bean。您将获得一个代理,该代理将根据作用域委托该bean的适当实例。正如我在最初的评论中所述,您正在尝试修复不应该修复的内容,这些内容来自错误实现的作用域。@M.Deinum“错误实现的作用域”是org.springframework.context.support.SimpleThreadScope
。我没有实施任何措施。默认情况下,此作用域不提供任何代理。我发现,为了有一个代理作用域(您称之为未中断),我必须在目标bean上使用JDK代理机制的@Scope(value=“Scope\u name”,proxyMode=ScopedProxyMode.TARGET\u CLASS)
或ScopedProxyMode.INTERFACES
。作用域实现与代理部分无关。如果需要刷新它,则说明您的作用域已断开。作用域应生成代理,并且代理应根据作用域获取正确的对象。您不需要刷新服务和其他组件中的任何内容。如果您构建了一个需要它的作用域,那么您的作用域实现错误。原型不是一个作用域bean。您可以创建一个范围化的原型,其结果是为在该bean上调用的每个方法创建一个新的bean实例,但是对于正在使用的bean(服务),这一切都是透明处理的。这同样适用于请求、会话、线程范围的bean。您将获得一个代理,该代理将根据作用域委托该bean的适当实例。正如我在最初的评论中所述,您正在尝试修复不应该修复的内容,这些内容来自错误实现的作用域。@M.Deinum“错误实现的作用域”是org.springframework.context.support.SimpleThreadScope
。我没有实施任何措施。默认情况下,此作用域不提供任何代理。我发现,为了有一个代理作用域(您称之为未中断),我必须在目标bean上使用JDK代理机制的@Scope(value=“Scope\u name”,proxyMode=ScopedProxyMode.TARGET\u CLASS)
或ScopedProxyMode.INTERFACES
。作用域实现与代理部分无关。getBeanDefinitionNames
为我提供了所有的bean定义,无论当前的实例化如何。getBeanDefinitionNames