如何使用PropertyChangeSupport和PropertyChangeListener?调试断点异常求助
问题分析与解决方案
核心原因
你的ScrapeService没有成功注册为ScrapeController的属性变更监听器,大概率是以下两种情况:
ScrapeService不是Spring容器管理的Bean,导致它的构造函数从未被执行,自然没完成监听器注册。ScrapeController是多实例作用域(比如请求作用域),而ScrapeService只在初始实例上注册了监听器,请求触发的是新的Controller实例,监听器未生效。
解决方案
方案1:确保ScrapeService被Spring管理
给ScrapeService添加Spring组件注解,让容器自动创建实例并完成依赖注入:
@Component public class ScrapeService implements PropertyChangeListener { private final ScrapeController sc; // Spring会自动注入ScrapeController单例实例 public ScrapeService(ScrapeController sc) { this.sc = sc; sc.addPropertyChangeListener(this); } @Override public void propertyChange(PropertyChangeEvent evt) { System.out.println("Name = " + evt.getPropertyName()); System.out.println("Old Value = " + evt.getOldValue()); System.out.println("New Value = " + evt.getNewValue()); } }
同时确认你的Spring配置(比如@SpringBootApplication或@ComponentScan)覆盖了这两个类所在的包,保证组件能被扫描到。
方案2:适配Controller多实例场景
如果ScrapeController是请求作用域(@RequestScope)等多实例配置,需要在每个Controller实例初始化时注册监听器:
修改ScrapeController,注入ScrapeService并在初始化方法中注册:
@Controller @RequestMapping("/scrape") @RequestScope // 假设是请求作用域 public class ScrapeController { private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); private final ScrapeService scrapeService; // 构造注入ScrapeService public ScrapeController(ScrapeService scrapeService) { this.scrapeService = scrapeService; } @PostConstruct public void initListener() { pcs.addPropertyChangeListener(scrapeService); } @GetMapping({"/", ""}) public String scrape(){ this.pcs.firePropertyChange("value", "wait", "scrape"); return "done"; } // 监听器注册/移除方法不变 }
这样每个新创建的Controller实例都会绑定监听器,请求触发时就能正常回调propertyChange方法。
验证步骤
- 启动Spring应用时,确认
ScrapeService的构造函数被执行(可以加日志打印)。 - 触发请求后,检查
propertyChange方法的断点是否命中,控制台是否输出日志。
内容的提问来源于stack exchange,提问作者Kifsif
相关产品推荐
相关产品推荐

