SpringBoot普通類獲取spring容器中bean的操作
前言
在spring框架中,是無法在普通類中通過註解注入例項的,因為sping框架在啟動的時候,就會將標明交給spring容器管理的類進行例項化,並梳理他們彼此的依賴關係,進行注入,沒有交給spring容器管理的普通類,是不會進行注入的,即使你使用了注入的相關注解。這個時候,如果我們需要在普通類中獲取spring容器中的例項,就需要一些特定的方法,這裡將整理一下如何在springboot中實現這樣的方法。
建立springboot工程demo
專案結構圖示
專案結構說明
service包下為demo介面和實現類,新增@Service註解,標明交由spring框架管理例項。
test包下為測試用的普通類,測試獲取例項的方法。
utils包下為自定義的獲取spring容器中例項的方法。
工程程式碼
service
package com.demo.service; public interface IDemoService { String demo(); }
package com.demo.service.impl; import com.demo.service.IDemoService; import org.springframework.stereotype.Service; @Service public class DemoServiceImpl implements IDemoService { @Override public String demo() { return "Hello World"; } }
@Service註解標明瞭此例項交由spring容器管理
test
package com.demo.test; import com.demo.service.IDemoService; import com.demo.utils.BeanUtil; public class Test { public void test(){ //獲取已經例項化的介面bean IDemoService bean = BeanUtil.getBean(IDemoService.class); //執行bean中方法 String demo = bean.demo(); //輸出結果 System.out.println(demo); } }
utils
package com.demo.utils; import org.springframework.context.ConfigurableApplicationContext; public class BeanUtil { //將管理上下文的applicationContext設定成靜態變數,供全域性呼叫 public static ConfigurableApplicationContext applicationContext; //定義一個獲取已經例項化bean的方法 public static <T> T getBean(Class<T> c){ return applicationContext.getBean(c); } }
啟動類
package com.demo; import com.demo.test.Test; import com.demo.utils.BeanUtil; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication() public class DemoApplication { public static void main(String[] args) { //run方法的返回值ConfigurableApplicationContext繼承了ApplicationContext上下文介面 ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class,args); //將run方法的返回值賦值給工具類中的靜態變數 BeanUtil.applicationContext = applicationContext; //測試獲取已經例項化的介面bean,執行bean中方法 new Test().test(); } }
測試效果
可以看到,test方法應成功獲取DemoService介面例項,這裡總結的是springboot工程在普通類獲取sping容器中例項的方法,其原理和傳統方法其實都是一樣的,獲取上下文環境,從上下文環境中拿到spring容器管理的例項。
補充知識:SpringBoot獲取Bean
一種最簡單的方法是實現ApplicationContextAware類來獲取容器中的bean:
import org.springframework.beans.BeansException; 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; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringContextUtil.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); } }
我們可以通過bean的名稱、bean的型別或者bean的名稱+型別來獲取容器中的bean。
預設情況下,Spring容器中的bean是單例的,為此我做了一個測試,我建立了兩個bean,一個是預設的,一個是我指定多例的:
import org.springframework.stereotype.Service; /** * 這是一個單例的bean */ @Service public class BeanSingletonService { }
import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; /** * 這是一個多例的bean */ @Service @Scope("prototype") public class BeanPrototypeService { }
驗證下我的想法:
import com.xqnode.learning.common.config.SpringContextUtil; import com.xqnode.learning.service.BeanPrototypeService; import com.xqnode.learning.service.BeanSingletonService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class LearningApplicationTests { @Test public void contextLoads() { BeanSingletonService s1 = SpringContextUtil.getBean(BeanSingletonService.class); BeanSingletonService s2 = SpringContextUtil.getBean(BeanSingletonService.class); BeanPrototypeService p1 = SpringContextUtil.getBean(BeanPrototypeService.class); BeanPrototypeService p2 = SpringContextUtil.getBean(BeanPrototypeService.class); System.out.println("s1==s2: " + s1.equals(s2)); System.out.println("p1==p2: " + p1.equals(p2)); } }
從結果中可以看到預設的BeanSingletonService 這個bean是單例的,兩個物件完全相等,而我指定的BeanPrototypeService 這個bean則是多例的,兩個bean不相同。
以上這篇SpringBoot普通類獲取spring容器中bean的操作就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。