在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接口
@Componentpublic class SpringUtil implements ApplicationContextAware { private static ApplicationContext applicationContext = null;// 非@import显式注入,@Component是必须的,且该类必须与main同包或子包 // 若非同包或子包,则需手动import 注入,有没有@Component都一样 // 可复制到Test同包测试 @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if(SpringUtil.applicationContext == null){ SpringUtil.applicationContext = applicationContext; } System.out.println("---------------com.ilex.jiutou.util.Test.Main.SubPackage.SpringUtil---------------"); } //获取applicationContext public static ApplicationContext getApplicationContext() { return applicationContext; } //通过name获取 Bean. public static Object getBean(String name){ return getApplicationContext().getBean(name); } //通过class获取Bean. public staticT getBean(Class clazz){ return getApplicationContext().getBean(clazz); } //通过name,以及Clazz返回指定的Bean public static T getBean(String name,Class clazz){ return getApplicationContext().getBean(name, clazz); }}
需要被spring注入,覆写setApplicationContext
2. 普通类
//@Component 在不可扫描区域,且不需要注入,作为一个普通的util类public class SpringUtil{ private static ApplicationContext applicationContext = null; public static void setApplicationContext(ApplicationContext applicationContext){ if(SpringUtil.applicationContext == null){ SpringUtil.applicationContext = applicationContext; } } //获取applicationContext public static ApplicationContext getApplicationContext() { return applicationContext; } //通过name获取 Bean. public static Object getBean(String name){ return getApplicationContext().getBean(name); } //通过class获取Bean. public staticT getBean(Class clazz){ return getApplicationContext().getBean(clazz); } //通过name,以及Clazz返回指定的Bean public static T getBean(String name,Class clazz){ return getApplicationContext().getBean(name, clazz); }}
不需要被注入,但需要手动调用
主函数
@SpringBootApplication@Import(value={UserFooterService.class})public class Test { public static void main(String[] args) { ApplicationContext ctx = SpringApplication.run(Test.class, args); // SpringUtil.setApplicationContext(ctx); 这个对应于AnoStatic String[] beanNames = ctx.getBeanDefinitionNames(); System.out.println("beanNames个数:"+beanNames.length); for(String bn:beanNames){ System.out.println(bn); } // 测试加载UserFooterService UserFooterService userFooterService = (UserFooterService) SpringUtil.getBean(UserFooterService.class); List
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