Spring Bean Annotations


1.概述

在本文中,我们将讨论用于定义不同类型bean的最常见的Spring bean注释。

有几种方法可以在Spring容器中配置bean。我们可以使用XML配置声明它们。我们可以在配置类中使用@Bean批注声明bean 。

或者我们可以使用org.springframework.stereotype包中的一个注释标记该类,并将其余部分留给组件扫描。

2.组件扫描

如果启用了组件扫描,Spring可以自动扫描bean的包。

@ComponentScan配置要扫描具有注释配置的类的包。我们可以直接使用basePackages或value参数之一指定基本包名(value是basePackages的别名):

@Configuration
@ComponentScan(basePackages = "com.baeldung.annotations")
class VehicleFactoryConfig {}

此外,我们可以使用basePackageClasses参数指向基础包中的类:

@Configuration
@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
class VehicleFactoryConfig {}

两个参数都是数组,因此我们可以为每个参数提供多个包。

如果未指定参数,则扫描从存在@ComponentScan注释类的同一包中进行。

@ComponentScan利用Java 8重复注释功能,这意味着我们可以多次用它标记一个类:

@Configuration
@ComponentScan(basePackages = "com.baeldung.annotations")
@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
class VehicleFactoryConfig {}

或者,我们可以使用@ComponentScans指定多个@ComponentScan配置:

@Configuration
@ComponentScans({
  @ComponentScan(basePackages = "com.baeldung.annotations"),
  @ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
})
class VehicleFactoryConfig {}

当使用XML配置,所述配置组件扫描也很容易:

<context:component-scan base-package="com.baeldung" />

3. @Component

@Component是一个类级别的注释。在组件扫描期间,Spring Framework会自动检测使用@Component注释的类。

例如:

@Component
class CarUtility {
    // ...
}

默认情况下,此类的bean实例与具有小写首字母的类名具有相同的名称。最重要的是,我们可以使用此批注的可选值参数指定其他名称。

由于@Repository,@Service,@Configuration,和@Controller是所有元注释@Component,它们共享同一个bean的命名行为。此外,Spring会在组件扫描过程中自动拾取它们。

4. @Repository

DAO或Repository类通常表示应用程序中的数据库访问层,应使用@Repository注释:

@Repository
class VehicleRepository {
    // ...
}

使用此批注的一个优点是它启用了自动持久性异常转换。当使用诸如Hibernate之类的持久性框架时,在使用@Repository注释的类中抛出的本机异常将自动转换为Spring的DataAccessExeption的子类。

要启用异常转换,我们需要声明自己的PersistenceExceptionTranslationPostProcessor bean:

@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
    return new PersistenceExceptionTranslationPostProcessor();
}

请注意,在大多数情况下,Spring会自动执行上述步骤。

或者,通过XML配置:

<bean class=
  "org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

5. @Service

应用程序的业务逻辑通常驻留在服务层中 - 因此我们将使用@Service批注指示类属于该层:

@Service
public class VehicleService {
    // ...    
}

6. @Controller

@Controller是一个类级别的注释,它告诉Spring Framework这个类在Spring MVC中充当控制器:

@Controller
public class VehicleController {
    // ...
}

7. @Configuration

配置类可以包含使用@Bean注释的bean定义方法:

@Configuration
class VehicleFactoryConfig {

    @Bean
    Engine engine() {
        return new Engine();
    }

8.刻板印象注释和AOP

当我们使用Spring构造型注释时,很容易创建一个切入点,该切入点针对具有特定构造型的所有类。

例如,假设我们想要从DAO层测量方法的执行时间。我们将利用@Repository构造型创建以下方面(使用AspectJ注释):

@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;
    }
}

在这个例子中,我们创建了一个切入点,它匹配用@Repository注释的类中的所有方法。我们使用@Around建议然后定位该切入点并确定截获的方法调用的执行时间。

使用此方法,我们可以向每个应用程序层添加日志记录,性能管理,审计或其他行为。