Contents

Spring Bean 注解

1.概述

在本教程中,我们将讨论用于定义不同类型bean的最常见的 Spring bean 注解。 有几种方法可以在 Spring 容器中配置 bean。首先,我们可以使用 XML 配置声明它们。我们还可以在配置类中使用*@Bean*注解来声明 bean。

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

2. 组件扫描

如果启用了组件扫描,Spring 可以自动扫描包中的 bean。 @ComponentScan配置要扫描哪些包以查找具有注释配置的类。我们可以使用basePackagesvalue参数之一直接指定基本包名称( valuebasePackages的别名):

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

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

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

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

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

@ComponentScan利用了 Java 8 的重复注解特性,这意味着我们可以用它多次标记一个类:

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

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

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

使用XML 配置时,配置组件扫描同样简单:

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

3. @Component

@Component是一个类级别的注解。在组件扫描期间,Spring Framework 会自动检测带有@Component*注解的类:*

@Component
class CarUtility {
    // ...
}

默认情况下,此类的 bean 实例与具有小写首字母的类名称具有相同的名称。此外,我们可以使用此注解的可选value参数指定不同的名称。 由于*@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

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*通知来定位那个切入点,并确定被拦截方法调用的执行时间。

此外,使用这种方法,我们可以将日志记录、性能管理、审计和其他行为添加到每个应用程序层。