Entonces, el título es bastante sencillo. Tengo una clase de controlador DynamicBeanHandler que implementa la interfaz BeanDefinitionRegistryPostProcessor proporcionada por Spring. En esta clase, estoy agregando varios beans SCOPE_SINGLETON que tienen una clase de bean configurada como MyDynamicBean de la siguiente manera:
GenericBeanDefinition myBeanDefinition = new GenericBeanDefinition(); myBeanDefinition.setBeanClass(MyDynamicBean.class); myBeanDefinition.setScope(SCOPE_SINGLETON); myBeanDefinition.setPropertyValues(getMutableProperties(dynamicPropertyPrefix)); registry.registerBeanDefinition(dynamicBeanId, myBeanDefinition); El método getMutableProperties() devuelve un objeto de MutablePropertyValues .
Más tarde, hago SpringUtil.getBean(dynamicBeanId) para obtener la instancia requerida MyDynamicBean donde la clase SpringUtil implementa ApplicationContextAware . Todo esto funciona muy bien. El problema surge cuando quiero eliminar una de estas instancias y agregar una nueva instancia más adelante donde no tengo la instancia de registro. ¿Puede alguien por favor ayudarme a encontrar una manera de hacer esto?
El siguiente es el código para la clase SpringUtil :
public class SpringUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringUtil.applicationContext = applicationContext; } public static ApplicationContext getApplicationContext() { return applicationContext; } public static Object getBean(String beanId) { return applicationContext.getBean(beanId); } public static <T> T getBean(String beanId, Class<T> beanClass) { return applicationContext.getBean(beanId, beanClass); } }Puede utilizar BeanDefinitionRegistry (busque aquí la API) para eliminar o registrar los beans de forma dinámica.
Entonces, en su clase SpringUtil , puede agregar el siguiente método para eliminar la definición de bean existente usando removeBeanDefinition() y luego agregar una nueva definición de bean usando registerBeanDefinition() .
public void removeExistingAndAddNewBean(String beanId) { AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory(); BeanDefinitionRegistry registry = (BeanDefinitionRegistry) factory; registry.removeBeanDefinition(beanId); //create newBeanObj through GenericBeanDefinition registry.registerBeanDefinition(beanId, newBeanObj); }Puede crear programáticamente un bean con dependencias inyectadas de esta manera:
AutowireCapableBeanFactory#createBean
Cree completamente una nueva instancia de bean de la clase dada con la estrategia de conexión automática especificada. Todas las constantes definidas en esta interfaz son compatibles aquí. Realiza la inicialización completa del bean, incluidos todos los BeanPostProcessors aplicables.
@Autowired ApplicationContext context; AutowireCapableBeanFactory factory = context.getAutowireCapableBeanFactory(); MyDynamicBean bean = (MyDynamicBean) factory.createBean(MyDynamicBean.class, AUTOWIRE_CONSTRUCTOR, false);En lugar de autowiring WebApplicationContext, puede hacer
@Autowired private GenericWebApplicationContext context;Luego puede registrar un nuevo bean o eliminar uno antiguo y registrar un nuevo bean
AutowireCapableBeanFactory factory = context.getAutowireCapableBeanFactory(); BeanDefinitionRegistry registry = (BeanDefinitionRegistry) factory; registry.removeBeanDefinition("myBean"); context.registerBean("myBean", MyBean.class, () -> new MyBean());