关于Spring+MyBatis的MapperScannerConfigurer无法加载place-holder属性问题分析
admin
2023-07-31 05:00:06
0

在1.2.5以下版本的mybatis-spring一下配置可能会无法启动,但junit方式可以启动

配置:

<bean id="sqlSessionFactoryName" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation"
     value="${dao.mybatis.sqlSessionFactory.configLocation}" />
bean>
经分析1.2.5以下的mybatis-spring的MapperScannerConfigurer中判断是否为GenericApplicationContext的实例
启动时不为GenericApplicationContext的实例时属性无法加载
1.3.1以后版本已经修改

   
 
 
 


到此Mybatis本身的属性已经可以正常加载了,但在正式环境中可能会碰到xml中其他注入属性无法加载,如Dubbo的配置信息注入
经分析原因在于MapperScannerConfigurer中的代码有问题。
private void processPropertyPlaceHolders() {
   Map prcs = this.applicationContext.getBeansOfType(PropertyResourceConfigurer.class);
   if(!prcs.isEmpty() && this.applicationContext instanceof ConfigurableApplicationContext) {
   红色这一行代码会导致在属性加载前加载dubbo的xml文件中定义的bean,导致属性未注入
解决方法如下:
   新建对象继承MapperScannerConfigurer,注入自定义属性在开始扫描前加载,示例如下:
   
   

import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.PropertyResourceConfigurer;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

/**
*  
*/
public class SelfMapperScannerConfigurer extends MapperScannerConfigurer {
   private ApplicationContext applicationContext;
   private String beanName;
   private String preLoadPropBeanName;

   public void setApplicationContext(ApplicationContext applicationContext) {
       super.setApplicationContext(applicationContext);
       this.applicationContext = applicationContext;
   }

   @Override
   public void setBeanName(String name) {
       this.beanName = name;
       super.setBeanName(name);
   }

   public void setPreLoadPropBeanName(String preLoadPropBeanName) {
       this.preLoadPropBeanName = preLoadPropBeanName;
   }

   public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
       if (this.preLoadPropBeanName != null) {
           preloadPropertyResource();
           this.setProcessPropertyPlaceHolders(false);
       }
       super.postProcessBeanDefinitionRegistry(registry);

   }

   private void preloadPropertyResource() {
       if (applicationContext.containsBean(this.preLoadPropBeanName)) {
           BeanDefinition mapperScannerBean = ((ConfigurableApplicationContext) this.applicationContext).getBeanFactory().getBeanDefinition(this.beanName);
           DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
           factory.registerBeanDefinition(this.beanName, mapperScannerBean);
           PropertyResourceConfigurer configurer = applicationContext.getBean(this.preLoadPropBeanName, PropertyResourceConfigurer.class);
           configurer.postProcessBeanFactory(factory);
           if (applicationContext.containsBean("propertyConfigurer")) {
               configurer = applicationContext.getBean(this.preLoadPropBeanName, PropertyResourceConfigurer.class);
               configurer.postProcessBeanFactory(factory);
           }

           MutablePropertyValues values1 = mapperScannerBean.getPropertyValues();
           String basePackage = this.updatePropertyValue("basePackage", values1);
           String sqlSessionFactoryBeanName = this.updatePropertyValue("sqlSessionFactoryBeanName", values1);
           String sqlSessionTemplateBeanName = this.updatePropertyValue("sqlSessionTemplateBeanName", values1);
           this.setBasePackage(basePackage);
           this.setSqlSessionFactoryBeanName(sqlSessionFactoryBeanName);
           this.setSqlSessionTemplateBeanName(sqlSessionTemplateBeanName);


       }
   }


   private String updatePropertyValue(String propertyName, PropertyValues values) {
       PropertyValue property = values.getPropertyValue(propertyName);
       String rst = null;
       if (property == null) {
           return null;
       } else {
           Object value = property.getValue();
           rst = value == null ? null : (value instanceof String ? value.toString() : (value instanceof TypedStringValue ? ((TypedStringValue) value).getValue() : null));
       }
       return rst;
   }
}
修改配置:

 
 
 
 
 





相关内容

热门资讯

网传网易云音乐人运营全员遭裁 ... 7月7日消息 ,近日,市场有消息称网易云音乐核心团队裁员的相关消息,引发外界热议。 网传内容指出,网...
辰山植物园等联合团队摸清215... 辰山植物园等联合团队20年潜心研究 摸清215种植物的“碳胃口” 龙吴路徐梅路交会处往西南方向走20...
2026世界人工智能大会7月1... 央广网上海7月7日消息(记者冯丽 实习记者曹倍瑜)2026世界人工智能大会暨人工智能全球治理高级别会...
国内短信发送通道类型科普:直连... 随着数字经济的蓬勃发展,短信作为企业触达用户的核心渠道,其底层传输架构的合规性与稳定性备受关注。在国...
空间计算重生!苹果曾力推失败,... AR 眼镜,终于又开始像 AR 眼镜了。 前段时间雷科技参加了 Rokid Open Day 202...
2026世界人工智能大会亮点剧... 上证报中国证券网讯(记者 宋薇萍)上海市经济信息化委主任汤文侃7月7日在上海市政府新闻发布会上表示,...
法国总统府、国际足联主席强烈谴... 7月5日,美加墨世界杯八分之一决赛,法国队在费城体育场以1:0战胜巴拉圭队,成为本届世界杯第二支晋级...
公共二维码变涉黄码、诈骗码,该... 拿起手机扫一扫身边的二维码早已是我们生活中习以为常的动作。但一段时间来,多地网民反映,自己在扫一些公...
原创 今... 虽说现在完全不推荐大家买手机,特别是 618 过后有些机型还涨价了就很离谱~ 但安兔兔最近公布的这个...
曾被中方制裁的荷兰大臣率团访华... 荷兰外贸与发展合作大臣舍尔茨玛将展开三天访华贸易之行。外媒普遍关注到,2021年中方曾将他列入制裁名...