第3节 如何从 Spring 容器中获取 Bean 实例

517 阅读1分钟

  通过上篇文章 第2节 Spring IOC 容器对 Bean 的管理 ,我们知道了如何向容器中注入 Bean,了解这些是远远不够的。
  本篇文章将简单说明 如何从容器中是获取 Bean 实例

1. 利用 BeanFactory 获取

在 Spring 3.1 之前我们可以用 XmlBeanFactory 来获取,方式如下:

BeanFactory factory = new XmlBeanFactory(new ClassPathResource("application-bean.xml"));
System.out.println(factory.getBean("bwmCar", Car.class).getCarName());

但在 Spring 3.1 之后, XmlBeanFactory@Deprecated 注解标识,不推荐使用了。那么替代 XmlBeanFactory 获取 Bean 的方式是什么呢?我们可以参考 Spring 源码中FactoryBeanTests 类中的测试用例方式来获取 Bean。

public class FactoryBeanTests {

   private static final Class<?> CLASS = FactoryBeanTests.class;
   // 获取类路径下的资源文件
   private static final Resource RETURNS_NULL_CONTEXT = qualifiedResource(CLASS, "returnsNull.xml");

   @Test
   public void testFactoryBeanReturnsNull() throws Exception {
      DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
      new XmlBeanDefinitionReader(factory).loadBeanDefinitions(RETURNS_NULL_CONTEXT);

      assertEquals("null", factory.getBean("factoryBean").toString());
   }
}

看完这段代码后,发现它主要是利用 DefaultListableBeanFactoryXmlBeanDefinitionReader 来获取容器中的 Bean 。

@Test
public void defaultFactory() {
   DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
   XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);

   Resource resource = new ClassPathResource("application-bean.xml");
   reader.loadBeanDefinitions(resource);

   System.out.println(factory.getBean("bwmCar", Car.class).getCarName());
}

2. 利用 ApplicationContext 获取

ApplicationContext 接口是对 BeanFactory 接口的扩展。

@Test
public void defaultContext() {
   ApplicationContext cx = new ClassPathXmlApplicationContext("application-bean.xml");
   Car car = cx.getBean("bwmCar", Car.class);
   System.out.println(car.getCarName());
}

3. 利用 ApplicationContextAware 获取

  Spring 容器在初始化的时候会通过 ApplicationContextAware setApplicationContext 方法把 ApplicationContext  对象注入到容器中,该对象中包含了 Bean 实例的信息。
  使用该种方式获取容器中的 Bean 与前两种方式不同,需要我们的 Spring 应用正常启动后使用,在 junit 测试用例中无法直接使用。在程序中使用 SpringContextUtil.getBean("bwmCar") 来获取 Bean 实例。

@Component
public class SpringContextUtil implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.context = applicationContext;
    }

    /**
     * 从应用上下文中取 bean
     */
    public static <T> T getBean(String name) {
        checkApplicationContext();
        return (T) context.getBean(name);
    }

    public static ApplicationContext getContext() {
        checkApplicationContext();
        return context;
    }

    private static void checkApplicationContext() {
        if (null == context) {
            throw new IllegalStateException("applicaitonContext 未注入");
        }
    }
}