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

扫描二维码关注公众号,回复: 5904499 查看本文章

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-inhttps://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画的一个层级图。

猜你喜欢

转载自blog.csdn.net/chaiyu2002/article/details/87865503