在Tycho Surefire测试环境中获取Spring注解上下文的问题
看起来你在Tycho测试环境下遇到了Spring Bean注入失败的问题——正常运行插件时没问题,但测试启动插件就报UnsatisfiedDependencyException,找不到ParseTextService的Bean。我来帮你梳理下可能的原因和解决办法:
一、先排查最基础的Bean扫描问题
首先确认你的ParseTextService类有没有标注@Service或者@Component注解?Spring只会扫描带有这些注解的类并注册成Bean,要是漏加了肯定找不到。另外检查@ComponentScan(basePackages = {"io.github.magwas"})的包路径,确保ParseTextService在这个包或者它的子包下面,测试环境的包结构有时候会和生产环境有细微差异,别大意。
二、调整Spring上下文的创建方式
你现在把ParserBundleActivator作为Spring的配置类来创建上下文,同时还在Activator里用@Autowired注入Bean,这其实有点冲突——Activator本身是OSGi的组件,不是Spring管理的Bean,Spring会尝试注入但时机可能不对。建议改成单独的Spring配置类:
@Configuration @ComponentScan(basePackages = {"io.github.magwas"}) public class SpringConfig { // 可以在这里添加其他Bean配置 }
然后在Activator里这样初始化上下文:
@Override public void start(BundleContext bundleContext) { // 先设置上下文类加载器 Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); // 初始化Spring上下文 appContext = new AnnotationConfigApplicationContext(); appContext.setClassLoader(this.getClass().getClassLoader()); // 明确指定类加载器 appContext.register(SpringConfig.class); appContext.refresh(); // 手动获取Bean,去掉原来的@Autowired注解 parseText = appContext.getBean(ParseTextService.class); Assert.notNull(parseText, "parseText is null"); // 注册OSGi服务 ServiceRegistration<ParseTextService> registration = bundleContext.registerService(ParseTextService.class, parseText, new Hashtable<String, String>()); System.err.println("registered ParseTextService:"+registration); }
这样把Spring配置和OSGi Activator职责分开,逻辑更清晰,也能避免注入时机的问题。
三、处理OSGi类加载器隔离问题
Tycho测试基于Equinox OSGi,每个Bundle的类加载器是隔离的,你只设置当前线程的上下文类加载器可能不够,Spring内部的线程可能没继承这个加载器。上面的代码里已经给AnnotationConfigApplicationContext明确设置了类加载器,这能确保Spring用Bundle的类加载器去扫描Bean。
另外还要检查测试Bundle的MANIFEST.MF,确保Import-Package里包含了Spring相关的包(比如org.springframework.context.annotation、org.springframework.beans.factory.annotation),以及你的Bean所在的包(io.github.magwas.inez.parse),不然类加载器找不到这些类。
四、调整Tycho Surefire的Bundle启动顺序
Spring相关的Bundle必须在你的插件Bundle之前启动,不然你的插件启动时Spring还没初始化好。修改tycho-surefire的配置,添加Spring Bundle的启动设置:
<plugin> <groupId>org.eclipse.tycho</groupId> <artifactId>tycho-surefire-plugin</artifactId> <configuration> <bundleStartLevel> <!-- 先启动Spring核心Bundle --> <bundle> <id>org.springframework.context</id> <level>1</level> <autoStart>true</autoStart> </bundle> <bundle> <id>org.springframework.core</id> <level>1</level> <autoStart>true</autoStart> </bundle> <!-- 再启动你的插件Bundle --> <bundle> <id>io.github.magwas.inez.parser</id> <level>2</level> <autoStart>true</autoStart> </bundle> </bundleStartLevel> <!-- 如果是无UI的测试,添加这个配置 --> <useUIHarness>false</useUIHarness> </configuration> </plugin>
这样能保证Spring先启动完成,你的插件启动时Spring上下文才能正常工作。
五、去掉Activator里的@Autowired注解
你现在既手动从上下文获取Bean,又用@Autowired注入,这会导致Spring尝试注入但Activator不是Spring管理的Bean,反而容易出问题。直接去掉@Autowired ParseTextService parseText这行,完全通过appContext.getBean()获取就好。
按照上面的步骤调整后,应该能解决测试环境下Spring找不到Bean的问题。
内容来源于stack exchange

