spring 动态注入bean的问题?


声明一个A类和A的子类B,
在 
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 方法里执行

ConfigurableListableBeanFactory.destroyBean("a")
ConfigurableListableBeanFactory.registerSingleton("a",new B());
然后马上
Object bean = ConfigurableListableBeanFactory.getBean("a"),

获取的 bean 类型是B类了,
但是使用 

@Autowired 
A a;

获取的还是A类型,请问是哪里不对?

这个问题的原因在于,Spring 的自动注入是基于反射实现的,并不会直接访问容器内部管理的对象,而是访问一个代理对象(Proxy Object)。代理对象是一个中间层,实际指向的是目标对象(Target Object),代理对象主要负责执行相关的处理逻辑(如事务控制等)。

在你的情况中,当你在 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 方法里执行 ConfigurableListableBeanFactory.registerSingleton("a", new B()); 时,虽然 A 类型的 Bean 已经被移除并被重新创建并注册为 B 类型的 Bean,但是因为之前已经通过 @Autowired 注解自动注入了一个 A 类型的 Bean,该 Bean 已经被实例化并被代理了,因此无法直接获取到新注册的 B 类型的 Bean。

如果你想要获取到新注册的 B 类型的 Bean,可以直接使用容器获取服务(Service)的方式,而不是使用自动注入。你可以在 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 方法中直接获取容器对象 ApplicationContext 或者 BeanFactory,然后通过该对象获取新注册的 B 类型的 Bean,具体可以参考下面的代码示例:

public class MyPostProcessor implements InstantiationAwareBeanPostProcessor {

    @Autowired
    private ApplicationContext applicationContext;

    public Object postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if("a".equals(beanName)) {
            ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
            beanFactory.destroyBean("a");
            beanFactory.registerSingleton("a", new B());
            Object beanObj = beanFactory.getBean("a");
            // 在这里可以直接使用 beanObj,它是新注册的 B 类型的 Bean
        }
        return bean;
    }
}

需要注意强制类型转换并不是推荐的方式,在 Spring 框架中,通常通过依赖注入的方式来获取 Bean 对象。这种方式是更加灵活和更容易管理 Bean 对象的。

其实你可以这么做,每次使用bean的时候进行依赖查找,直接从BeanFactory中进行依赖查找。保证每次获取的bean是最新的。
方法一:使用到动态bean的类实现一下BeanFactoryAware接口。在使用动态bean的时候 直接使用回调的beanfactory进行依赖查找~
方法二:注入一个动态bean的holder对象实现BeanFactoryWare接口。对外提供bean的依赖查找功能。

之前遇到过一个场景,需求就是要进行对对象进行重建~ 采用的上述方法二,在此过程中遇到了@Configuration注解的一些问题。以下是扩展
传送门

希望能帮助到你~