SpringMVC獲取ApplicationContext - ApplicationContextAware實現AppContextHolder(含github源碼)

項目地址https://github.com/bootsrc/sword/tree/master/sword-springboot
父項目是https://github.com/bootsrc/sword


應用場景:

一般情況下,使用SpringMVC/SpringBoot的時候,各種bean註冊到Spring容器裏了,然後在需要這個bean的地方,

使用@Autowired或者@Resource標註的bean都可以被自動注入。 但是在某些場景下,

需要手動注入。比如在一個Util裏面,這個Util裏面的方法都是static的,這個時候,如果需要獲取Spring容器中的某個

bean,或者獲取到ApplicationContext, 這個時候,就需要一個ApplicationContext Holder的東西,這裏命名爲AppContextHolder

其實Spring裏有一個接口就是爲了這個應用場景而生的ApplicationContextAware

本人就開發了一個com.appjishu.swordboot.boot.AppContextHolder實現了這個接口, 源碼如下:

package com.appjishu.swordboot.boot;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 *
 * @author liushaoming
 *
 */
@Component
public class AppContextHolder implements ApplicationContextAware {
    private static ApplicationContext applicationContext = null;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (AppContextHolder.applicationContext == null) {
            AppContextHolder.applicationContext = applicationContext;
        }
    }

    // 獲取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    // 通過name獲取 Bean.
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    // 通過class獲取Bean.
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    // 通過name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}

使用的時候,很簡單, 就像使用Spring原生的ApplicationContext一樣, 現在要獲取一個已經註冊到容器裏的一個bean Student

@Configuration
public class SysConfig {
    @Bean(name = "myStudent")
    public Student student() {
        Student student=new Student();
        student.setName("Frank Liu");
        student.setAddress("Shanghai");
        return student;
    }
}

使用AppContextHolder獲取bean的操作

Student student0 = (Student) AppContextHolder.getBean("myStudent");
// 或者
Student student1 = (Student) AppContextHolder.getBean(Student.class);
log.info("student0.name={}", student0.getName());

測試方法:
在idea/eclipse裏,導入maven項目sword-springboot, 右鍵運行SwordBootApp -> run as -> Java Application

這是一個springboot項目,打開瀏覽器訪問地址http://localhost:15000/test

可以運行測試AppContextHolder的測試代碼, 貼出TestUtil裏的方法

public class TestUtil {
    private static final Logger log = LoggerFactory.getLogger(TestUtil.class);

    public static void testAppContextHolder() {
        log.info("--testAppContextHolder start---");
        Student student0 = (Student) AppContextHolder.getBean("myStudent");
        Student student1 = (Student) AppContextHolder.getBean(Student.class);

        // 如果"student0 == student1"成立,則驗證了AppContextHolder的確能獲取到Spring容器ApplicationContext
        // 而且Spring容器默認註冊bean使用的是單例模式
        log.info("student0==student1? {}", student0 == student1);
        log.info("-------------------");
        log.info("student0.name={}", student0.getName());
        log.info("student0.address={}", student0.getAddress());
        log.info("-------------------");
        log.info("student1.name={}", student1.getName());
        log.info("student1.address={}", student1.getAddress());
        log.info("--testAppContextHolder done---");
    }
}

打印結果: 說明測試成功了

2019-01-06 15:43:47.563  INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil     : --testAppContextHolder start---
2019-01-06 15:43:47.564  INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil     : student0==student1? true
2019-01-06 15:43:47.564  INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil     : -------------------
2019-01-06 15:43:47.565  INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil     : student0.name=Frank Liu
2019-01-06 15:43:47.565  INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil     : student0.address=Shanghai
2019-01-06 15:43:47.566  INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil     : -------------------
2019-01-06 15:43:47.566  INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil     : student1.name=Frank Liu
2019-01-06 15:43:47.566  INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil     : student1.address=Shanghai
2019-01-06 15:43:47.566  INFO 21612 --- [io-15000-exec-1] com.appjishu.swordboot.util.TestUtil     : --testAppContextHolder done---

注意事項:

AppContextHolder在SpringBoot裏使用,只需要在類名AppContextHolder前標註@Component

如果在SpringMVC裏使用的,需要用@Component標註類AppContextHolder, 並且在applicationContext.xml裏面設置

包含AppContextHolder所在的package, 或者直接用bean標籤來註冊它。

項目地址https://github.com/bootsrc/sword/tree/master/sword-springboot
父項目是https://github.com/bootsrc/sword

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章