阅读 207

Springboot如何获取上下文ApplicationContext

这篇文章主要介绍了Springboot如何获取上下文ApplicationContext,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

目录
  • Springboot获取上下文ApplicationContext

  • springboot的应用上下文

    • ServletWebServerApplicationContext

    • 扩展的功能

    • AnnotationConfigServletWebServerApplicationContext

Springboot获取上下文ApplicationContext

在项目中遇到了一个场景,就是通过获得上下文然后获取特定的bean。在此遇到了不小的坑,故留下这个篇文章,做个记录。

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
56
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
  
@Component
public class SpringContextUtil implements ApplicationContextAware {
    /**
     * 上下文对象实例
     */
    private static ApplicationContext applicationContext;
  
    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
  
    /**
     * 获取applicationContext
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
  
    /**
     * 通过name获取 Bean.
     * @param name
     * @return
     */
    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }
  
    /**
     * 通过class获取Bean.
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> clazz){
        return getApplicationContext().getBean(clazz);
    }
  
    /**
     * 通过name,以及Clazz返回指定的Bean
     * @param name
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(String name,Class<T> clazz){
        return getApplicationContext().getBean(name, clazz);
    }
}

看上面的代码,可以看到在工具类中一开始是声明了一个ApplicationContext类型的静态变量,但是由于静态变量是不能被Spring容器管理的,一开始用正常的getter和setter方法不能获取到特定的bean,实践证明,需要在此变量的setter方法上加上@Autowired注解,并且去除setter方法中的static关键字。才可实现特定bean的注入。

springboot的应用上下文

springboot上下文有两个

  • ServletWebServerApplicationContext

  • AnnotationConfigServletWebServerApplicationContext(继承上面)

ServletWebServerApplicationContext

该类属于spring-boot-2.1.1Release.jar中,是自springboot诞生就衍生出来的,是spring框架的应用上下文Application的子类。

多说无益,show me code

扩展的功能


首先让我们来看一下,这个类到底做了什么,有什么存在的价值?

1
2
3
4
5
6
7
8
9
10
11
   private volatile WebServer webServer;
@Override
protected void onRefresh() {
 super.onRefresh();
 try {
  createWebServer();
 }
 catch (Throwable ex) {
  throw new ApplicationContextException("Unable to start web server", ex);
 }
}

在此类中有个WebServer成员变量,让我们用脚趾头想一下也应该可以知道,这其实就是web服务对象,也基本上可以猜测就是跟tomcat相关了(当然也可以是其他web服务器,如jetty)

然后我们又发现了onRefresh方法,相信我们并不陌生,这就是spring核心refresh方法的中一个钩子方法(即表明此时已经加载所有配置bean),进行WebServer对象的创建

1
2
3
4
5
6
7
8
@Override
protected void finishRefresh() {
 super.finishRefresh();
 WebServer webServer = startWebServer();
 if (webServer != null) {
  publishEvent(new ServletWebServerInitializedEvent(webServer, this));
 }
}

我们又发现该类存在finishRefresh,仔细想一下,这个也是spring核心#refresh方法中的一个钩子方法(不过这个特别,因为该方法是refresh方法中的最后一步,即会去实例化spring容器中的所有beandefinition对象)

首先赞一个,这个很巧妙,调用了super.finishRefresh() ,并没有丢弃父类的逻辑功能(这点在多态中,我相信还是会有人犯错,本来是扩展功能,但是直接重写,丢弃了父类的方法,当然spring框架开发大佬肯定不会犯这种错误,对吧!)

第二点重点来了,就是startWebServer,也就是在spring完成实例化之后,就会去启动web服务。

AnnotationConfigServletWebServerApplicationContext

小结一下:

首先此类是springboot启动运行run()创建ApplicationContext的实现类,不过很可惜,该类并没有很强的实质性扩展。

**唯一作用就是拥有了通过注解加载配置类的作用,即和AnnotationConfigApplication一样,只不过springboot的运行启动已经是通过注解加载bean类**

(虽然是鸡肋,不过这也符合spring创建类的一贯风格,就是每个类都是高内聚的,即每个类除了父类的功能之外,还都拥有其他扩展的作用。即使创建出来还没有用到就被遗弃,但仍然不能阻止spring开发大佬创建该类,哈哈)

以上为个人经验,希望能给大家一个参考

原文链接:https://blog.csdn.net/moxinjuaner/article/details/82876889


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐