我们必须与合作伙伴共享我们的代码库,但我们不希望透露某些服务的实现。
假设我们有一个界面FooService
及其实现FooServiceImpl
。
public interface FooService
{
void doSomething();
}
@Service
public class FooServiceImpl implements FooService
{
@Override
public String doSomething();
{
...
}
}
许多其他类自动装配此服务并调用doSomething()。例如:
@Service
public class BarServiceImpl implements BarService
{
@Autowired
private FooService fooService;
@Override
public String validate();
{
fooService.doSomething();
...
}
}
如果我只删除FooServiceImpl
,当然会在启动时抛出NoSuchBeanException
。如果我在FooService自动装配的每个地方都使用@Autowired(required = false)
,那么只要调用NullPointerException
,就会在运行时抛出doSomething()
。
除了手动删除FooServiceImpl中的每个方法体之外,还有其他方法可以解决这个问题吗?
感谢任何帮助。
答案 0 :(得分:2)
我同意chrylis;您的用例听起来像是应该发布默认实现。我还将配置您的代码以允许您的库的用户提供他们自己的实现。 Spring允许您使用@Conditional...
注释轻松完成此操作。具体来说,我认为你应该使用@ConditionalOnMissingBean
。
默认实施
@Component
public class DefaultFooServiceImpl implements FooService {
@Override
public void doSomething() {
LOG.info("Using default implementation of doSomething(); nothing will happen");
}
}
示例配置
@Configuration
public class ServiceConfig {
@ConditionalOnMissingBean(FooService.class)
@Bean
DefaultFooServiceImpl defaultFooServiceImpl() {
return new DefaultFooServiceImpl();
}
}
当您的合作伙伴使用您的库时,他们会获得默认实现,以及提供更好实现的选项。当您使用库时,您可以创建一个ProprietaryFooServiceImpl
bean,它将被注入。
答案 1 :(得分:1)
首先,正如@AdrianShum和@chrylis所评论的那样,FooService
的{{1}}实现工作正常。因此,“不想透露某些服务的实现”并不清楚你的意思。
BarServiceImpl.validate()
中自动装配FooService
时,将进行扫描以查找BarServiceImpl
类型的bean。由于您没有FooService
的任何实现,因此会发生此错误。FooService
,在初始化期间忽略上述问题。但required=false
显然会有private FooService fooService
值。因此,当您致电NULL
时会发生异常。fooService.doSomething()
(或类似的东西)
在@Component
上。从Spring文档中,“此注释适用于
要通过classpath自动检测的实现类
扫描“。然后会有 NoSuchBeanException ,因为你没有
实施班。因此,如果没有在Spring中实现任何实现,则无法自动装配接口。
答案 2 :(得分:0)
我们可以在Spring中自动装配一个没有任何实现的接口吗?
否强>
您正在尝试为接口 创建实例,这在Java中是不可能的。