4.RPC框架的简单实现(服务发布-ServiceBean实现)

本文详细解析了LDubbo框架中的服务发布过程。通过Spring的InitializingBean接口,ServiceBean实现了服务的初始化与发布。ServiceBean继承ServiceConfig并实现afterPropertiesSet()方法来完成服务发布的核心逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面介绍了ServiceBean不是一个简单的Java pojo对象,只拥有get,set方法,它需要在初始化之后执行服务发布的操作。spirng的InitializingBean接口为bean提供了定义初始化方法的方式,它只包括一个afterPropertiesSet()方法,凡是实现了该接口的类,在初始化bean的时候会执行该方法,ServiceBean对象就是通过实现InitializingBean接口实现服务发布的。

ServiceBean代码如下:

package com.lipenglong.ldubbo.config.spring;

import com.lipenglong.ldubbo.config.ServiceConfig;
import org.springframework.beans.factory.InitializingBean;

/**
 * ldubbo service对象类,是暴露服务的入口
 * <p/>
 * Created by lipenglong on 2017/7/21.
 */
public class ServiceBean extends ServiceConfig implements InitializingBean {

    private static final long serialVersionUID = 3083255015367616542L;

    @Override
    public String toString() {
        return super.toString();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        export();
    }
}

export(),就是服务发布的方法,在父类ServiceConfig中添加该方法的实现,ServiceConfig代码:

package com.lipenglong.ldubbo.config;

import com.lipenglong.ldubbo.rpc.Protocol;
import com.lipenglong.ldubbo.rpc.ProtocolFactory;

/**
 * service配置类
 * <p/>
 * Created by lipenglong on 2017/7/24.
 */
public class ServiceConfig<T> extends AbstractConfig {
    private static final long serialVersionUID = 831848002887083456L;
    private String interfaceName;
    private T ref;
    private ProtocolConfig protocolConfig;
    private Class<?> interfaceClass;
    private Protocol protocol;

    public String getInterface() {
        return interfaceName;
    }

    public void setInterface(String interfaceName) {
        this.interfaceName = interfaceName;
    }

    public T getRef() {
        return ref;
    }

    public void setRef(T ref) {
        this.ref = ref;
    }

    public ProtocolConfig getProtocolConfig() {
        return protocolConfig;
    }

    public void setProtocolConfig(ProtocolConfig protocolConfig) {
        this.protocolConfig = protocolConfig;
    }

    public synchronized void export() {
        try {
            interfaceClass = Class.forName(interfaceName, true, Thread.currentThread().getContextClassLoader());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        protocol = ProtocolFactory.getProtocol(protocolConfig.getName());
        protocol.export(interfaceClass, ref);
    }

    @Override
    public String toString() {
        return "ServiceConfig{" +
                "interfaceName='" + interfaceName + '\'' +
                ", ref=" + ref +
                ", protocolConfig=" + protocolConfig +
                ", interfaceClass=" + interfaceClass +
                ", protocol=" + protocol +
                '}';
    }
}

通过ServiceConfig类的setInterface方法,把xml文件中配置的interface属性值赋值给interfaceName,通过setRef方法,把引用的对象赋值给ref属性,这里定义一个泛型T,因为不知道暴露服务的接口具体的实现类的类型。protocolConfig的get,set方法把xml中配置的ProtocolConfig对象引用过来,因为发布服务时需要知道用哪个协议。在上一篇LdubboBeanDefinitionParser类的实现中,有一个判断set方法名称是“protocolConfig”的处理,就是做这个用的。

然后是export()方法的实现,也是比较简单:通过interfaceName得到interfaceClass;根据protocolConfig.getName()获取xml中配置的具体协议(rmi或ldubbo),然后通过ProtocolFactory.getProtocol()方法根据配置的name得到具体的protocol实现类;调用protocol的export方法,实现某个协议具体的服务发布。

Protocol是协议的接口类,定义了两个方法,export方法和refer方法,定义了服务的发布和引用接口,Protocol接口类:

package com.lipenglong.ldubbo.rpc;

import com.lipenglong.ldubbo.config.RegistryConfig;

/**
 * rpc协议接口类
 * <p/>
 * Created by lipenglong on 2017/7/25.
 */
public interface Protocol {
    /**
     * 暴露远程服务
     *
     * @param interfaceClass 服务接口class
     * @param ref            服务接口的实现
     */
    void export(Class<?> interfaceClass, Object ref);

    /**
     * 引用远程服务
     *
     * @param interfaceClass 服务接口class
     * @param registryConfig registry配置
     * @return 服务接口的代理类
     */
    <T> T refer(Class<?> interfaceClass, RegistryConfig registryConfig);
}

在介绍具体的协议实现之前,下一篇要先写一下ProtocolFactory.getProtocol()的具体实现,如何根据name得到具体的协议对象类,这里也是参考dubbo框架中应用很广泛的SPI思想。

2025-06-09T22:03:14.229+08:00 INFO 1 --- [ruoyi-archives] [ main] d.s.b.c.e.WelcomeLogoApplicationListener : [DUBBO] :: Dubbo (v3.2.14) : https://github.com/apache/dubbo :: Discuss group : dev@dubbo.apache.org , dubbo version: 3.2.14, current host: 172.17.0.11 Spring Boot Version: 3.2.9 Spring Application Name: ruoyi-archives _ _ | | (_) __ _ _ __ ___| |__ ___ _____ ___ / _` | '__/ __| '_ \| \ \ / / _ \/ __| | (_| | | | (__| | | | |\ V / __/\__ \ \__,_|_| \___|_| |_|_| \_/ \___||___/ 2025-06-09T22:03:14.400+08:00 INFO 1 --- [ruoyi-archives] [ main] o.d.archives.RuoYiArchivesApplication : Starting RuoYiArchivesApplication using Java 17.0.15 with PID 1 (/ruoyi-archives.jar started by root in /) 2025-06-09T22:03:14.401+08:00 INFO 1 --- [ruoyi-archives] [ main] o.d.archives.RuoYiArchivesApplication : The following 1 profile is active: "prod" 2025-06-09T22:03:14.484+08:00 WARN 1 --- [ruoyi-archives] [ main] c.a.c.n.c.NacosConfigDataLoader : [Nacos Config] config[dataId=ruoyi-archives.yml, group=DEFAULT_GROUP] is empty 2025-06-09T22:03:14.484+08:00 WARN 1 --- [ruoyi-archives] [ main] c.a.c.n.c.NacosConfigDataLoader : [Nacos Config] config[dataId=datasource.yml, group=DEFAULT_GROUP] is empty 2025-06-09T22:03:14.484+08:00 WARN 1 --- [ruoyi-archives] [ main] c.a.c.n.c.NacosConfigDataLoader : [Nacos Config] config[dataId=application-common.yml, group=DEFAULT_GROUP] is empty 2025-06-09T22:03:16.045+08:00 INFO 1 --- [ruoyi-archives] [ main] o.apache.dubbo.rpc.model.FrameworkModel : [DUBBO] Dubbo Framework[1] is created, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.061+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.r.GlobalResourcesRepository : [DUBBO] Creating global shared handler ..., dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.160+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.dubbo.rpc.model.ApplicationModel : [DUBBO] Dubbo Application[1.0](unknown) is created, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.162+08:00 INFO 1 --- [ruoyi-archives] [ main] org.apache.dubbo.rpc.model.ScopeModel : [DUBBO] Dubbo Module[1.0.0] is created, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.202+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.context.AbstractConfigManager : [DUBBO] Config settings: {dubbo.config.mode=STRICT, dubbo.config.ignore-duplicated-interface=false}, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.203+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.context.AbstractConfigManager : [DUBBO] Config settings: {dubbo.config.mode=STRICT, dubbo.config.ignore-duplicated-interface=false}, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.221+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.utils.SerializeSecurityManager : [DUBBO] Serialize check serializable: true, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.222+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.u.SerializeSecurityConfigurator : [DUBBO] Read serialize allow list from jar:nested:/ruoyi-archives.jar/!BOOT-INF/lib/dubbo-3.2.14.jar!/security/serialize.allowlist, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.249+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.u.SerializeSecurityConfigurator : [DUBBO] Read serialize allow list from jar:nested:/ruoyi-archives.jar/!BOOT-INF/lib/dubbo-common-3.2.14.jar!/security/serialize.allowlist, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.250+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.u.SerializeSecurityConfigurator : [DUBBO] Read serialize blocked list from jar:nested:/ruoyi-archives.jar/!BOOT-INF/lib/dubbo-3.2.14.jar!/security/serialize.blockedlist, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.294+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.u.SerializeSecurityConfigurator : [DUBBO] Read serialize blocked list from jar:nested:/ruoyi-archives.jar/!BOOT-INF/lib/dubbo-common-3.2.14.jar!/security/serialize.blockedlist, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.417+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.dubbo.rpc.model.ApplicationModel : [DUBBO] Dubbo Application[1.1](unknown) is created, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.418+08:00 INFO 1 --- [ruoyi-archives] [ main] org.apache.dubbo.rpc.model.ScopeModel : [DUBBO] Dubbo Module[1.1.0] is created, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.432+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.context.AbstractConfigManager : [DUBBO] Config settings: {dubbo.config.mode=STRICT, dubbo.config.ignore-duplicated-interface=false}, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.432+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.context.AbstractConfigManager : [DUBBO] Config settings: {dubbo.config.mode=STRICT, dubbo.config.ignore-duplicated-interface=false}, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.440+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.u.SerializeSecurityConfigurator : [DUBBO] Read serialize allow list from jar:nested:/ruoyi-archives.jar/!BOOT-INF/lib/dubbo-3.2.14.jar!/security/serialize.allowlist, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.440+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.u.SerializeSecurityConfigurator : [DUBBO] Read serialize allow list from jar:nested:/ruoyi-archives.jar/!BOOT-INF/lib/dubbo-common-3.2.14.jar!/security/serialize.allowlist, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.440+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.u.SerializeSecurityConfigurator : [DUBBO] Read serialize blocked list from jar:nested:/ruoyi-archives.jar/!BOOT-INF/lib/dubbo-3.2.14.jar!/security/serialize.blockedlist, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.441+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.u.SerializeSecurityConfigurator : [DUBBO] Read serialize blocked list from jar:nested:/ruoyi-archives.jar/!BOOT-INF/lib/dubbo-common-3.2.14.jar!/security/serialize.blockedlist, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.463+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.s.c.DubboSpringInitializer : [DUBBO] Use default application: Dubbo Application[1.1](unknown), dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.463+08:00 INFO 1 --- [ruoyi-archives] [ main] org.apache.dubbo.rpc.model.ScopeModel : [DUBBO] Dubbo Module[1.1.1] is created, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.471+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.context.AbstractConfigManager : [DUBBO] Config settings: {dubbo.config.mode=STRICT, dubbo.config.ignore-duplicated-interface=false}, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.476+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.u.SerializeSecurityConfigurator : [DUBBO] Read serialize allow list from jar:nested:/ruoyi-archives.jar/!BOOT-INF/lib/dubbo-3.2.14.jar!/security/serialize.allowlist, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.476+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.u.SerializeSecurityConfigurator : [DUBBO] Read serialize allow list from jar:nested:/ruoyi-archives.jar/!BOOT-INF/lib/dubbo-common-3.2.14.jar!/security/serialize.allowlist, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.477+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.u.SerializeSecurityConfigurator : [DUBBO] Read serialize blocked list from jar:nested:/ruoyi-archives.jar/!BOOT-INF/lib/dubbo-3.2.14.jar!/security/serialize.blockedlist, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.477+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.u.SerializeSecurityConfigurator : [DUBBO] Read serialize blocked list from jar:nested:/ruoyi-archives.jar/!BOOT-INF/lib/dubbo-common-3.2.14.jar!/security/serialize.blockedlist, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.480+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.s.c.DubboSpringInitializer : [DUBBO] Use default module model of target application: Dubbo Module[1.1.1], dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:16.480+08:00 INFO 1 --- [ruoyi-archives] [ main] o.a.d.c.s.c.DubboSpringInitializer : [DUBBO] Bind Dubbo Module[1.1.1] to spring container: org.springframework.beans.factory.support.DefaultListableBeanFactory@5b88b8e, dubbo version: 3.2.14, current host: 172.17.0.11 ___ _ _ ___ | __| __ _ ___ | || | ___ | __| ___ | _| / _` | (_-< \_, | |___| | _| (_-< |___| \__,_| /__/_ _|__/ _____ |___| /__/_ _|"""""|_|"""""|_|"""""|_| """"|_| |_|"""""|_|"""""| "`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-' -----------------------------------------------------------> :: project :: Easy-Es > :: version :: 2.0.0 > :: home :: https://easy-es.cn/ > :: community :: https://dromara.org/ > :: wechat :: 252645816, add and become muscle man! > -----------------------------------------------------------> 2025-06-09T22:03:17.306+08:00 INFO 1 --- [ruoyi-archives] [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode 2025-06-09T22:03:17.310+08:00 INFO 1 --- [ruoyi-archives] [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode. 2025-06-09T22:03:17.355+08:00 INFO 1 --- [ruoyi-archives] [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 27 ms. Found 0 Redis repository interfaces. 2025-06-09T22:03:17.511+08:00 INFO 1 --- [ruoyi-archives] [ main] c.s.b.f.a.ServiceAnnotationPostProcessor : [DUBBO] BeanNameGenerator bean can't be found in BeanFactory with name [org.springframework.context.annotation.internalConfigurationBeanNameGenerator], dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:17.511+08:00 INFO 1 --- [ruoyi-archives] [ main] c.s.b.f.a.ServiceAnnotationPostProcessor : [DUBBO] BeanNameGenerator will be a instance of org.springframework.context.annotation.AnnotationBeanNameGenerator , it maybe a potential problem on bean name generation., dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:17.521+08:00 INFO 1 --- [ruoyi-archives] [ main] c.s.b.f.a.ServiceAnnotationPostProcessor : [DUBBO] Found 1 classes annotated by Dubbo @Service under package [org.dromara.archives]: [org.dromara.archives.dubbo.ArchivesDubbonServiceImpl], dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:17.539+08:00 INFO 1 --- [ruoyi-archives] [ main] c.s.b.f.a.ServiceAnnotationPostProcessor : [DUBBO] Register ServiceBean[ServiceBean:org.dromara.archives.service.ArchivesServiceDubbon::]: Root bean: class [org.apache.dubbo.config.spring.ServiceBean]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null, dubbo version: 3.2.14, current host: 172.17.0.11 2025-06-09T22:03:17.556+08:00 WARN 1 --- [ruoyi-archives] [ main] o.m.s.mapper.ClassPathMapperScanner : No MyBatis mapper was found in '[org.dromara.archives]' package. Please check your configuration. 2025-06-09T22:03:17.558+08:00 WARN 1 --- [ruoyi-archives] [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'org.dromara.common.mybatis.config.MybatisPlusConfiguration#MapperScannerRegistrar#0' defined in null: Could not resolve placeholder 'mybatis-plus.mapperPackage' in value "${mybatis-plus.mapperPackage}" 2025-06-09T22:03:17.591+08:00 INFO 1 --- [ruoyi-archives] [ main] .s.b.a.l.ConditionEvaluationReportLogger : Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. 2025-06-09T22:03:17.643+08:00 ERROR 1 --- [ruoyi-archives] [ main] o.s.boot.SpringApplication : Application run failed org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'org.dromara.common.mybatis.config.MybatisPlusConfiguration#MapperScannerRegistrar#0' defined in null: Could not resolve placeholder 'mybatis-plus.mapperPackage' in value "${mybatis-plus.mapperPackage}" at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:230) ~[spring-beans-6.1.12.jar!/:6.1.12] at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.processProperties(PropertySourcesPlaceholderConfigurer.java:207) ~[spring-context-6.1.12.jar!/:6.1.12] at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(PropertySourcesPlaceholderConfigurer.java:173) ~[spring-context-6.1.12.jar!/:6.1.12] at org.mybatis.spring.mapper.MapperScannerConfigurer.processPropertyPlaceHolders(MapperScannerConfigurer.java:406) ~[mybatis-spring-3.0.3.jar!/:3.0.3] at org.mybatis.spring.mapper.MapperScannerConfigurer.postProcessBeanDefinitionRegistry(MapperScannerConfigurer.java:360) ~[mybatis-spring-3.0.3.jar!/:3.0.3] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) ~[spring-context-6.1.12.jar!/:6.1.12] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:148) ~[spring-context-6.1.12.jar!/:6.1.12] at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:789) ~[spring-context-6.1.12.jar!/:6.1.12] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:607) ~[spring-context-6.1.12.jar!/:6.1.12] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.2.9.jar!/:3.2.9] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.9.jar!/:3.2.9] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.9.jar!/:3.2.9] at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.2.9.jar!/:3.2.9] at org.dromara.archives.RuoYiArchivesApplication.main(RuoYiArchivesApplication.java:28) ~[!/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:569) ~[na:na] at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:102) ~[ruoyi-archives.jar:na] at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:64) ~[ruoyi-archives.jar:na] at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:40) ~[ruoyi-archives.jar:na] Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'mybatis-plus.mapperPackage' in value "${mybatis-plus.mapperPackage}" at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:180) ~[spring-core-6.1.12.jar!/:6.1.12] at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126) ~[spring-core-6.1.12.jar!/:6.1.12] at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239) ~[spring-core-6.1.12.jar!/:6.1.12] at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210) ~[spring-core-6.1.12.jar!/:6.1.12] at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:200) ~[spring-context-6.1.12.jar!/:6.1.12] at org.springframework.beans.factory.config.BeanDefinitionVisitor.resolveStringValue(BeanDefinitionVisitor.java:293) ~[spring-beans-6.1.12.jar!/:6.1.12] at org.springframework.beans.factory.config.BeanDefinitionVisitor.resolveValue(BeanDefinitionVisitor.java:219) ~[spring-beans-6.1.12.jar!/:6.1.12] at org.springframework.beans.factory.config.BeanDefinitionVisitor.visitPropertyValues(BeanDefinitionVisitor.java:147) ~[spring-beans-6.1.12.jar!/:6.1.12] at org.springframework.beans.factory.config.BeanDefinitionVisitor.visitBeanDefinition(BeanDefinitionVisitor.java:85) ~[spring-beans-6.1.12.jar!/:6.1.12] at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:227) ~[spring-beans-6.1.12.jar!/:6.1.12] ... 20 common frames omitted 2025-06-09T22:03:17.647+08:00 WARN 1 --- [ruoyi-archives] [ Thread-6] c.a.nacos.common.notify.NotifyCenter : [NotifyCenter] Start destroying Publisher 2025-06-09T22:03:17.647+08:00 WARN 1 --- [ruoyi-archives] [ Thread-4] c.a.n.common.http.HttpClientBeanHolder : [HttpClientBeanHolder] Start destroying common HttpClient 分析问题给出解决办法
最新发布
06-10
<think>我们正在解决SpringBoot应用中MyBatis-Plus的`mapperPackage`占位符无法解析的问题。这个问题通常发生在配置文件中使用了占位符(如`${mybatis-plus.mapperPackage}`)但该属性未被正确赋值的情况下。以下是解决此问题的系统化步骤:###1.检查属性配置首先确认在`application.properties`或`application.yml`中已正确定义了`mybatis-plus.mapperPackage`属性。**正确示例(.properties)**:```propertiesmybatis-plus.mapperPackage=com.example.mapper```**正确示例(.yml)**:```yamlmybatis-plus:mapperPackage:com.example.mapper```###2.验证占位符语法确保MyBatis-Plus配置中的占位符语法正确:**Java配置类示例**:```java@Configuration@MapperScan("${mybatis-plus.mapperPackage}")//占位符引用publicclassMybatisConfig{}```###3.排查环境差异若开发/生产环境配置不同,需确认:-激活的Profile(`spring.profiles.active`)-Profile专属配置文件(如`application-dev.yml`)中是否定义了该属性###4.检查属性加载顺序若使用`@PropertySource`加载自定义配置文件,确保其优先级高于MyBatis配置类的加载时机。建议将关键属性放在主配置文件中。###5.处理默认值(可选)为防止属性未定义导致启动失败,可设置默认值:```java@MapperScan("${mybatis-plus.mapperPackage:com.example.fallback.mapper}")```###6.日志诊断启用调试日志查看属性加载详情:```propertieslogging.level.root=DEBUG```在启动日志中搜索:```logProperty'mybatis-plus.mapperPackage'foundin[...]```###7.版本兼容性不同MyBatis-Plus版本对占位符支持存在差异,请参考对应版本的文档:|MyBatis-Plus版本|占位符支持||------------------|-----------||≥3.4.0|完全支持||<3.4.0|需检查注解[^1]|###8.源码级解决方案若以上步骤无效,可放弃占位符改用直接路径:```java@MapperScan("com.example.actual.mapper")```>**最佳实践**:在多个模块的项目中,建议使用**全限定类名常量**而非字符串:>```java>packagecom.example.constants;>publicclassProjectConstants{>publicstaticfinalStringMAPPER_PACKAGE="com.example.mapper";>}>```>配置类引用:>```java>@MapperScan(ProjectConstants.MAPPER_PACKAGE)>```§§相关问题§§1.SpringBoot多环境配置如何管理MyBatis-Plus属性?2.MyBatis-Plus如何实现动态数据源切换?3.如何为MyBatis-Plus的Mapper接口添加自定义注解?</think> ### 解决 MyBatis-Plus `mapperPackage` 占位符无法解析的问题 该错误通常发生在 Spring Boot 配置未正确注入属性值时。以下是系统化的排查和解决方案: --- #### **1. 检查配置文件语法** 确保在 `application.yml` 或 `application.properties` 中正确定义了占位符属性: ```yaml # application.yml 正确示例 mybatis-plus: mapper-locations: classpath*:/mapper/**/*.xml mapperPackage: com.example.mapper # 属性名需匹配占位符 ``` ```properties # application.properties 正确示例 mybatis-plus.mapperPackage=com.example.mapper ``` **常见错误**: - 占位符名称不一致:`${mybatis-plus.mapperPackage}` ≠ `mybatisplus.mapper-package` - YAML 缩进错误导致属性未被识别[^1] --- #### **2. 验证属性加载** 在配置类中添加诊断日志,确认属性是否被正确加载: ```java @Configuration public class AppConfig { @Value("${mybatis-plus.mapperPackage}") private String mapperPackage; @PostConstruct public void init() { System.out.println("DEBUG: mapperPackage = " + mapperPackage); } } ``` - 若输出 `null` 或抛错 → 属性未注入成功 - 若输出正确值 → 检查 MyBatis-Plus 配置 --- #### **3. MyBatis-Plus 配置修正** 在配置类中使用 **`@MapperScan` 代替占位符**(推荐方案): ```java @Configuration @MapperScan("com.example.mapper") // 直接指定包路径 public class MybatisConfig { // 移除xml中的占位符引用 } ``` **替代方案**(需要显式注入): ```java @Bean public MybatisPlusInterceptor mybatisPlusInterceptor( @Value("${mybatis-plus.mapperPackage}") String packageName) { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 使用packageName变量 return interceptor; } ``` --- #### **4. 多环境配置排查** 若使用 `application-dev.yml` 等 profile 文件: 1. 检查激活的 profile:`spring.profiles.active=dev` 2. 确保该 profile 文件中定义了 `mybatis-plus.mapperPackage` 3. 避免属性被更高优先级的配置覆盖(如系统环境变量) --- #### **5. 依赖冲突检查** 确认 `pom.xml` 依赖兼容性: ```xml <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> <!-- 使用稳定版本 --> </dependency> ``` **排查冲突**:执行 `mvn dependency:tree | grep 'mybatis'` 检查版本冲突。 --- #### **6. 自定义 PropertySource 处理** 若使用动态配置源(如数据库配置),确保实现 `PropertySourcePlaceholderConfigurer`: ```java @Bean public static PropertySourcesPlaceholderConfigurer configurer() { return new PropertySourcesPlaceholderConfigurer(); } ``` --- > **关键总结**: > 1. 优先采用 `@MapperScan` 硬编码路径 > 2. 通过 `@PostConstruct` 日志验证属性注入 > 3. 检查 YAML/properties 文件命名一致性 > 4. 排除依赖冲突和 Profile 配置覆盖
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值