1. 程式人生 > >ApplicationContextAware實現AppContextHolder(含github原始碼)

ApplicationContextAware實現AppContextHolder(含github原始碼)

專案地址https://github.com/flylib/sword/tree/master/sword-springboot
父專案是https://github.com/flylib/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/flylib/sword/tree/master/sword-springboot
父專案是https://github.com/flylib/sword