Spring动态加载项目(包含各个业务层),主要解决如何加载Mapper、Service,以及二次加载的问题

Spring动态加载项目(包含各个业务层),主要解决如何加载Mapper、Service,以及二次加载的问题,第1张

Spring动态加载项目(包含各个业务层),主要解决如何加载Mapper、Service,以及二次加载的问题 针对很多人问我的如何注入mapper以及service接口的问题,特此写一篇博文解答,供后来者参考 PS:第一次写博文不当之处敬请谅解
1、前提
  • 首先参考该博文–》
    spring boot 动态加载模块(加载外部jar包)
  • 但我要说的是加载的方式可以是有多种的,不一定是需要打包成jar包,也可以直接是字节码文件。
  • 具体怎么做可以自行研究一下,不会的可以评论提问,在此就不说了,不是重点。
2、主要加载区分部分:(重要!)

  • 照图中的方法将Service和Mapper在加载前进行一次特殊化处理,即动态代理。
  • 注意,图中使用的是GenericBeanDefinition,与上文的博主用的有区别。
  • 图中在注入Service层时使用的是一个自定义的动态代理,具体怎么用请学习JDK动态代理和CGLIB动态代理相关知识。也可参考:SpringAOP详解(第二次学习Spring,主要是JDK动态代理)
3、二次加载的问题:(重要)
  • 在第一次加载完后,你会发现,如果移除完后,在不重启项目的情况下再次加载相关类就会出现问题。这是因为移除的时候并未完全移除掉相关的mapper方法,所以我们需要重写MapperFactoryBean类中的checkDaoConfig方法,让其在代理注入的时候先把残留的注入移除干净。
    
    @Override
    protected void checkDaoConfig() {
        super.checkDaoConfig();
        Assert.notNull(this.mapperInterface, "Property 'mapperInterface' is required");
        Configuration configuration = this.getSqlSession().getConfiguration();
        String interfaceName = this.mapperInterface.getName();

        // 清除已存的残留  重要修改的地方
        boolean isSupper = configuration.getClass().getSuperclass() == Configuration.class;
        try {
            Field loadedResourcesField = isSupper
                    ? configuration.getClass().getSuperclass().getDeclaredField("loadedResources")
                    : configuration.getClass().getDeclaredField("loadedResources");
            loadedResourcesField.setAccessible(true);
            Set loadedResourcesSet = ((Set) loadedResourcesField.get(configuration));
            loadedResourcesSet.remove("interface " + interfaceName);

            Set mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(configuration);
            mapperRegistryCache.remove("interface " + interfaceName);

            Field knownMappers = MybatisMapperRegistry.class.getDeclaredField("knownMappers");
            knownMappers.setAccessible(true);
            Map, MapperProxyFactory> knownMappersMap = (Map, MapperProxyFactory>)
                    knownMappers.get(configuration.getMapperRegistry());
            for (Class key : knownMappersMap.keySet()) {
                if (key.getName().startsWith(interfaceName.substring(0, interfaceName.lastIndexOf(".")))){
                    knownMappersMap.remove(key);
                    logger.info("移除残留的knownMappersMap:" + key.getName());
                    break;
                }
            }

            Collection mappedStatements = configuration.getMappedStatements();
            List objects = Lists.newArrayList();
            for (Object object : mappedStatements) {
                if (object instanceof MappedStatement) {
                    MappedStatement mappedStatement = (MappedStatement) object;
                    if (mappedStatement.getId().startsWith(interfaceName)) {
                        objects.add(mappedStatement);
                    }
                }
            }
            mappedStatements.removeAll(objects);
            SqlSessionTemplate sqlSessionTemplate = this.getSqlSessionTemplate();
            sqlSessionTemplate.flushStatements();

        } catch (Exception e) {
            logger.error("Refresh IOException :" + e.getMessage());
        }

        if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
            try {
                configuration.addMapper(this.mapperInterface);
            } catch (Exception var6) {
                this.logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", var6);
                throw new IllegalArgumentException(var6);
            } finally {
                ErrorContext.instance().reset();
            }
        }

    }

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5576580.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-14
下一篇2022-12-14

发表评论

登录后才能评论

评论列表(0条)

    保存