Spring的@component、@controller、@service和@repository的学习笔记
前言
本文记录一下对Spring的这几个注解的学习。
正文
本文主要参考了https://www.baeldung.com/spring-bean-annotations,不打算全文翻译,更多输出理解的笔记。
1. Overview
In this article, we’ll discuss the most common Spring bean annotations used to define different types of beans.
There’re several ways to configure beans in a Spring container. We can declare them using XML configuration. We can declare beans using the @Bean annotation in a configuration class.
Or we can mark the class with one of the annotations from the org.springframework.stereotype package and leave the rest to component scanning.
有很多方法可以去在Spring的容器中去配置bean,可以在XML配置文件里面配置,也可以在配置类中使用 @Bean 注解。
或者,我们可以使用 org.springframework.stereotype 里面的注解去标记一个类,剩下的事情让 component scanning 处理。
2. Component Scanning
Spring can automatically scan a package for beans if component scanning is enabled.
@ComponentScan configures which packages to scan for classes with annotation configuration. We can specify the base package names directly with one of the basePackages or value arguments (value is an alias for basePackages):
1
2
3
@Configuration
@ComponentScan
(basePackages =
"com.baeldung.annotations"
)
class
VehicleFactoryConfig {}
Also, we can point to classes in the base packages with the basePackageClasses argument:
1
2
3
@Configuration
@ComponentScan
(basePackageClasses = VehicleFactoryConfig.
class
)
class
VehicleFactoryConfig {}
Both arguments are arrays so that we can provide multiple packages for each.
If no argument is specified, the scanning happens from the same package where the @ComponentScan annotated class is present.
如果component scanning打开了,Spring可以自动扫描一个包。像上面的例子那样,可以指定包名,或者类名。如果没有指定,就扫描被@ComponentScan注解的类。
@ComponentScan leverages the Java 8 repeating annotations feature, which means we can mark a class with it multiple times:
1
2
3
4
@Configuration
@ComponentScan
(basePackages =
"com.baeldung.annotations"
)
@ComponentScan
(basePackageClasses = VehicleFactoryConfig.
class
)
class
VehicleFactoryConfig {}
Alternatively, we can use @ComponentScans to specify multiple @ComponentScan configurations:
1
2
3
4
5
6
@Configuration
@ComponentScans
({
@ComponentScan
(basePackages =
"com.baeldung.annotations"
),
@ComponentScan
(basePackageClasses = VehicleFactoryConfig.
class
)
})
class
VehicleFactoryConfig {}
When using XML configuration, the configuring component scanning is just as easy:
1
<
context:component-scan
base-package
=
"com.baeldung"
/>
也可以像上面那样多重注解。
3. @Component
@Component is a class level annotation. During the component scan, Spring Framework automatically detects classes annotated with @Component.
For example:
1
2
3
4
@Component
class
CarUtility {
// ...
}
By default, the bean instances of this class have the same name as the class name with a lowercase initial. On top of that, we can specify a different name using the optional value argument of this annotation.
Since @Repository, @Service, @Configuration, and @Controller are all meta-annotations of @Component, they share the same bean naming behavior. Also, Spring automatically picks them up during the component scanning process.
@Component 这个类的bean实例名字是的小写的类名,当然我们也可以通过 value 这个参数去指定另外一个实例名。
4. @Repository
DAO or Repository classes usually represent the database access layer in an application, and should be annotated with @Repository:
1
2
3
4
@Repository
class
VehicleRepository {
// ...
}
One advantage of using this annotation is that it has automatic persistence exception translation enabled. When using a persistence framework such as Hibernate, native exceptions thrown within classes annotated with @Repository will be automatically translated into subclasses of Spring’s DataAccessExeption.
To enable exception translation, we need to declare our own PersistenceExceptionTranslationPostProcessor bean:
1
2
3
4
@Bean
public
PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return
new
PersistenceExceptionTranslationPostProcessor();
}
Note, that in most cases, Spring does the step above automatically.
Or, via XML configuration:
1
2
<
bean
class
=
"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"
/>
@Repository用来注解DAO,或者数据库层。
5. @Service
The business logic of an application usually resides within the service layer – so we’ll use the @Service annotation to indicate that a class belongs to that layer:
1
2
3
4
@Service
public
class
VehicleService {
// ...
}
@Service 注解用于注解业务逻辑层。
6. @Controller
@Controller is a class level annotation which tells the Spring Framework that this class serves as a controller in Spring MVC:
1
2
3
4
@Controller
public
class
VehicleController {
// ...
}
@Controller。
7. @Configuration
classes can contain bean definition methods annotated with @Bean:
1
2
3
4
5
6
7
8
9
@Configuration
class
VehicleFactoryConfig {
@Bean
Engine engine() {
return
new
Engine();
}
}
@Configuration 下面会包含 @Bean。
8. Stereotype Annotations and AOP
When we use Spring stereotype annotations, it’s easy to create a pointcut that targets all classes that have a particular stereotype.
For example, suppose we want to measure the execution time of methods from the DAO layer. We’ll create the following aspect (using AspectJ annotations) taking advantage of @Repository stereotype:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Aspect
@Component
public
class
PerformanceAspect {
@Pointcut
(
"within(@org.springframework.stereotype.Repository *)"
)
public
void
repositoryClassMethods() {};
@Around
(
"repositoryClassMethods()"
)
public
Object measureMethodExecutionTime(ProceedingJoinPoint joinPoint)
throws
Throwable {
long
start = System.nanoTime();
Object returnValue = joinPoint.proceed();
long
end = System.nanoTime();
String methodName = joinPoint.getSignature().getName();
System.out.println(
"Execution of "
+ methodName +
" took "
+
TimeUnit.NANOSECONDS.toMillis(end - start) +
" ms"
);
return
returnValue;
}
}
In this example, we created a pointcut that matches all methods in classes annotated with @Repository. We used the @Around advice to then target that pointcut and determine the execution time of the intercepted methods calls.
Using this approach, we may add logging, performance management, audit, or other behaviors to each application layer.
这里面这几个注解现在似乎已经不常用了,这里没有太细看。
9. Conclusion
In this article, we have examined the Spring stereotype annotations and learned what type of semantics these each represent.
We also learned how to use component scanning to tell the container where to find annotated classes.
Finally – we saw how these annotations lead to a clean, layered design and separation between the concerns of an application. They also make configuration smaller, as we no longer need to explicitly define beans manually.
As usual, the examples are available over on GitHub.
总结
读了上面,产生几个问题:
1、如果不写这几个注解会怎么样?
不写的话,Spring应该会找不到@bean,不会自动加载。
2、如果这几个注解换着写有关系吗?
参考:https://stackoverflow.com/questions/46272424/when-to-use-service-or-component-in-spring、https://stackoverflow.com/questions/6827752/whats-the-difference-between-component-repository-service-annotations-in和https://stackoverflow.com/questions/12862203/autowired-and-service-working-from-controller-but-not-from-a-different-package。
@Controller
=@Component
belonging to Presentation Layer@Service
=@Component
belonging to Service/Use Case Layer@Repository
=@Component
belonging to Persistence Layer
初步得出一个结论,这几个注解其实和@component是一样的,只是概念上不同,为了标识不同的业务层。
其他参考
https://www.tutorialspoint.com/spring_boot/spring_boot_service_components.htm
https://martinfowler.com/eaaCatalog/serviceLayer.html 这个是martinfowler画的一个层级图。
posted on 2019-12-15 17:06 chaiyu2002 阅读(138) 评论(0) 编辑 收藏 举报