这里罗列一些Spring的注解,不断巩固

Spring Core Annotations

概述

我们可以使用 org.springframework.beans.factory.annotationorg.springframework.context.annotation 包中的注释来利用Spring DI引擎的功能。

称之为spring核心注解(Spring core annotations)

依赖注入相关注释

@Autowired

我们可以使用@Autowired标记Spring将要解析和注入的依赖项。我们可以将这个注释与构造函数,setter或字段注入一起使用。

构造方法注入:
class Car {
    Engine engine;
 
    @Autowired
    Car(Engine engine) {
        this.engine = engine;
    }
}
setter方法注入
class Car {
    Engine engine;
 
    @Autowired
    void setEngine(Engine engine) {
        this.engine = engine;
    }
}
属性注入
class Car {
    @Autowired
    Engine engine;
}

@Autowired有默认为required的布尔参数,默认值为true。当它没有找到合适的bean,如果为true,则抛出异常。

如果使用构造函数注入,则所有构造函数参数都是必需的。

从版本4.3开始,除非我们声明至少两个构造函数,否则我们不需要显式地使用@Autowired注释构造函数。

@Autowired and constructor injection相关详细内容

@Bean

@Bean标记了一个实例化Spring bean的工厂方法

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

当需要返回类型的新实例时,Spring会调用这些方法。

生成的bean与工厂方法具有相同的名称。如果我们想以不同的方式命名,我们可以使用此注解的名称或值参数(参数值是参数名称的别名)

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

注意,所有使用@Bean注释的方法都必须在@Configuration类中。

@Qualifier

使用@Autowired 不确定bean id 或 bean name时,可以使用Qualifier来显式指定。

、、两个bean实现相同的接口
class Bike implements Vehicle {}
class Car implements Vehicle {}

如果Spring需要注入一个Vehicle bean,它最终会有多个匹配的定义。在这种情况下,我们可以使用@Qualifier注释显式提供bean的名称。

构造方法注入
@Autowired
Biker(@Qualifier("bike") Vehicle vehicle) {
    this.vehicle = vehicle;
}
setter方法注入
@Autowired
void setVehicle(@Qualifier("bike") Vehicle vehicle) {
    this.vehicle = vehicle;
}
setter方法注入2
@Autowired
@Qualifier("bike")
void setVehicle(Vehicle vehicle) {
    this.vehicle = vehicle;
}
属性注入
@Autowired
@Qualifier("bike")
Vehicle vehicle;

更多详细内容

@Required

@Required 注释应用于 bean 属性的 setter 方法,它表明受影响的 bean 属性在配置时必须放在 XML 配置文件中,否则容器就会抛出一个 BeanInitializationException 异常。

@Required
void setColor(String color) {
    this.color = color;
}
<bean class="com.baeldung.annotations.Bike">
    <property name="color" value="green" />
</bean>

@Value

我们可以使用@Value将属性值注入bean。它与构造方法注入,setter方法注入和属性注入兼容。

构造方法注入
Engine(@Value("8") int cylinderCount) {
    this.cylinderCount = cylinderCount;
}
setter方法注入
@Autowired
void setCylinderCount(@Value("8") int cylinderCount) {
    this.cylinderCount = cylinderCount;
}
setter方法注入2
@Value("8")
void setCylinderCount(int cylinderCount) {
    this.cylinderCount = cylinderCount;
}
属性注入
@Value("8")
int cylinderCount;

我们可以在@Value中使用占位符字符串来连接外部源中定义的值,例如,在.properties或.yaml文件中

engine.fuelType=petrol
@Value("${engine.fuelType}")
String fuelType;

即使使用SpEL,我们也可以使用@Value。有关@Value的文章中可以找到更高级的示例

@DependsOn

我们可以使用这个注释使Spring在注释之前初始化其他bean。通常,此行为是自动的,基于bean之间的显式依赖关系。

只在当依赖关系是隐式时标注该注解,例如JDBC驱动程序加载或静态变量初始化

我们可以在依赖类上使用@DependsOn来指定依赖关系bean的名称。注释的value参数需要一个包含依赖项bean名称的数组:

@DependsOn("engine")
class Car implements Vehicle {}

或者,如果我们使用@Bean批注定义bean,则应使用@DependsOn注释工厂方法

@Bean
@DependsOn("fuel")
Engine engine() {
    return new Engine();
}

@Lazy

  • 标记在bean工厂方法:延迟方法的调用
  • 标记在配置类上:所有的bean都会被延迟创建
  • 标记在组件类上(不包括配置类):bean会被延迟初始化
  • 标记在构造方法,setter方法,属性上:依赖项延迟加载

如需进一步阅读,请访问此文章

@Primary

有时我们需要定义多个相同类型的bean。在这些情况下,注入将不会成功,因为Spring不知道我们需要哪种bean

@Component
@Primary
class Car implements Vehicle {}
 
@Component
class Bike implements Vehicle {}
 
@Component  //spring 注入Car Bean
class Driver {
    @Autowired
    Vehicle vehicle;
}
 
@Component  //spring 注入bike Bean
class Biker {
    @Autowired
    @Qualifier("bike")
    Vehicle vehicle;
}

@Scope

我们使用@Scope来定义@Component类的范围或@Bean定义。它可以是singleton,prototype,request,session,globalSession或某些自定义范围。

@Component
@Scope("prototype")
class Engine {}

Context Configuration Annotations

@Profile

详见这里

@Import

我们可以使用特定的@Configuration类,而不使用组件扫描(component scanning )。我们可以为这些类提供@ Import的value参数:

@Import(VehiclePartSupplier.class)
class VehicleFactoryConfig {}

@ImportResource

我们可以使用此批注导入XML配置。我们可以使用locations参数或其别名value参数指定XML文件位置:

@Configuration
@ImportResource("classpath:/annotations.xml")
class VehicleFactoryConfig {}

@PropertySource

指定properties文件 @PropertySource利用Java 8重复注释功能,这意味着我们可以多次使用它标记一个类:

@Configuration
@PropertySource("classpath:/annotations.properties")
@PropertySource("classpath:/vehicle-factory.properties")
class VehicleFactoryConfig {}

@PropertySources

指定多个@PropertySource配置:

@Configuration
@PropertySources({ 
    @PropertySource("classpath:/annotations.properties"),
    @PropertySource("classpath:/vehicle-factory.properties")
})
class VehicleFactoryConfig {}

Spring Boot Annotations

概述

Spring Boot通过自动配置功能使Spring更容易配置。
在这个文章中,讨论 org.springframework.boot.autoconfigureorg.springframework.boot.autoconfigure.condition 包。

@SpringBootApplication

这个注解来标记Spring Boot应用程序的主类
@SpringBootApplication 默认包括 @Configuration@ EnableAutoConfiguration@ComponentScan 注释。

@SpringBootApplication
class VehicleFactoryApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(VehicleFactoryApplication.class, args);
    }
}

@EnableAutoConfiguration

顾名思义,支持自动配置。这意味着Spring Boot在其类路径中查找自动配置bean并自动应用它们。

@Configuration
@EnableAutoConfiguration
class VehicleFactoryConfig {}

自动配置条件 Auto-Configuration Conditions

@ConditionalOnClass and @ConditionalOnMissingClass

@ConditionalOnClass 表示对应的类在classpath目录下存在时,才创建标记上该注解的类的实例 @ConditionalOnMisssingClass 表示classPath不存在指定的Class时,创建标记上该注解的类的实例

@Configuration
@ConditionalOnClass(DataSource.class)
class MySQLAutoconfiguration {
    //...
}

@ConditionalOnBean and @ConditionalOnMissingBean

ConditionalOnBean: 表示指定的bean classes and/or bean names在当前容器中,才创建标记上该注解的类的实例 ConditionalOnMissingBean: 表示指定的bean classes and/or bean names不存在当前容器中,才创建标记上该注解的类的实例,有指定忽略ignored的参数存在,可以忽略Class、Type等

@Bean
@ConditionalOnBean(name = "dataSource")
LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    // ...
}

@ConditionalOnResource

仅在存在特定资源时才创建标记上该注解的类的实例

@ConditionalOnResource(resources = "classpath:mysql.properties")
Properties additionalProperties() {
    // ...
}

@ConditionalOnWebApplication and @ConditionalOnNotWebApplication

我们可以根据当前应用程序是否是Web应用程序创建


@ConditionalOnWebApplication
HealthCheckController healthCheckController() {
    // ...
}

@ConditionalExpression

当SpEL表达式求值为true时才创建

@Bean
@ConditionalOnExpression("${usemysql} && ${mysqlserver == 'local'}")
DataSource dataSource() {
    // ...
}

@Conditional

对于更复杂的条件,我们可以创建一个评估自定义条件的类。我们告诉Spring使用@Conditional使用这个自定义条件

@Conditional(HibernateCondition.class)
Properties additionalProperties() {
    //...
}

Spring Bean Annotations

概述

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

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

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

@ComponentScan 组件扫描( Component Scanning )

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

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

basePackages

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

basePackageClasses

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

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

basePackages 多参数

参数为字符串数组指定多个包

@ComponentScan({"com.my.package.first","com.my.package.second"})

basePackages 空参数

不指定参数默认为当前包

指定多次

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

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

使用XML配置

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

@Component

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

@Component
class CarUtility {
    // ...
}

默认情况下,此类的bean实例名称为小写首字母的类名。也可以使用 value 参数指定其他名称。

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

@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"/>

@Service

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

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

@Controller

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

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

@Configuration

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

@Configuration
class VehicleFactoryConfig {
 
    @Bean
    Engine engine() {
        return new Engine();
    }
 
}

Stereotype Annotations and 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环绕通知 然后定位该切入点并确定截获的方法调用的执行时间。

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