多線程情況下如何注入Mapper,自己實例化的類如何注入其他Spring註解類

在多線程下,會發現Spring的自動注入失效了,原因是,Spring認爲在多線程下這樣做是危險的,如果你習慣用框架了,那麼我們都知道默認是單例的,那在多線程下如何注入Mapper,供我們使用呢?

在多線程的項目中,我也遇到了這個問題,而且我mapper接口以上的類的實例化是我自己通過java反射實例化的,我只有在Mapper接口的時候才加了@Mapper註解,導致的直接問題是,如果我如果在業務類中寫平常的@Resouce注入Mapper的話,mapper爲Null,這完全可以理解,因爲我的業務類並沒有加任何註解,沒有交給spring管理,是自己實例化的,這樣導致mapper無法注入,那我該如何調用mapper呢?哦吼!可以在業務類中申明一個mapper變量,然後在反射初始化時添加一個初始化方法

注意: 我討論的情況是一般的業務類是自己實例化,而一部分類交由spring管理

你可能會說:樓主有病吧?一部分自己實例化,一部分人家spring管理,豈不是很亂

非也,java反射是動態獲取類,實例化類的最初方法;

其次是從前的普通的springmvc項目,我們記得會有很多的配置文件,一個bean配置可以在初始化時添加你想要的屬性配置,

我們演化出了配置文件的方法;

現在的很多框架,比如springboot,springcloud等等都將這些工作自己處理,我們不必關心,寫的更多的是業務;

歸根到底,他們都是基於java反射的。

java反射的好處:你可以在代碼的層面上實例化你的特定類,比如根據模糊類名的方式實例化等等,並且在實例化中你可以做任何事情。

話不多說,我的情況是:

我實例化了com.skxx.work.busi包下的匹配接口的類,同時注意此處我添加了一個initMapper()方法,這個方法就是爲了給我的業務類配置mapper的。

再看我的業務類中:

我的UserLogic並沒有添加任何註解,之前說過,這個類是我自己通過上面的反射實例化的,並沒有交由spring管理

但是我的Mapper接口交由spring管理了,那我我們接下來如何獲取它呢?通過spring上下文,此處有一個工具方法來獲取你的上下文中的任何bean,上面的代碼和諸位其實關係並不大,只是爲了大家理解情況,下面的工具代碼就不是圖片了

這是我的mapper,它交由spring管理了:

 工具類:通過上下文獲取任何已經實例化的bean

package com.skxx.config.spring;

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

/**
 * @program: coalpreparation
 * @description:  解決在多線程情況下,非註解實例化類時,無法注入mapper的問題
 *              因爲類的實例化並不沒有交給spring,所以要自己手動去獲取mapper
 * @author: Mr.MYR(ClearLoveQ)
 * @create: 2020-04-21 14:24
 **/
@Component
public class SpringContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

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

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

    /**
     * 通過name獲取 Bean.
     *
     * @param name
     *            Bean's name
     * @return
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    /**
     * 通過class獲取Bean.
     *
     * @param clazz
     * @return
     */
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    /**
     * 通過name,以及Clazz返回指定的Bean
     *
     * @param name
     * @param clazz
     * @return
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }

}

 

至此,我相信你對spring的理解可能更深一點了,祝大家在代碼的路上不斷前進。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章