多线程情况下如何注入Mapper,自己实例化的类如何注入其他Spring注解类

2022-06-27 11:46:45

在多线程下,会发现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的理解可能更深一点了,祝大家在代码的路上不断前进。

  • 作者:ClearLoveQ
  • 原文链接:https://blog.csdn.net/ClearLoveQ/article/details/105661353
    更新时间:2022-06-27 11:46:45