Java Spring检查是否实例化了惰性bean

Java 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

假设在自定义范围内有一个lazy Spring管理的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
        }
    } 
}
还有另一个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