1、动态注入Bean示例

  • 创建接口及其实现类
public interface BaseTest {
    String getValue();
}

public class TestOne implements BaseTest {
    @Override
    public String getValue() {
        return "test one";
    }
}

public class TestTwo implements BaseTest {
    @Override
    public String getValue() {
        return "test two";
    }
}
  • 创建Bean管理工具类
import java.util.LinkedHashMap;
import java.util.Map;
public final class TestBeanHolder {
    private TestBeanHolder() {
        throw new RuntimeException("无法创建工具类对象");
    }

    private static ThreadLocal<String> threadLocal = new InheritableThreadLocal<>();

    private static Map<String, BaseTest> config = new LinkedHashMap<>();

    static {
        // 根据实际情况添加Bean
        config.put("one", new TestOne());
        config.put("two", new TestTwo());
    }

    public static Map<String, BaseTest> getTestBeans() {
        return config;
    }

    public static void setKey(String key) {
        threadLocal.set(key);
    }

    public static BaseTest getCurrentBaseTest() {
        return config.get(threadLocal.get());
    }
}
  • 实现ObjectFactory
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
import java.io.Serializable;
public class TestObjectFactory implements ObjectFactory<BaseTest>, Serializable {

    @Override
    public BaseTest getObject() throws BeansException {
        return TestBeanHolder.getCurrentBaseTest();
    }
}
  • 注册依赖(指定类型Bean)
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
@Component
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        beanFactory.registerResolvableDependency(BaseTest.class, new TestObjectFactory());
    }
}

2、注意事项

  • BaseTest必须是接口类型、BeanFactory必须实现Serializable接口,Spring才会通过注册的BeanFactory获取Bean。

    DefaultListableBeanFactory类的findAutowireCandidates方法中,通过AutowireUtils类的resolveAutowiringValue方法查找某种类型可自动注入的Bean。 alt 在AutowireUtils类的resolveAutowiringValue方法中,当类型是接口类型且BeanFactory实例实现了Serializable接口时,会为该类型创建代理对象。 alt 通过代理对象调用方法时,会触发ObjectFactoryDelegatingInvocationHandler的invoke方法。其中,会通过注册的BeanFactory实例获取实际的对象。 alt

  • 无法在BeanFactoryPostProcessor中注入普通Bean。

    在AbstractApplicationContext类中的refresh方法中,有如下代码段。其中BeanFactoryPostProcessor在其它非懒加载Bean创建之前执行。因此,在BeanFactoryPostProcessor中,无法注入非懒加载的Bean。 alt

3、本文中动态注入Bean方法的优缺点

  • 优点
    • 在需要使用的地方,可直接通过@Resource等方式注入。
    • 间接实现了Bean的懒加载:在使用的时候获取。
  • 缺点
    • 所需的Bean必须是接口类型,不适合现有类的改造。
    • 所需的Bean需要自己维护。