You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PropertySourcesPlaceholderConfigurer导致Spring启动失败问题排查

解决Spring配置类构造函数注入导致的CGLIB增强无默认构造函数异常

我来帮你理清楚这个问题的根因和解决办法:

首先,你的MyConfiguration是被@Configuration标记的配置类,而且里面包含了@Bean方法。Spring在处理这类配置类时,默认会通过CGLIB动态代理生成一个子类来增强它(就是报错日志里的MyConfiguration$$EnhancerBySpringCGLIB$$d0d9c3b2)——这个增强是为了拦截@Bean方法的调用,确保每次返回的都是同一个Bean实例(单例特性)。

但CGLIB生成子类有个硬性要求:父类必须提供无参的默认构造函数,否则子类无法完成实例化。而你的MyConfiguration只定义了一个带ApplicationContext参数的构造函数,没有显式声明无参构造函数,所以就抛出了NoSuchMethodException。

至于你说其他Bean没问题,是因为普通的@Component类(非@Configuration)的代理逻辑和配置类不一样:普通Bean即使被CGLIB增强,Spring也可以直接通过构造函数注入来实例化父类,不需要依赖无参构造函数;但配置类的代理子类必须先调用父类的无参构造函数,这就是核心差异所在。

下面给你几种可行的解决方法:

方法一:添加无参构造函数

最直接的方式就是给MyConfiguration添加一个无参构造函数,这样CGLIB就能正常生成子类了:

@Configuration
@ComponentScan(
    useDefaultFilters = false,
    basePackages = "...",
    includeFilters = @Filter(
        type = FilterType.REGEX,
        pattern = "..."
    )
)
class MyConfiguration {
    private final ApplicationContext context;

    // 添加无参构造函数
    MyConfiguration() {
        // 这里可以留空,Spring会通过带参构造函数完成实际注入
        this.context = null;
    }

    MyConfiguration(final ApplicationContext context) {
        this.context = context;
    }

    @Bean
    PropertySourcesPlaceholderConfigurer configurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

方法二:改用ApplicationContextAware接口注入

如果你不想添加无参构造函数,可以让配置类实现ApplicationContextAware接口,Spring会自动把ApplicationContext注入进来,不需要构造函数:

@Configuration
@ComponentScan(...)
class MyConfiguration implements ApplicationContextAware {
    private ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }

    @Bean
    PropertySourcesPlaceholderConfigurer configurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

方法三:关闭配置类的代理(仅适用于Spring Boot 2.2+ / Spring 5.2+)

如果你使用的是Spring Boot 2.2及以上版本(对应Spring 5.2+),可以给@Configuration添加proxyBeanMethods = false属性,将配置类设置为Lite模式——这种模式下Spring不会生成CGLIB代理,自然也就不需要无参构造函数了:

@Configuration(proxyBeanMethods = false)
@ComponentScan(...)
class MyConfiguration {
    private final ApplicationContext context;

    MyConfiguration(final ApplicationContext context) {
        this.context = context;
    }

    @Bean
    PropertySourcesPlaceholderConfigurer configurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

不过注意,Lite模式下,配置类里的@Bean方法如果互相调用,不会被拦截,会直接创建新的实例,所以如果你的配置类里有Bean之间的依赖调用,需要谨慎使用这个选项。

内容的提问来源于stack exchange,提问作者LppEdd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:26:08