只需要社区评估的东西。以下是一段代码,它是一个创建特定类型实例的简单工厂。该方法将在上下文中将 bean 注册为原型并返回实例。这是我第一次在运行时配置 bean。您能否评估并提供反馈?先感谢您。
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 容器中配置为单例。所以要创建一个新的同步管理器,我执行以下操作:
flexSyncFactory.createSyncService(userName, password, SyncType.FULL);
我正在使用 Spring 3.1。请查看并提供您宝贵的反馈。
亲切的问候。
这纯粹是我的观点,不是专家的观点:
Spring 提供了两种自定义修改应用程序上下文的机制 - 使用BeanFactoryPostProcessor允许修改现有 bean 定义或添加新 bean 定义,以及BeanPostProcessors允许修改 bean 实例(将它们包装在代理等周围)。
Spring 没有提供任何其他本地方式来在运行时动态添加 bean 定义或 bean 实例,但就像您通过获取底层 bean 工厂实例并添加 bean 定义所做的那样,是一种方法。它有效,但存在风险:
如果用新类型覆盖现有 bean 名称会发生什么,如何处理已注入该 bean 的位置。此外,如果现有 bean 名称被完全不同的类型覆盖会发生什么!
这个新注册的 bean 不会有任何自动装配的字段,也不会被注入到其他 bean 中——所以本质上 bean 工厂只是充当保存 bean 的注册表,而不是真正的依赖注入功能!
如果
refresh()
在应用程序上下文中调用a ,则支持 bean 工厂将被覆盖并创建一个新工厂,因此任何直接针对 bean 工厂注册的 bean 实例都将丢失。如果目标纯粹是创建由 Spring 自动装配的 bean,我会选择类似@Configurable 的东西。如果上述风险是可以接受的,那么您的方法也应该有效。