多线程或监听器@Autowired注入null空指针

发布时间 2023-05-31 14:14:42作者: 睡个好觉"
// 问题:在多线程中使用@Autowired注入IUserService时,userService使用时为null,获取不到bean
// 原因:new thread不在spring容器中,也就无法获得spring中的bean对象;
@Autowired
private IUserService userService;

// 解决:手动获取bean对象
private IUserService userService = AppContextUtils.getBean(IUserService.class);
简单配置类
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 获取bean实例
 */
@Component
public class AppContextUtils implements ApplicationContextAware, BeanDefinitionRegistryPostProcessor {

    private static ApplicationContext appCtx;

    private static BeanDefinitionRegistry beanDefinitionRegistry;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        appCtx = applicationContext;
    }

    public static ApplicationContext getApplicationContext(){
        return appCtx;
    }

    /**
     * 这是一个便利的方法,帮助我们快速得到一个BEAN
     * @param beanName bean的名字
     * @return 返回一个bean对象
     */
    public static Object getBean( String beanName ) {
        return appCtx.getBean( beanName );
    }

    /**
     * 通过类型获得BEAN
     * @param cls
     * @return
     */
    public static <T> T getBean(Class<T> cls){
        return appCtx.getBean(cls);
    }

    /**
     *
     * @param beanName
     * @param cls
     * @param <T>
     * @return
     */
    public static <T> T getBean(String beanName, Class<T> cls){
        return appCtx.getBean(beanName, cls);
    }

    public static String getEnvProp(String key){
        return appCtx.getEnvironment().getProperty(key);
    }

    public static void unRegisterBean(String beanName){
        if(appCtx.containsBean(beanName)) {
            beanDefinitionRegistry.removeBeanDefinition(beanName);
        }
    }

    public static <T> T registerBean(String name, Class<T> clazz, Object... args) {
        if(appCtx.containsBean(name)) {
            Object bean = appCtx.getBean(name);
            if (bean.getClass().isAssignableFrom(clazz)) {
                return (T) bean;
            } else {
                throw new RuntimeException("BeanName 重复 " + name);
            }
        }

        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
        for (Object arg : args) {
            beanDefinitionBuilder.addConstructorArgValue(arg);
        }
        BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();

        beanDefinitionRegistry.registerBeanDefinition(name, beanDefinition);
        return appCtx.getBean(name, clazz);
    }

    public static <T> Map<String, T> getBeansOfType(Class<T> cls){
        return appCtx.getBeansOfType(cls);
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        AppContextUtils.beanDefinitionRegistry = beanDefinitionRegistry;
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
       //doNothing
    }
}