SpringBoot - 获取ApplicationContext,调用下层服务

问题背景

我们使用TestNG + SpringBoot实现基于关键字的自动化测试。
问题是,如果直接通过类名和方法名做反射,就无法@Autowired到下层的Service。原因是在方法调用的时候,cla.newInstance()新建了一个对象。源代码如下:

Class cla = Class.forName("com.demo.test." + ClassName);
Method method = cla.getMethod(MethodName, String.class);
method.invoke(cla.newInstance());

解决方案

Step1. 新建SpringContextUtil,获取当前的applicationContext

注意SpringContextUtil必须实现ApplicationContextAware

@Component
public class SpringContextUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        if (SpringContextUtil.applicationContext == null) {
            SpringContextUtil.applicationContext = ctx;
        }
    }

    // 获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    // 通过name获取 Bean.
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    // 通过class获取Bean.
    public static  T getBean(Class clazz) {
        return getApplicationContext().getBean(clazz);
    }

    // 通过name,以及Clazz返回指定的Bean
    public static  T getBean(String name, Class clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}
Step2. 调用类使用SpringContextUtil.getBean(cla)获取带有applicationContext的clazz
Class cla = Class.forName("com.demo.test." + param.get("Keyword").toString());
Object clazz = SpringContextUtil.getBean(cla);
Method method = clazz.getClass().getMethod(param.get("Method").toString(), ITestContext.class, Map.class);
method.invoke(clazz, ctx, param);

已注入dataSourceConfig和commonService


image.png
小心:类名是小写开头

一开始,我是通过类名去获取反射的object对象的,使用了cla.getSimpleName()。
这个方法本身没错,但是一直报错:NoSuchBeanDefinitionException。


SpringBoot - 获取ApplicationContext,调用下层服务_第1张图片
image.png

查找了一下原因,才终于发现,getBean里如果传String,必须是小写字母开头才行!!
将上面方法更新为如下写法,把首字母转成小写再去getBean。终于搞定。

    public static Object getBean(String name) {
        char[] cs = name.toCharArray();
        cs[0] += 32; //首字母大写到小写
        name = String.valueOf(cs);
        return getApplicationContext().getBean(name);
    }

http://www.cnblogs.com/imeng/p/5952109.html
http://blog.csdn.net/jinzhencs/article/details/51673782
https://stackoverflow.com/questions/31237062/using-class-forname-but-want-to-autowire-members-of-the-target-class

你可能感兴趣的:(SpringBoot - 获取ApplicationContext,调用下层服务)