在Spring中运行时注册bean(prototype) [英] Registering beans(prototype) at runtime in Spring

查看:208
本文介绍了在Spring中运行时注册bean(prototype)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只需要社区评估的东西。以下是代码段,它是一个创建特定类型实例的简单工厂。该方法将在上下文中将bean注册为原型并返回实例。这是我第一次在运行时配置bean。你能否评价并提供反馈?谢谢你提前。

Just need something evaluated by the community. Following is a snippet of code, which is a simple factory that creates instances of a particular type. The method will register the bean in the context as a prototype and return the instance. This is the first time I am configuring beans at run time. Could you kindly evaluate and provide feedback? thank you in advance.

package au.com.flexcontacts.flexoperations;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.AbstractApplicationContext;

import au.com.flexcontacts.exceptions.SyncClassCreactionError;

/**
 * @author khushroo.mistry
 * Class purpose: Simple Factory to create an 
 * instance of SynchroniseContactsService and register it in the Spring IoC.
 */
public final class FLEXSyncFactory implements ApplicationContextAware {

    private static AbstractApplicationContext context;


    /**
     * @param username
     * @param password
     * @param syncType
     * @return the correct service class
     * @throws SyncClassCreactionError
     * The method registers the classes dynamically into the Spring IoC
     */
    public final SynchroniseContactsService createSyncService(String username, String password, SyncType syncType) throws SyncClassCreactionError {

        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();

        try {

            //Register the bean in the IoC
            BeanDefinition bdb = new GenericBeanDefinition();
            bdb.setBeanClassName(syncType.getClassName());
            bdb.setScope("prototype");
            ConstructorArgumentValues constructor = bdb.getConstructorArgumentValues();
            constructor.addIndexedArgumentValue(0, username);
            constructor.addIndexedArgumentValue(1, password);
            beanFactory.registerBeanDefinition(syncType.getInstanceName(), bdb);

            //Return instance of bean
            return (SynchroniseContactsService) beanFactory.getBean(syncType.getInstanceName());
        } catch (Exception e) {
            e.printStackTrace();
            throw new SyncClassCreactionError("Error: Illegal Handler");
        }

    }

    public void setApplicationContext(ApplicationContext applicationContext)
    throws BeansException {
        context = (AbstractApplicationContext) applicationContext;

    }

}

FLEX Sync工厂已经在IoC容器中配置为单例。所以要创建一个新的同步管理器我执行以下操作:

FLEX Sync factory has been configured in the IoC container as a singleton. So to create a new sync manager I do the following:

flexSyncFactory.createSyncService(userName, password, SyncType.FULL);

我使用的是Spring 3.1。请仔细阅读并提供宝贵的意见。

I am using Spring 3.1. Please review and provide your valuable feedback.

kind of。

推荐答案

这完全是我的意见,而不是专家观点:

This is purely my opinion, not an expert view:

Spring为应用程序上下文的自定义修改提供了两种机制 - 使用 BeanFactoryPostProcessor ,允许修改现有的bean定义或添加新的bean定义,以及 BeanPostProcessors ,它允许修改bean实例(将它们绕过代理等)。

Spring provides two mechanisms for custom modification of an application context - using BeanFactoryPostProcessor which allows for modification of existing bean definitions or adding new bean definitions, and BeanPostProcessors which allows for modification of bean instances(wrapping them around proxy etc).

Spring不提供任何其他本机方式在运行时动态添加bean定义或bean实例,但是像您已经通过抓住底层bean工厂实例并添加在bean定义中是一种方法。它有效,但有风险:

Spring does not provide any other native way to dynamically add bean definitions or bean instances at runtime, but like you have done by getting hold of the underlying bean factory instances and adding in bean definitions is one way to go. It works, but there are risks:


  • 如果您使用新类型覆盖现有的bean名称,那么会发生什么这个bean已经被注入处理了。此外,如果现有的bean名称被完全不同的类型覆盖,会发生什么!

  • What happens if you overwrite an existing bean name with a new type, how are places where this bean is already injected handled. Also, what happens if a existing bean name is overwritten with a totally different type!

这个新注册的bean将不会有自动连接的任何字段,也不会也注入到其他bean中 - 所以本质上bean工厂纯粹是作为一个用来保存bean的注册表,而不是真正的依赖注入功能!

This newly registered bean will not have any fields autowired in, and will not be injected into other beans also - so essentially the bean factory is purely acting as a registry for holding the bean, not really a dependency injection functionality!

如果在应用程序上下文调用了 refresh(),那么后备bean工厂将被覆盖,并创建一个新的bean,因此任何直接注册到bean工厂的bean实例都将丢失。

if a refresh() is called on the application context then the backing bean factory will be overwritten and a new one created, thus any bean instances registered against the bean factory directly will be lost.

如果目标是纯粹创建已经由Spring自动连线的bean,我会去像 @可配置。如果上述风险是可以接受的,您的方法也应该奏效。

If the objective is purely to create beans which has been autowired by Spring, I would go for something like @Configurable. If the risks above are acceptable also your approach should work.

这篇关于在Spring中运行时注册bean(prototype)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆