Answers:
我从不将@Component
(或@Service
...)放在接口上,因为这会使接口无用。让我解释一下原因。
声明1:如果您有一个接口,那么您想将该接口用于注入点类型。
权利要求2:接口的目的是它定义可以由多种实现方式实现的契约。在另一侧,您有注射点(@Autowired
)。(IMHO)仅具有一个接口且只有一个实现该接口的类是无用的,并且违反了YAGNI。
事实:当你放:
@Component
(或@Service
,...)在界面上,然后您将获得和NoUniqueBeanDefinitionException
(或者您具有非常特殊的配置设置,包括环境,配置文件或限定符...)
结论:如果在接口上使用@Component
(或@Service
,...),则必须违反两个规则中的至少一个。因此,我认为放在@Component
接口级别上是没有用的(除了一些罕见的情况)。
Spring-Data-JPA存储库接口完全不同
@Transactional
是使用bean代理的示例之一。AOP是另一个。
基本上注解像@服务,@Repository,@Component等,它们都达到同样的目的:
使用基于注释的配置和类路径扫描时自动检测。
从我的经验我一直使用@Service
的接口或抽象类和注释像注释@Component
,并@Repository
组织落实。@Component
我在那些用于基本目的的类上使用的注解,简单的Spring bean,仅此而已。@Repository
我在该DAO
层中使用的注释,例如,如果我必须与数据库进行通信,进行一些事务等。
因此,我建议@Service
根据功能在和其他层上注释您的界面。
将注释放在@Service上的优点是,它暗示了它是服务。我不知道默认情况下是否有任何实现类会继承此注释。
缺点是,您将使用特定于Spring的注释将接口与特定框架(例如Spring)耦合。由于应该将接口与实现分离,因此我不建议使用任何特定于框架的注释或接口的对象部分。
spring的一个好处是可以轻松地切换Service(或其他)实现。为此,您需要在接口上进行注释并声明变量,如下所示:
@Autowired
private MyInterface myVariable;
并不是 :
@Autowired
private MyClassImplementationWhichImplementsMyInterface myVariable;
与第一种情况一样,您可以从唯一的那一刻起就激活要注入的实现(只有一个类实现该接口)。在第二种情况下,您需要重构所有代码(新类实现具有另一个名称)。因此,注释需要尽可能多地位于界面上。此外,JDK代理非常适合于此:它们是在应用程序启动时创建和实例化的,因为与CGlib代理相反,运行时类型是预先已知的。
@Service
实现并自动连接接口。Spring将检查实现此接口的任何对象。
我会把@Service
你的类,但将接口的名称作为参数例如注释
interface ServiceOne {}
@Service("ServiceOne")
class ServiceOneImpl implements ServiceOne{}
这样,您将获得所有好处,并且仍然可以注入接口但可以获取类
@Autowired
private ServiceOne serviceOne;
因此,您的界面不依赖于Spring框架,您可以随时更改类,而不必更新所有注入点。
因此,如果我想更改实现类,则可以注释新的类并从第一个类中删除,但这就是所有需要更改的地方。如果您要注入类,那么在您想更改impl类时,可能需要做很多工作。
有5个注释可用于制作春豆。在答案下面列出。
您真的需要一个界面吗?如果每个服务接口都有一个实现,请避免使用,仅使用类。当然,如果您没有RMI或需要接口代理时。
@Repository-用于注入您的dao图层类。
@Service-用于注入服务层类。在服务层中,您可能还需要使用@Transactional批注进行数据库事务管理。
@Controller-用于您的前端层控制器,例如作为弹簧bean注入的JSF托管bean。
@RestController-用于spring rest控制器,这将帮助您避免每次都将@ResponseBody和@RequestBody批注放入rest方法中。
@Component-在需要注入不是控制器,服务或dao类的spring bean的任何其他情况下使用它