Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从Spring获取实例化bean的列表?_Spring_Junit_State - Fatal编程技术网

如何从Spring获取实例化bean的列表?

如何从Spring获取实例化bean的列表?,spring,junit,state,Spring,Junit,State,我的Spring上下文中有几个bean具有状态,所以我想在单元测试之前/之后重置该状态 我的想法是向助手类中添加一个方法,该类只需遍历Spring上下文中的所有bean,检查在@之前或@之后注释的方法并调用它们 如何从ApplicationContext获取实例化的bean列表 注意:简单地迭代所有已定义bean的解决方案是无用的,因为我有许多惰性bean,其中一些不能实例化,因为这会导致某些测试失败(例如,我有一个bean需要java.sql.DataSource,但测试可以工作,因为它们不需

我的Spring上下文中有几个bean具有状态,所以我想在单元测试之前/之后重置该状态

我的想法是向助手类中添加一个方法,该类只需遍历Spring上下文中的所有bean,检查在
@之前
@之后
注释的方法并调用它们

如何从
ApplicationContext
获取实例化的bean列表


注意:简单地迭代所有已定义bean的解决方案是无用的,因为我有许多惰性bean,其中一些不能实例化,因为这会导致某些测试失败(例如,我有一个bean需要
java.sql.DataSource
,但测试可以工作,因为它们不需要该bean).

我不确定这对你是否有帮助

您需要创建自己的注释,例如MyAnnot。 并将该注释放置在要获取的类上。 然后使用下面的代码可以得到实例化的bean

ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(MyAnnot.class));
for (BeanDefinition beanDefinition : scanner.findCandidateComponents("com.xxx.yyy")){
    System.out.println(beanDefinition.getBeanClassName());
}
通过这种方式,您可以获得具有自定义注释的所有bean。

例如:

 public static List<Object> getInstantiatedSigletons(ApplicationContext ctx) {
            List<Object> singletons = new ArrayList<Object>();

            String[] all = ctx.getBeanDefinitionNames();

            ConfigurableListableBeanFactory clbf = ((AbstractApplicationContext) ctx).getBeanFactory();
            for (String name : all) {
                Object s = clbf.getSingleton(name);
                if (s != null)
                    singletons.add(s);
            }

            return singletons;

    }
公共静态列表GetInstancedSigleton(ApplicationContext ctx){
List singleton=new ArrayList();
字符串[]all=ctx.getBeanDefinitionNames();
ConfigurableListableBeanFactory clbf=((AbstractApplicationContext)ctx).getBeanFactory();
for(字符串名称:all){
对象s=clbf.getSingleton(名称);
如果(s!=null)
单身人士;
}
返回单身人士;
}
我已经创建了一个

这个helper类做两件事:

  • 它将所有内部字段设置为空。这允许Java释放不再使用的内存。但是,它对Spring不太有用(Spring上下文仍然保留对所有bean的引用)

  • 它试图在上下文中的所有bean中找到用
    @After
    注释的所有方法,并在测试后调用它们

  • 这样,您就可以轻松地重置单例/模拟的状态,而无需销毁/刷新上下文

    示例:您有一个模拟DAO:

    public void MockDao implements IDao {
    
        private Map<Long, Foo> database = Maps.newHashMap();
    
        @Override
        public Foo byId( Long id ) { return database.get( id ) );
    
        @Override
        public void save( Foo foo ) { database.put( foo.getId(), foo ); }
    
        @After
        public void reset() { database.clear(); }
    }
    
    public void MockDao实现IDao{
    私有地图数据库=Maps.newHashMap();
    @凌驾
    publicfoobyid(长id){returndatabase.get(id));
    @凌驾
    public void save(Foo-Foo){database.put(Foo.getId(),Foo);}
    @之后
    public void reset(){database.clear();}
    }
    

    注释将确保在每次单元测试后调用
    reset()
    ,以清除内部状态。

    我不得不对其进行一些改进

    @Resource
    AbstractApplicationContext context;
    
    @After
    public void cleanup() {
        resetAllMocks();
    }
    
    private void resetAllMocks() {
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        for (String name : context.getBeanDefinitionNames()) {
            Object bean = beanFactory.getSingleton(name);
            if (Mockito.mockingDetails(bean).isMock()) {
                Mockito.reset(bean);
            }
        }
    }
    

    使用前面的答案,我已将其更新为使用Java 8 Streams API:

    @Inject
    private ApplicationContext applicationContext;
    
    @Before
    public void resetMocks() {
        ConfigurableListableBeanFactory beanFactory = ((AbstractApplicationContext) applicationContext).getBeanFactory();
        Stream.of(applicationContext.getBeanDefinitionNames())
                .map(n -> beanFactory.getSingleton(n))
                // My ConfigurableListableBeanFactory isn't compiled for 1.8 so can't use method reference. If yours is, you can say
                // .map(ConfigurableListableBeanFactory::getSingleton)
                .filter(b -> Mockito.mockingDetails(b).isMock())
                .forEach(Mockito::reset);
    }
    

    applicationContext.getBeanDefinitionNames()不显示注册了而没有BeanDefinition实例的bean

    package io.velu.core;
    
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan
    public class Core {
    
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Core.class);
        String[] singletonNames = context.getDefaultListableBeanFactory().getSingletonNames();
        for (String singleton : singletonNames) {
            System.out.println(singleton);
        }       
    }
    
    }


    控制台输出 正如您在输出中看到的,环境、systemProperties、systemEnvironmentbean将使用上下文.getBeanDefinitionNames()方法显示

    弹簧靴 对于SpringBootWeb应用程序,可以使用以下端点列出所有bean

    @RestController
    @RequestMapping("/list")
    class ExportController {
    
    @Autowired
    private ApplicationContext applicationContext;
    
    @GetMapping("/beans")
    @ResponseStatus(value = HttpStatus.OK)
    String[] registeredBeans() {
        return printBeans();
    }
    
    private String[] printBeans() {
        AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
        if (autowireCapableBeanFactory instanceof SingletonBeanRegistry) {
            String[] singletonNames = ((SingletonBeanRegistry) autowireCapableBeanFactory).getSingletonNames();
            for (String singleton : singletonNames) {
                System.out.println(singleton);
            }
            return singletonNames;
        }
        return null;
    }
    
    }


    [ “自动配置报告”, “springApplicationArguments”, “斯普林布特班纳”, “springBootLoggingSystem”, “环境”, “系统属性”, “系统环境”, “org.springframework.context.annotation.internalConfigurationAnnotationProcessor”, “org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory”, “org.springframework.boot.autoconfigure.condition.beantypergistry”, “org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry”, “属性资源占位符配置器”, “org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.store”, “保留ErrorControllerTargetClassPostProcessor”, “org.springframework.context.annotation.InternalAutowiredNotationProcessor”, “org.springframework.context.annotation.internalRequiredAnnotationProcessor”, “org.springframework.context.annotation.internalCommonAnnotationProcessor”, “org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor”, “org.springframework.scheduling.annotation.ProxySyncConfiguration”, “org.springframework.context.annotation.internalAsyncAnnotationProcessor”, “methodValidationPostProcessor”, “embeddedServletContainerCustomizerBeanPostProcessor”, “errorPageRegistrarBeanPostProcessor”, “消息源”, “applicationEventMulticaster”, “org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration$EmbeddedTomcat”, “tomcatEmbeddedServletContainerFactory”, “org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration$TomcatWebSocketConfiguration”, “websocketContainerCustomizer”, “spring.http.encoding org.springframework.boot.autoconfigure.web.HttpEncodingProperties”, “org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration”, “localeCharsetMappingsCustomizer”, “org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration”, “服务器属性”, “duplicateServerPropertiesDetector”, “spring.resources org.springframework.boot.autoconfigure.web.ResourceProperties”, “org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration”, “conventionErrorViewResolver”, “org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration”, “errorPageCustomizer”, “servletContext”, “上下文参数”, “contextAttributes”, “spring.mvc org.springframework.boot.autoconfigure.web.WebMvcProperties”, “spring.http.multipart org.springframework.boot.autoconfigure.w
    @RestController
    @RequestMapping("/list")
    class ExportController {
    
    @Autowired
    private ApplicationContext applicationContext;
    
    @GetMapping("/beans")
    @ResponseStatus(value = HttpStatus.OK)
    String[] registeredBeans() {
        return printBeans();
    }
    
    private String[] printBeans() {
        AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
        if (autowireCapableBeanFactory instanceof SingletonBeanRegistry) {
            String[] singletonNames = ((SingletonBeanRegistry) autowireCapableBeanFactory).getSingletonNames();
            for (String singleton : singletonNames) {
                System.out.println(singleton);
            }
            return singletonNames;
        }
        return null;
    }