[Solved] Springboot Reflection calls ServiceImpl Error: java.lang.NullPointerException, mapper is null

Springboot uses reflection to call serviceimpl and reports an error: java.lang.nullpointerexception

Because the mapper of ServiceImpl is null, the following is the original implementation code:

           // package name and class name
           Class classzz = Class.forName("com.XXX.XXX.service.impl.SenDataServiceImpl");

           // Get the constructor object
           Constructor constructor = null;
           try {
               constructor = classzz.getConstructor();
           } catch (NoSuchMethodException e) {
               e.printStackTrace();
           }
           // Create an object using the constructor object
           Object o = constructor.newInstance();
           // Pass the method to be executed Pass the parameter type, if not, you can leave it out
           Method method = classzz.getMethod("method name", long.class,String.class,String.class );
// invoke method, and pass parameters, if there are no parameters, you can leave them out
           Object obj =method.invoke(o,  5,
                  "param1",
                   "param2");

In the post query mode, you need to ContextLoader.getCurrentWebApplicationContext() firstly, but you haven’t gone to invoke, so the ContextLoader.getCurrentWebApplicationContext() is null.

The final solution is as follows:

1. Create a new class SpringBootBeanUtil

package com.smart.hyd.common.utils.reflect;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * SpringBoot Common class to get the bean tool class in the Spring container
 */
@Component
public class SpringBootBeanUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringBootBeanUtil.applicationContext == null) {
            SpringBootBeanUtil.applicationContext = applicationContext;
        }
        System.out.println("========ApplicationContext========");
//        System.out.println("========In the general class you can get the applicationContext object by calling SpringBootBeanUtil.getApplicationContext()========");
        System.out.println("========applicationContext="+ SpringBootBeanUtil.applicationContext +"========");
    }

    /**
     * get applicationContext
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * Get Bean by name.
     * @param name
     * @return
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    /**
     * Get Bean by class.
     * @param clazz
     * @return
     */
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    /**
     * Return the specified bean by name, and Clazz
     * @param name
     * @param clazz
     * @return
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }

}

2. Call SpringBootBeanUtil.getApplicationContext(). When invoking, the first parameter is applicationContext.getBean(ServiceImplType). Refer to the following code for specific implementation.

try {
               //Retrieve the created object from the ApplicationContext
               // Do not create the serviceimpi object directly by reflection, because the object created by reflection cannot instantiate the dao interface
               ApplicationContext applicationContext = SpringBootBeanUtil.getApplicationContext();
               //reflection creates the serviceimpi entity object, and the entity class
               Class<? > ServiceImplType = Class.forName("com.XXX.XXX.service.impl.SenDataServiceImpl");
              // Class<? > entityType = Class.forName("com.XXX.XXX.service.impl.SenDataServiceImpl");
               //reflection set method parameters.
               Method method = ServiceImplType.getDeclaredMethod("methodName",long.class,String.class,String.class );
               // get the instantiated bean in the ApplicationContext according to class
               method.invoke(applicationContext.getBean(ServiceImplType), 5,
                           "param1",
                           "param2");

           } catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
               e.printStackTrace();
               LOGGER.error("\n onMessage Receive Processing Message Failed - {}", "methodName");
           }

This solves the problem that the reflection calls ServiceImpland the mapper reports an error when it is null.

Read More: