开发者

Add Bean Programmatically to Spring Web App Context

开发者 https://www.devze.com 2023-02-01 03:14 出处:网络
Because of a plug-in architecture, I\'m trying to add a bean programmatically to my webapp.I have a Spring bean created through the @Component annotation, and i am implementing the ApplicationContextA

Because of a plug-in architecture, I'm trying to add a bean programmatically to my webapp. I have a Spring bean created through the @Component annotation, and i am implementing the ApplicationContextAware interface.

My override function looks like this:

@Override
public void setApplicationContext(ApplicationContext applicationContext)
        throws BeansException {

    // this fails
    this.applicationContext = (GenericWebApplicationContext) applicationContext;
 }

Basically, I can't figure out how to add a bean to the applicationContext object given to setApplicationContext. Can anyone tell me how I am going about this the wrong way?

Ok, this is what i ended up with as the solution:

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry bdr)
        throws BeansExc开发者_C百科eption {
    BeanDefinition definition = new RootBeanDefinition(
            <My Class>.class);

    bdr.registerBeanDefinition("<my id>", definition);
}


Here is a simple code:

ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
beanFactory.registerSingleton(bean.getClass().getCanonicalName(), bean);


In Spring 3.0 you can make your bean implement BeanDefinitionRegistryPostProcessor and add new beans via BeanDefinitionRegistry.

In previous versions of Spring you can do the same thing in BeanFactoryPostProcessor (though you need to cast BeanFactory to BeanDefinitionRegistry, which may fail).


Why do you need it to be of type GenericWebApplicationContext?
I think you can probably work with any ApplicationContext type.

Usually you would use an init method (in addition to your setter method):

@PostConstruct
public void init(){
    AutowireCapableBeanFactory bf = this.applicationContext
        .getAutowireCapableBeanFactory();
    // wire stuff here
}

And you would wire beans by using either

AutowireCapableBeanFactory.autowire(Class, int mode, boolean dependencyInject)

or

AutowireCapableBeanFactory.initializeBean(Object existingbean, String beanName)


Actually AnnotationConfigApplicationContext derived from AbstractApplicationContext, which has empty postProcessBeanFactory method left for override

/**
 * Modify the application context's internal bean factory after its standard
 * initialization. All bean definitions will have been loaded, but no beans
 * will have been instantiated yet. This allows for registering special
 * BeanPostProcessors etc in certain ApplicationContext implementations.
 * @param beanFactory the bean factory used by the application context
 */
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}

To leverage this, Create AnnotationConfigApplicationContextProvider class which may look like following(given for Vertx instance example, you can use MyClass instead)...

public class CustomAnnotationApplicationContextProvider {
private final Vertx vertx;

public CustomAnnotationApplicationContextProvider(Vertx vertx) {
    this.vertx = vertx;
}

/**
 * Register all beans to spring bean factory
 *
 * @param beanFactory, spring bean factory to register your instances
 */
private void configureBeans(ConfigurableListableBeanFactory beanFactory) {
    beanFactory.registerSingleton("vertx", vertx);
}

/**
 * Proxy method to create {@link AnnotationConfigApplicationContext} instance with no params
 *
 * @return {@link AnnotationConfigApplicationContext} instance
 */
public AnnotationConfigApplicationContext get() {
    return new AnnotationConfigApplicationContext() {

        @Override
        protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
            super.postProcessBeanFactory(beanFactory);
            configureBeans(beanFactory);
        }
    };
}

/**
 * Proxy method to call {@link AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(DefaultListableBeanFactory)} with our logic
 *
 * @param beanFactory bean factory for spring
 * @return
 * @see AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(DefaultListableBeanFactory)
 */
public AnnotationConfigApplicationContext get(DefaultListableBeanFactory beanFactory) {
    return new AnnotationConfigApplicationContext(beanFactory) {

        @Override
        protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
            super.postProcessBeanFactory(beanFactory);
            configureBeans(beanFactory);
        }
    };
}

/**
 * Proxy method to call {@link AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(Class[])} with our logic
 *
 * @param annotatedClasses, set of annotated classes for spring
 * @return
 * @see AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(Class[])
 */
public AnnotationConfigApplicationContext get(Class<?>... annotatedClasses) {
    return new AnnotationConfigApplicationContext(annotatedClasses) {

        @Override
        protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
            super.postProcessBeanFactory(beanFactory);
            configureBeans(beanFactory);
        }
    };
}

/**
 * proxy method to call {@link AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(String...)} with our logic
 *
 * @param basePackages set of base packages for spring
 * @return
 * @see AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(String...)
 */
public AnnotationConfigApplicationContext get(String... basePackages) {
    return new AnnotationConfigApplicationContext(basePackages) {

        @Override
        protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
            super.postProcessBeanFactory(beanFactory);
            configureBeans(beanFactory);
        }
    };
}
}

While creating ApplicationContext you can create it using

Vertx vertx = ...; // either create or for vertx, it'll be passed to main verticle
ApplicationContext context = new CustomAnnotationApplicationContextProvider(vertx).get(ApplicationSpringConfig.class);


First initialize Property values

MutablePropertyValues mutablePropertyValues = new MutablePropertyValues();
mutablePropertyValues.add("hostName", details.getHostName());
mutablePropertyValues.add("port", details.getPort());

DefaultListableBeanFactory context = new DefaultListableBeanFactory();
GenericBeanDefinition connectionFactory = new GenericBeanDefinition();
connectionFactory.setBeanClass(Class);
connectionFactory.setPropertyValues(mutablePropertyValues);

context.registerBeanDefinition("beanName", connectionFactory);

Add to the list of beans

ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
beanFactory.registerSingleton("beanName", context.getBean("beanName"));
0

精彩评论

暂无评论...
验证码 换一张
取 消