Spring 自动装配多个服务实现
Spring autowire multiple service Implementations
我有一个基本接口和两个实现
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");
}
}
在我的主要方法中尝试以这种方式调用这两个服务实现:
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,所以我将我的自动装配代码更改为:
@Autowired
@Qualifier("birdService")
private AnimalService birdService;
更改为:
@Autowired
private BirdServiceImpl birdService;
但这会给我一个运行时间错误,也就是"can't find bean BirdServiceImpl"。
我有google 很多文档,有些说使用@Resource。但这对我不起作用。有人说在 Spring 上下文中注册 bean,而我所有的 bean 注册都是通过注释完成的。我不想触及 Spring 上下文。
现在我的解决方案是添加一个新接口
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");
}
}
我的主要 class 更改为:
public class test
{
@Autowired
private AnimalService animalService;
@Autowired
private BirdService birdService;
public static void main(String[] args)
{
animalService.eat();
birdService.eat();
birdService.fly();
}
}
现在可以了。但对我来说,这并不完美。如果我使用普通的 java,我可以只编写单个接口和多个实现。在主要方法中,我可以选择要使用的实现。为什么在 spring 中,我必须为每个新实现构建一个新接口,以便让我的程序 运行.
我想知道我的场景是否有更好的方法?
正如我在您的问题中所读到的,您已经通过为继承的 class BirdService
创建 Interface
来解决问题。你抱怨只是因为你必须创建一个新的界面...
当我读到你的问题时,我又想到了另一个问题:你使用的是哪个 AOP?也许您必须将 CGLIB 添加到您的 class 路径(或 Maven POM 或 Gradle)。
阅读一些 Spring AOP documentation,我发现:
If the class of a target object that is to be proxied (hereafter
simply referred to as the target class) doesn’t implement any
interfaces, then a CGLIB-based proxy will be created. This is the
easiest scenario, because JDK proxies are interface based, and no
interfaces means JDK proxying isn’t even possible.
你的问题实际上暴露了两个问题:
1.继承问题
此问题与Spring框架无关,而是您对继承的误解所致。
如果您将服务声明为 AnimalService
,显然您只能将其用作 AnimalService
,而不管其实际实现如何。
如果你想使用具体的实现方法,你需要转换你的对象。
2。 'Autowiring a class' 问题
这通常应该在 Spring 中工作,所以如果您的代码不起作用取决于您的上下文配置。也许你也在你的应用程序中使用 AOP 或事务,
如果是,则启用自动代理生成器。这可能会导致您的问题。
看看这个问题:Spring Autowiring class vs. interface?。并注意:
When using autoproxies, you need to program to the interface, not the implementation
3。请注意
如何在 Java interface/class 名称的末尾使用 ()
?
我有一个基本接口和两个实现
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");
}
}
在我的主要方法中尝试以这种方式调用这两个服务实现:
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,所以我将我的自动装配代码更改为:
@Autowired
@Qualifier("birdService")
private AnimalService birdService;
更改为:
@Autowired
private BirdServiceImpl birdService;
但这会给我一个运行时间错误,也就是"can't find bean BirdServiceImpl"。 我有google 很多文档,有些说使用@Resource。但这对我不起作用。有人说在 Spring 上下文中注册 bean,而我所有的 bean 注册都是通过注释完成的。我不想触及 Spring 上下文。
现在我的解决方案是添加一个新接口
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");
}
}
我的主要 class 更改为:
public class test
{
@Autowired
private AnimalService animalService;
@Autowired
private BirdService birdService;
public static void main(String[] args)
{
animalService.eat();
birdService.eat();
birdService.fly();
}
}
现在可以了。但对我来说,这并不完美。如果我使用普通的 java,我可以只编写单个接口和多个实现。在主要方法中,我可以选择要使用的实现。为什么在 spring 中,我必须为每个新实现构建一个新接口,以便让我的程序 运行.
我想知道我的场景是否有更好的方法?
正如我在您的问题中所读到的,您已经通过为继承的 class BirdService
创建 Interface
来解决问题。你抱怨只是因为你必须创建一个新的界面...
当我读到你的问题时,我又想到了另一个问题:你使用的是哪个 AOP?也许您必须将 CGLIB 添加到您的 class 路径(或 Maven POM 或 Gradle)。
阅读一些 Spring AOP documentation,我发现:
If the class of a target object that is to be proxied (hereafter simply referred to as the target class) doesn’t implement any interfaces, then a CGLIB-based proxy will be created. This is the easiest scenario, because JDK proxies are interface based, and no interfaces means JDK proxying isn’t even possible.
你的问题实际上暴露了两个问题:
1.继承问题
此问题与Spring框架无关,而是您对继承的误解所致。
如果您将服务声明为 AnimalService
,显然您只能将其用作 AnimalService
,而不管其实际实现如何。
如果你想使用具体的实现方法,你需要转换你的对象。
2。 'Autowiring a class' 问题
这通常应该在 Spring 中工作,所以如果您的代码不起作用取决于您的上下文配置。也许你也在你的应用程序中使用 AOP 或事务, 如果是,则启用自动代理生成器。这可能会导致您的问题。
看看这个问题:Spring Autowiring class vs. interface?。并注意:
When using autoproxies, you need to program to the interface, not the implementation
3。请注意
如何在 Java interface/class 名称的末尾使用 ()
?