MybatisPlus 根据实体类获取对应的Mapper
一、思路
MybatisPlus没有直接提供根据实体类获取Mapper的方法, 因此我们考虑手动构造.
一个思路是在Bean初始化时构建一个Map关系, 这里主要用到BeanPostProcessor.
BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口, 我们可以通过实现它对Spring管理的bean进行再加工。
接口声明如下:
public interface BeanPostProcessor {// bean初始化方法调用前被调用Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;// bean初始化方法调用后被调用Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
说明:
- postProcessBeforeInitialization方法会在任何bean初始化回调(如InitializingBean的afterPropertiesSet方法或者自定义的init-method)之前被调用。也就是说,这个方法会在bean的属性已经设置完毕,但还未进行初始化时被调用。
- postProcessAfterInitialization方法在任何bean初始化回调(比如InitializingBean的afterPropertiesSet或者自定义的初始化方法)之后被调用。这个时候,bean的属性值已经被填充完毕。返回的bean实例可能是原始bean的一个包装。
二、Bean的生命周期
整个Bean生命周期的调用顺序如图所示:
三、实现代码
代码如下:
i
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dongan.core.mybatis.MybatisReflect;
import org.apache.commons.lang3.ObjectUtils;
import org.mybatis.spring.mapper.MapperFactoryBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;@Component
public class MybatisBeanPostProcessor implements BeanPostProcessor {private final static Map<String, String> MAP_MAPPER_NAME_TO_ENTITY_CLASS_NAME = new ConcurrentHashMap<>();@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof MapperFactoryBean) {Class<?> mapperInterface = ((MapperFactoryBean<?>) bean).getMapperInterface();Type[] genericInterfaces = mapperInterface.getGenericInterfaces();if (ObjectUtils.isNotEmpty(genericInterfaces)) {Type[] actualTypeArguments = ((ParameterizedType) genericInterfaces[0]).getActualTypeArguments();String entityClassName = actualTypeArguments[0].getTypeName();MAP_MAPPER_NAME_TO_ENTITY_CLASS_NAME.put(beanName, entityClassName);}}return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof BaseMapper) {String entityClassName = MAP_MAPPER_NAME_TO_ENTITY_CLASS_NAME.get(beanName);MybatisReflect.putEntityClassNameToMapper(entityClassName, bean);}return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);}}
import com.baomidou.mybatisplus.core.mapper.BaseMapper;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;public class MybatisReflect {private final static Map<String, BaseMapper<?>> MAP_CLASSNAME_TO_MAPPER = new ConcurrentHashMap<>();public static void putEntityClassNameToMapper(String className, Object bean){MAP_CLASSNAME_TO_MAPPER.put(className, (BaseMapper<?>) bean);}public static <T> BaseMapper<T> getMapper(String className) {return (BaseMapper<T>) MAP_CLASSNAME_TO_MAPPER.get(className);}public static <T> BaseMapper<T> getMapper(Class<?> t) {return (BaseMapper<T>) MAP_CLASSNAME_TO_MAPPER.get(t.getName());}
}