通过上篇文章 第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());
}
}
看完这段代码后,发现它主要是利用 DefaultListableBeanFactory 和XmlBeanDefinitionReader 来获取容器中的 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 未注入");
}
}
}