Spring 从应用获取Bean的常用姿势

如何在普通类中获取 Spring 管理的 Bean ,各种姿势,从本文中寻找。

通常,在Spring应用程序中,当我们使用@Bean/@Service/@Controller@Component/@Configuration或者其它的注解将Bean注入的Spring IOC。然后我们可以使用@Autowired或者@Resource来使用由Spring IoC来管理的Bean

一、从应用程序上下文中获取Bean

我们今天学习将来如何从ApplicationContext中的Bean。因为有些情况下我们不得不从应用程序上下文中来获取Bean,例如在没有注入Spring的工具类中。

1.1 在初始化时保存ApplicationContext对象

1
2
ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml"); 
ac.getBean("beanId");

这种方式适用于采用Spring框架的独立应用程序,需要程序通过配置文件手工初始化Spring的情况。

注意:在获取失败时抛出异常。

1.2 通过Spring提供的工具类获取ApplicationContext对象

1
2
3
4
ApplicationContext ac1 = WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc); 
ApplicationContext ac2 = WebApplicationContextUtils.getWebApplicationContext(ServletContext sc);
ac1.getBean("beanId");
ac2.getBean("beanId");

这种方式适合于采用Spring框架的B/S系统,通过ServletContext对象获取ApplicationContext对象,然后在通过它获取需要的类实例。获取失败时返回null

1.3 继承自抽象类ApplicationObjectSupport

抽象类ApplicationObjectSupport提供getApplicationContext()方法,可以方便的获取ApplicationContext

Spring初始化时,会通过该抽象类的setApplicationContext(ApplicationContext context)方法将ApplicationContext 对象注入。

1.4 继承自抽象类WebApplicationObjectSupport

类似上面方法,调用getWebApplicationContext()获取WebApplicationContext

1.5 通过Spring提供的ContextLoader

1
2
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
wac.getBean(beanID);

该方式不依赖于servlet,不需要注入的方式。

1.6 实现接口ApplicationContextAware(本文重点)

实现该接口的setApplicationContext(ApplicationContext context)方法,并保存ApplicationContext 对象。Spring初始化时,会通过该方法将ApplicationContext对象注入。

二、Spring ApplicationContext 工具类

2.1 项目准备

新增一个Bean,使其被Spring IOC 管理。

  • SpringBean.java
1
2
3
4
5
6
7
8
9
@Component
public class SpringBean {

private String desc;

public String getDesc() {
return "SpringBean desc";
}
}
  • application.yml
1
2
demo:
value: 8888

2.2 定义一个工具类,实现 ApplicationContextAware

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
@Component
public final class SpringUtils implements ApplicationContextAware {
/**
* Spring应用上下文环境
*/
private static ApplicationContext applicationContext;

/**
* 实现ApplicationContextAware接口的回调方法,设置上下文环境
* @param applicationContext
* @throws BeansException
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringUtils.applicationContext == null) {
SpringUtils.applicationContext = applicationContext;
}
}

/**
* 获取对象,重写了bean方法
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> clazz) {
return SpringUtils.applicationContext.getBean(clazz);
}

/**
* 同上方法
* @param name
* @return
*/
public static Object getBean(String name) {
return SpringUtils.applicationContext.getBean(name);
}

/**
* 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
* @param name
* @return
*/
public static boolean containsBean(String name) {
return SpringUtils.applicationContext.containsBean(name);
}
/**
* 读取配置信息
* @param key
* @return
*/
public static String getProperty(String key) {
return SpringUtils.applicationContext.getEnvironment().getProperty(key);
}
}
  1. 通过@Component注解将SpringUtils.java注入的Spring IOCSpring能够为我们自动地执行 setApplicationContext() 方法;
  2. 我在该工具类封装了三个方法,主要用于获取Bean/判断Bean是否存在/获取配置文件中信息。

2.3 getBean()

该方法用于获取对象,获取不到会抛异常。

  • 测试
1
2
3
4
5
6
7
@Test
public void getBeanDemo() {
SpringBean springBean = SpringUtils.getBean(SpringBean.class);
log.info("springBean.desc:{}", springBean.getDesc());
// 如果bean 不存在
log.info("springBeanOther:{}", SpringUtils.getBean("springBeanOther"));
}

2.4 containsBean()

用来判断该Bean 是否注入到Spring IOC

  • 测试
1
2
3
4
5
6
@Test
public void containsBeanDemo() {
log.info("containsBean:{}", SpringUtils.containsBean("springBean"));
// 如果bean 不存在
log.info("containsBean:{}", SpringUtils.containsBean("springBeanOther"));
}

2.5 getProperty()

用来获取配置文件属性,属性不存在返回null

  • 测试
1
2
3
4
5
6
7
8
@Test
public void getPropertyDemo() {
String value = SpringUtils.getProperty("demo.value");
log.info("value:{}", value);
// 配置中不存在
String key = SpringUtils.getProperty("demo.key");
log.info("key:{}", key);
}

三、总结

这里仅作简单展示,如需探究更多使用方法,可以直接定义getApplicationContext()方法,将ApplicationContext返回,具体详见文末工具类中代码。

1
2
3
4
5
@Test
public void getApplicationContext() {
ApplicationContext context = SpringUtils.getApplicationContext();
log.info("context.containsBean():{}", context.containsBean("springBean"));
}

Github 示例代码

  1. SpringUtils.java
  2. SpringUtilsTest.java

更多 Java 笔记,详见【Java 知识笔记本】,欢迎提供想法建议。

Van wechat
最新文章,欢迎您扫一扫上面的微信公众号!
-------------    本文结束  感谢您的阅读    -------------