如何在非服务类中引用服务?自定义实例化时避免依赖为空
问题解答
Component是否必须在插件启动时创建?
不是。默认情况下@Component的immediate属性为false,这类组件不会在插件启动时自动实例化,只有当它提供的服务被其他组件引用,或者通过OSGi容器主动获取该服务实例时,才会被初始化并完成依赖注入。你之前设置immediate = true才会触发插件启动时的立刻实例化。
如何实现Foo不自动实例化,且自行创建时Bar不为空?
核心问题在于:通过new Foo()创建的实例不受OSGi容器管理,容器不会自动为其注入@Reference标注的依赖。以下是几种可行的解决思路:
方案1:通过OSGi容器获取Foo实例(推荐)
取消Foo类的immediate = true配置,让它仅在被需要时实例化:
@Component // 移除immediate=true,使用默认的false public class Foo { @Reference private Bar bar; // 业务方法 }
之后不要自行new Foo(),而是通过OSGi组件上下文或ServiceTracker获取实例:
// 在其他受容器管理的组件中 @Component public class SomeOtherClass { @Reference private Foo foo; // 此时Foo会被容器实例化,Bar自动注入 // 或者通过ComponentContext手动获取 @Activate protected void activate(ComponentContext context) { Foo foo = context.locateService("Foo的服务标识"); // 使用foo,此时bar已完成注入 } }
这种方式完全依托OSGi容器的依赖注入能力,无需手动管理依赖关系。
方案2:手动注入Bar服务
如果一定要自行new Foo(),可以在Foo类中暴露依赖设置的入口,手动从容器获取Bar服务后注入:
public class Foo { // 可移除@Component,或保留但设immediate=false private Bar bar; // 提供setter方法 public void setBar(Bar bar) { this.bar = bar; } // 或通过构造函数接收Bar public Foo(Bar bar) { this.bar = bar; } }
在需要创建Foo的地方,先获取Bar服务再初始化Foo:
// 在受容器管理的组件中 @Component public class SomeClass { @Reference private Bar bar; public void createFoo() { Foo foo = new Foo(bar); // 或 new Foo(); foo.setBar(bar); // 此时foo的bar不为空 } }
方案3:使用OSGi工厂组件
通过factory属性将Foo声明为工厂组件,借助ComponentFactory创建实例,容器会自动处理依赖注入:
@Component(factory = "foo.factory") public class Foo { @Reference private Bar bar; // 业务方法 }
在需要创建Foo的地方,获取ComponentFactory并生成实例:
@Component public class SomeClass { @Reference(target = "(component.factory=foo.factory)") private ComponentFactory fooFactory; public void createFoo() { Foo foo = (Foo) fooFactory.newInstance(null); // 此时foo的bar已被容器注入 } }
内容的提问来源于stack exchange,提问作者Bourbon_7
相关产品推荐
相关产品推荐

