在spring中,我們通過如下代碼取得一個spring托管類:
- ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml");
- ac.getBean("beanId");
在spring boot中,我參考了如下三篇文章:
讓非Spring管理的類獲得一個Bean
http://blog.sina.com.cn/s/blog_72ef7bea0102wcvk.htmlblog.sina.com.cn/s/blog_72ef7bea0102wcvk.html
Spring Boot普通類調用bean
http://blog.csdn.net/u014695188/article/details/52396880
SpringBoot-獲取上下文
http://www.2cto.com/kf/201701/582935.html
做了一些實踐。
首先,我們需要一個媒介,來取得AppicationContext——SpringUtil
這個類有兩種方式:
1. 實現ApplicationContextAware接口
@Component
public class SpringUtil implements ApplicationContextAware {
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> ApplicationContext applicationContext = <span class="hljs-keyword">null</span>;</br>
// 非@import顯式注入,@Component是必須的,且該類必須與main同包或子包
// 若非同包或子包,則需手動import 注入,有沒有@Component都一樣
// 可復制到Test同包測試
<span class="hljs-annotation">@Override</span></br>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setApplicationContext</span><span class="hljs-params">(ApplicationContext applicationContext)</span> <span class="hljs-keyword">throws</span> BeansException </span>{</br>
<span class="hljs-keyword">if</span>(SpringUtil.applicationContext == <span class="hljs-keyword">null</span>){</br>
SpringUtil.applicationContext = applicationContext;</br>
}</br>
System.out.println(<span class="hljs-string">"---------------com.ilex.jiutou.util.Test.Main.SubPackage.SpringUtil---------------"</span>);</br>
}</br></br>
<span class="hljs-comment">//獲取applicationContext</span></br>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> ApplicationContext <span class="hljs-title">getApplicationContext</span><span class="hljs-params">()</span> </span>{</br>
<span class="hljs-keyword">return</span> applicationContext;</br>
}</br>
//通過name獲取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}</br></br>
<span class="hljs-comment">//通過class獲取Bean.</span></br>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <T> <span class="hljs-function">T <span class="hljs-title">getBean</span><span class="hljs-params">(Class<T> clazz)</span></span>{</br>
<span class="hljs-keyword">return</span> getApplicationContext().getBean(clazz);</br>
}</br></br>
<span class="hljs-comment">//通過name,以及Clazz返回指定的Bean</span></br>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <T> <span class="hljs-function">T <span class="hljs-title">getBean</span><span class="hljs-params">(String name,Class<T> clazz)</span></span>{</br>
<span class="hljs-keyword">return</span> getApplicationContext().getBean(name, clazz);</br>
}</br>
}
需要被spring注入,覆寫setApplicationContext
2. 普通類
//@Component 在不可掃描區域,且不需要注入,作為一個普通的util類
public class SpringUtil{
private static ApplicationContext applicationContext = null;
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setApplicationContext</span><span class="hljs-params">(ApplicationContext applicationContext)</span></span>{</br>
<span class="hljs-keyword">if</span>(SpringUtil.applicationContext == <span class="hljs-keyword">null</span>){</br>
SpringUtil.applicationContext = applicationContext;</br>
}</br></br>
}</br></br>
<span class="hljs-comment">//獲取applicationContext</span></br>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> ApplicationContext <span class="hljs-title">getApplicationContext</span><span class="hljs-params">()</span> </span>{</br>
<span class="hljs-keyword">return</span> applicationContext;</br>
}</br></br>
<span class="hljs-comment">//通過name獲取 Bean.</span></br>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Object <span class="hljs-title">getBean</span><span class="hljs-params">(String name)</span></span>{</br>
<span class="hljs-keyword">return</span> getApplicationContext().getBean(name);</br></br>
}</br>
<span class="hljs-comment">//通過class獲取Bean.</span></br>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <T> <span class="hljs-function">T <span class="hljs-title">getBean</span><span class="hljs-params">(Class<T> clazz)</span></span>{</br>
<span class="hljs-keyword">return</span> getApplicationContext().getBean(clazz);</br>
}</br>
<span class="hljs-comment">//通過name,以及Clazz返回指定的Bean</span></br>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <T> <span class="hljs-function">T <span class="hljs-title">getBean</span><span class="hljs-params">(String name,Class<T> clazz)</span></span>{</br>
<span class="hljs-keyword">return</span> getApplicationContext().getBean(name, clazz);</br>
}</br>
}
不需要被注入,但需要手動調用
主函數
@SpringBootApplication
@Import(value={UserFooterService.class})
public class Test {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Test.class, args);
<span class="hljs-comment">// SpringUtil.setApplicationContext(ctx); 這個對應於AnoStatic</span></br></br>
String[] beanNames = ctx.getBeanDefinitionNames();</br>
System.out.println(<span class="hljs-string">"beanNames個數:"</span>+beanNames.length);</br>
<span class="hljs-keyword">for</span>(String bn:beanNames){</br>
System.out.println(bn);</br>
}</br></br>
<span class="hljs-comment">// 測試加載UserFooterService</span></br>
UserFooterService userFooterService = (UserFooterService) SpringUtil.getBean(UserFooterService.class);</br>
List<Map<String,Object>> list = userFooterService.hotTopic(<span class="hljs-string">"0"</span>, <span class="hljs-string">"5"</span>);</br>
System.out.println(list.toString());</br></br>
<span class="hljs-comment">// 測試加載SpringUtil</span></br>
SpringUtil springUtil = (SpringUtil)SpringUtil.getBean(SpringUtil.class);</br>
System.out.println(springUtil);</br>
}</br></br>
// @Bean
// public SpringUtil springUtil() {
// return new SpringUtil();
// }
}
UserFooterService是一個業務類,這里不榕樹
建立如下的測試結構:
Main/Test 主函數
AnoStatic/SpringUtil 普通類
Main/SubPackage/SpringUtil 實現ApplicationContextAware,但為主函數子包
NonSubPackage/SpringUtil 實現ApplicationContextAware,但非主函數子包和同包
SpringUtil注入方式有三種,在參考的三篇博客均有說明,在此僅總結:
1. 類與SpringBootApplication同包或子包,此在ComponentScan的掃描范圍之內,在類上@Component注解即可,會被自動注入;
2. 無論位置,都可通過在主函數用@import或@bean來手動注入。
第一種SpringUtil方式必須被spring注入,否則會報
Exception in thread "main" java.lang.NullPointerException
at com.ilex.jiutou.util.Test.NonSubPackage.SpringUtil.getBean(SpringUtil.java:40)
at com.ilex.jiutou.util.Test.Main.Test.main(Test.java:34)
表示applicationContext獲取失敗
第二種方式,SpringUtil可被注入可不被注入
當不注入時,主函數這一段:
// 測試加載SpringUtil
SpringUtil springUtil = (SpringUtil)SpringUtil.getBean(SpringUtil.class);
System.out.println(springUtil);
報錯:
No qualifying bean of type [**.Test.AnoStatic.SpringUtil