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

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

问题描述

只需要社区评估的东西.以下是一段代码,它是一个创建特定类型实例的简单工厂.该方法将在上下文中将 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.

亲切的问候.

推荐答案

这纯粹是我的观点,并非专家观点:

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 实例都将被丢失了.

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,我会选择类似 @Configurable.如果上述风险是可以接受的,那么您的方法也应该有效.

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(原型)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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