Похоже, это возможно, по крайней мере, в среде Spring Boot. В реализации ApplicationContext
существует GenericApplicationContext , который имеет возможность removeBeanDefinition () , который затем может быть перерегистрирован через registerBeanDefinition () .
Это даже распространяется каскадом для удаления bean-компонентов, содержащих ссылку на удаляемый bean-компонент (реализацию этого можно увидеть в DefaultSingletonBeanRegistry.destroyBean () ).
Например, если на Bean1
ссылается Bean2
:
@Component
public class Bean1 {
}
@Component
public class Bean2 {
@Autowired
public Bean1 bean1;
}
Затем тест может удалить bean1
из контекста, а также сменить bean2
также:
@RunWith(SpringRunner.class)
public class BeanRemovalTest implements ApplicationContextAware {
@Autowired
private Bean1 bean1;
@Autowired
private Bean2 bean2;
private ApplicationContext applicationContext;
@Test
public void test1() throws Exception {
System.out.println("test1():");
System.out.println(" bean1=" + bean1);
System.out.println(" bean2.bean1=" + bean2.bean1);
resetBean("bean1");
}
@Test
public void test2() throws Exception {
System.out.println("test2():");
System.out.println(" bean1=" + bean1);
System.out.println(" bean2.bean1=" + bean2.bean1);
}
private void resetBean(String beanName) {
GenericApplicationContext genericApplicationContext = (GenericApplicationContext) applicationContext;
BeanDefinition bd = genericApplicationContext
.getBeanDefinition(beanName);
genericApplicationContext.removeBeanDefinition("bean1");
genericApplicationContext.registerBeanDefinition("bean1", bd);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
}
Показывает замену обоих экземпляров бина:
test1():
bean1=hello.so.Bean1@61d6015a
bean2.bean1=hello.so.Bean1@61d6015a
test2():
bean1=hello.so.Bean1@2e570ded
bean2.bean1=hello.so.Bean1@2e570ded
(Если resetBean("bean1")
закомментирован, то это один и тот же экземпляр оба раза).
Обязательно должны быть ребра, где это не сработает - например, если другой бин держит ссылку, полученную из ApplicationContext.getBean()
.