SpringBoot如何使用ApplicationContext獲取bean對象

使用ApplicationContext獲取bean對象

編寫一個ApplicationContextFactory工廠類

public class ApplicationContextFactory{
 private static ApplicationContext applicationContext = null;
 public static void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  applicationContext = applicationContext;
 }
 public static ApplicationContext getApplicationContext(){
  return applicationContext;
 }
}

在SpringBoot的啟動類中設置ApplicationContext

public class Application {
 public static void main(String[] args) {
  ConfigurableApplicationContext app = SpringApplication.run(Application.class, args);
  ApplicationContextFactory.setApplicationContext(app);
 }
}

通過ApplicationContextFactory獲取SpringApplication從而獲取bean對象

ApplicationContext applicationContext=ApplicationContextFactory.getApplicationContext();
Clazz clazz = applicationContext.getBean(Clazz.class);

SpringBoot Bean註入的深入研究

下面代碼可正常運行

DemoService

@Service
public class DemoService {
    public void save(){
        System.out.println("DemoService save");
    }
}

CommonClass

@Component
public class CommonClass {
    @Resource
    private DemoService demoService;
    public void fun(){
        System.out.println("fun");
        demoService.save();
    }
}

Controller

@Resource
private CommonClass commonClass;
@ResponseBody
@GetMapping("/fun")
public void fun(){
    commonClass.fun();
}

下面代碼不能正常運行

DemoService

@Service
public class DemoService {
    public void save(){
        System.out.println("DemoService save");
    }
}

CommonClass

public class CommonClass {
    @Resource
    private DemoService demoService;
    public void fun(){
        System.out.println("fun");
        demoService.save();
    }
}

Controller

@ResponseBody
@GetMapping("/fun")
public void fun(){
    CommonClass commonClass = new CommonClass();
    commonClass.fun();
}

比較

比較兩個代碼發現後者與前者的區別:因後者的CommonClass 沒有使用@Component標註,所以在Controller中不能才用註入方式生成CommonClass對象,而是才用new的方式生成瞭該對象。

這樣一來,CommonClass 對象是手工創建,所以在它內部註入DemoService 對象的代碼就錯誤瞭。

解決方案

新建工具類

@Component
public class ApplicationContextUtil implements ApplicationContextAware {
    private static  ApplicationContext act;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        act = applicationContext;
    }
    /**
     * 根據bean的名字獲取工廠中對應的bean對象
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
        return act.getBean(beanName);
    }
}

:實際測試發現上面代碼中的static不能省略

DemoService

@Service
public class DemoService {
    public void save(){
        System.out.println("DemoService save");
    }
}

CommonClass

public class CommonClass {
    @Resource
    private DemoService demoService;
    public void fun(){
    DemoService demoService = (DemoService) ApplicationContextUtil.getBean("demoService");
        System.out.println("fun");
        demoService.save();
    }
}

此處不再采用註入的方式獲取DemoService對象,而是通過工具類的方式

Controller

@ResponseBody
@GetMapping("/fun")
public void fun(){
    CommonClass commonClass = new CommonClass();
    commonClass.fun();
}

再次運行程序,一切正常

應用

在SpringBoot整合Shiro的案例中,自定義Realm時,需要使用Service的對象。因為自定義的Realm類不能使用@Component之類的註解註釋,所以使用本案例介紹的方法是正確的解決方案。盡管在1.6.0的shiro-all中下面代碼可以正確運行:

在這裡插入圖片描述

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: