Spring 多線程下注入 bean 問題詳解

問題

Spring 中多線程注入 userThreadService 注不進去,顯示 userThreadService 爲 null 異常。java

代碼以下:spring

public class UserThreadTask implements Runnable {
    @Autowired
    private UserThreadService userThreadService;

    @Override
    public void run() {
        AdeUser user = userThreadService.get("0");

        System.out.println(user);
    }
}

解決方案一

把要注入的 Service,經過構造傳過去,代碼以下:多線程

public class UserThreadTask implements Runnable {
    private UserThreadService userThreadService;

    public UserThreadTask(UserThreadService userThreadService) {
        this.userThreadService = userThreadService;
    }

    @Override
    public void run() {
        AdeUser user = userThreadService.get("0");

        System.out.println(user);
    }
}

Thread t = new Thread(``new UserThreadTask(userThreadService));

t.start();

解決方案二

經過ApplicationContext中獲取須要使用的Serviceapp

import org.springframework.beans.BeansException;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;


public class ApplicationContextHolder implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext context)
        throws BeansException {
        ApplicationContextHolder.context = context;
    }

    //根據bean name 獲取實例
    public static Object getBeanByName(String beanName) {
        if ((beanName == null) || (context == null)) {
            return null;
        }

        return context.getBean(beanName);
    }

    //只適合一個class只被定義一次的bean(也就是說,根據class不能匹配出多個該class的實例)
    public static Object getBeanByType(Class clazz) {
        if ((clazz == null) || (context == null)) {
            return null;
        }

        return context.getBean(clazz);
    }

    public static String[] getBeanDefinitionNames() {
        return context.getBeanDefinitionNames();
    }
}

Spring 加載本身定義的 ApplicationContextHolder 類ide

<bean class="cn.com.infcn.applicationcontext.ApplicationContextHolder"></bean>

或

@Bean
public ApplicationContextHolder applicationContextHolder() {
    return new ApplicationContextHolder();
}

根據 bean 的名稱獲取實例this

複製代碼代碼以下:線程

UserService user = (UserService);

ApplicationContextHolder.getBeanByName("userService");

根據 bean 的 Class 獲取實例(若是該Class存在多個實例,會報錯的)code

複製代碼代碼以下:get

UserService user = (UserService);

ApplicationContextHolder.getBeanByType(UserService.class);

這種方式,無論是否多線程,仍是普通的不受 Spring IoC 管理的類,均可以使用該方法得到 Spring IoC 管理的 bean。it

相關文章
相關標籤/搜索