我有一个基本接口和两个实现
public interface AnimalService
{
public void eat();
}
@Service("animalService")
@Transactional
public class AnimalServiceImpl implements AnimalService
{
@Override
public void eat()
{
System.out.println("i'm eating");
}
}
@Service("birdService")
@Transactional
public class BirdServiceImpl extends AnimalServiceImpl
{
public void fly()
{
System.out.println("i'm flying");
}
}
在我的main方法中尝试以这种方式调用这两个服务实现:
public class test
{
@Autowired
private AnimalService animalService;
@Autowired
@Qualifier("birdService")
private AnimalService birdService;
public static void main(String[] args)
{
animalService.eat();
birdService.eat();
birdService.fly();
}
}
这会产生编译错误,因为birdService无法找到方法fly()。然后我想也许原因是我自动装备AnimalService而不是BirdServiceImpl,所以我改变了我的autowire代码:
@Autowired
@Qualifier("birdService")
private AnimalService birdService;
更改为:
@Autowired
private BirdServiceImpl birdService;
但这会给我一个运行时错误,即“找不到Bean BirdServiceImpl”。 我有google很多文档,有人说使用@Resource。但这对我不起作用。有人说在Spring Context中注册bean,而我的所有bean注册都是通过注释完成的。我不想触及Spring Context。
现在我的解决方案是添加一个新界面
public interface BirdService extends AnimalService
{
public void fly();
}
让我的BirdServiceImpl实现这个接口
public class BirdServiceImpl extends AnimalServiceImpl extends BirdService
{
public void fly()
{
System.out.println("i'm flying");
}
}
我的主要班级改为:
public class test
{
@Autowired
private AnimalService animalService;
@Autowired
private BirdService birdService;
public static void main(String[] args)
{
animalService.eat();
birdService.eat();
birdService.fly();
}
}
现在没问题。但对我来说,这并不完美。如果我使用普通的java,我可以只编写单个接口和多个实现。在main方法中,我可以选择要使用的实现。为什么在春天,我必须为每个新实现构建一个新接口,以便让我的程序运行。
我想知道我的方案有更好的方法吗?
答案 0 :(得分:2)
在你的问题中,你实际上暴露了两个问题:
<强> 1。继承问题
此问题不依赖于Spring Framework,而是由于您对继承的误解。
如果您将服务声明为AnimalService
,那么您显然只能将其用作AnimalService
,无论其实际执行情况如何。
如果要使用具体的实现方法,则需要转换对象。
<强> 2。 “自动发送课程”问题
这通常应该在Spring中工作,所以如果你的代码不起作用取决于你的上下文配置。也许您还在应用中使用AOP或交易, 如果是这样,则启用autoproxy生成器。这可能会导致您的问题。
看看这个问题:Spring Autowiring class vs. interface?。请注意:
使用自动代理时,您需要编程到界面,而不是实现
第3。只是一个注释
如何在Java接口/类名末尾使用()
?
答案 1 :(得分:1)
在我阅读您的问题时,您已经通过为继承的类Interface
创建BirdService
来解决问题。你只是抱怨,因为你必须创建一个新的界面......
当我读到你的问题时,会想到另一个问题:你使用的是哪个AOP?也许您必须将CGLIB添加到类路径(或Maven POM或Gradle)。
阅读一些Spring AOP documentation,我发现了这个:
如果要代理的目标对象的类(以下称 简称为目标类不实现任何 接口,然后将创建一个基于CGLIB的代理。这是 最简单的方案,因为JDK代理是基于接口的,没有 接口意味着甚至不可能进行JDK代理。