Spring自动装配多个服务实现

时间:2015-01-30 06:44:27

标签: java spring spring-mvc

我有一个基本接口和两个实现

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方法中,我可以选择要使用的实现。为什么在春天,我必须为每个新实现构建一个新接口,以便让我的程序运行。

我想知道我的方案有更好的方法吗?

2 个答案:

答案 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代理。