簡體   English   中英

如何使用動態創建的實例作為 bean 用於 Spring 自動裝配

[英]How to use a dynamically created instance as a bean for use in Spring autowiring

我有特定的實例需要用於AnnotationConfigWebApplicationContext中的自動裝配 下面是演示錯誤的代碼。 當然,我的情況要復雜得多,實例是在運行時確定的。 我在 spring 配置時間發現了這些實例,這就是為什么如果下面的代碼有效,那就沒問題了。 我試過了,但它會拋出NoSuchBeanDefinitionException ,即使ctx.getBean能夠找到它。 實現這一目標的正確方法是什么?

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

class Scratch {
    static class MyClass {
    }

    @Configuration
    static class TestConfig {
        @Autowired
        private MyClass myClass;
    }

    public static void main(String[] args) {
        MyClass requiredInstance = new MyClass();
        final AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.refresh(); // Throws "BeanFactory not initialized..." on next line if this not here
        ctx.getBeanFactory().registerSingleton("myClass", requiredInstance);
        // Also tried: ((DefaultListableBeanFactory)ctx.getAutowireCapableBeanFactory()).registerSingleton("myClass", requiredInstance);
        System.out.println(ctx.getBean(MyClass.class)); // Outputs "Scratch$MyClass@1804f60d"
        ctx.register(TestConfig.class);
        ctx.refresh(); // Throws "NoSuchBeanDefinitionException: No qualifying bean of type 'Scratch$MyClass' available:"
    }
}

在這里找到了解決方案https://blog.pchudzik.com/201705/dynamic-beans/ 我在其他地方看到過 BeanFactoryPostProcessor ,但他們沒有展示如何創建實例。 這個例子展示了使用我需要的工廠機制。

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

class Scratch {
    static class MyClass {
    }

    @Configuration
    static class TestConfig {
        @Autowired
        private MyClass myClass;
    }

    public static void main(String[] args) {
        final AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(TestConfig.class);
        ctx.register(DynamicBeanFactoryProcessor.class);
        ctx.refresh();
        System.out.println(ctx.getBean("myClass")); // Outputs "Scratch$MyClass@1804f60d"
        System.out.println(ctx.getBean(MyClass.class)); // Outputs "Scratch$MyClass@1804f60d"
    }

    @Configuration
    public static class DynamicBeanFactoryProcessor implements BeanFactoryPostProcessor {
        public <T> T createInstance(Class<T> c) {
            return c.cast(new MyClass()); // Create dynamic instance here
        }

        @Bean
        public DynamicBeanFactoryProcessor dynamicBeanFactoryProcessor() {
            return new DynamicBeanFactoryProcessor();
        }

        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            ((BeanDefinitionRegistry)beanFactory).registerBeanDefinition("myClass",
                    BeanDefinitionBuilder.genericBeanDefinition(MyClass.class)
                        .setFactoryMethodOnBean("createInstance", "dynamicBeanFactoryProcessor")
                        .addConstructorArgValue(MyClass.class)
                        .getBeanDefinition());
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM