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