Spring注解系列-核心注解

1.概述

我们可以通过org.springframework.beans.factory.annotationorg.springframework.context.annotation 包中的注解利用Spring DI引擎的能力。我们将这些包中的注解称为Spring核心注解,在本教程中将会复习它们。

2.DI有关的注解

2.1 @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的boolean参数,默认值为true。当此注解没有找到合适的bean进行注入时可以通过此参数调整Spring的注入行为。当required为true时,将会抛出异常,否则将不会执行注入。

注意,如果我们使用构造器进行注入,所有构造器参数是强制性的。

从4.3版本开始,如果只有一个构造器,那么我们不需要明确的在构造器上标注@Autowired注解。

2.2 @Bean

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

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

当需要一个返回类型的新实例时,被@Bean标注的方法将被调用。

返回的bean和该方法具有相同的名字。如果我们想给它起不同的名字,我们可以通过该注解中的name或value参数指定(其中value参数是name参数的别名):

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

注意,所有被@Bean标注的方法必须在被@Configuration注解标注的类中。

2.3 @Qualifier

当出现不确定注入哪个bean时,我们可以同时使用@Qualifier和@Autowired注解提供这个bean的id或名称唯一指定。

例如,下面两个bean实现相同的接口:

class Bike implements Vehicle {}

class Car implements Vehicle {}

如果Spring需要注入一个Vehicle bean,它会匹配到多个符合条件的bean,在这种情况下,我们可以通过@Qualifier注解明确的指定bean的名称。

使用构造器注入:

@Autowired
Biker(@Qualifier("bike") Vehicle vehicle) {
    this.vehicle = vehicle;
}

使用setter方法注入:

@Autowired
void setVehicle(@Qualifier("bike") Vehicle vehicle) {
    this.vehicle = vehicle;
}

另一种方式:

@Autowired
@Qualifier("bike")
void setVehicle(Vehicle vehicle) {
    this.vehicle = vehicle;
}

使用字段注入:

@Autowired
@Qualifier("bike")
Vehicle vehicle;

2.4 @Required

将@Required标注在setter方法上表示我们想通过xml注入:

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

如果不填充,则将抛出BeanInitializationException

2.5 @Value

我们可以使用@Value向bean中注入属性值,它适用于构造器、setter和字段注入。

构造器注入:

Engine(@Value("8") int cylinderCount) {
    this.cylinderCount = cylinderCount;
}

setter方法注入:

@Autowired
void setCylinderCount(@Value("8") int cylinderCount) {
    this.cylinderCount = cylinderCount;
}

另一种方式:

@Value("8")
void setCylinderCount(int cylinderCount) {
    this.cylinderCount = cylinderCount;
}

字段注入:

@Value("8")
int cylinderCount;

当然,注入一个静态值是没有用的,因此,我们可以在@Value中使用占位符,该占位符定义在外部资源中,比如定义在.properties 或 .yaml文件中。

假设有下面的文件:

engine.fuelType=petrol

我们可以通过下面的方式注入engine.fuelType的值:

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

2.6 @DependsOn

我们可以使用此注解使Spring在初始化被此注解标注的bean时提前初始化其他bean。通常,这种行为是自动的,基于bean之间明确的依赖。

我们仅仅在这种依赖是模糊的情况下才需要使用这个注解,例如,JDBC驱动加载或静态变量实例化。

我们可以在依赖类上使用@DependsOn指定依赖bean的名字。这个注解的value参数由一个包含依赖bean名字的数组组成:

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

或者,如果我们通过@Bean定义一个bean,这个工厂方法需要被@DependsOn标注:

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

2.7 @Lazy

当我们想延迟初始化bean时可以使用@Lazy注解。默认的,Spring在应用上下文启动后立即创建所有单实例的bean。

然而,有些情况我们需要请求它时才创建而不是应用启动时创建。

该注解的行为取决于我们将其准确放置在何处。我们可以把它放在:

  • 带@Bean注解的bean工厂方法,用于延迟方法调用
  • @Configuration类,所有包含的@Bean方法都将受到影响
  • 一个@Component类,它不是一个@Configuration类,这个bean将被惰性初始化
  • @Autowired构造函数、setter或字段,用于惰性地(通过代理)加载依赖项本身

这个注解有个value参数,默认值为true,它通常被用来覆盖默认行为。

例如,当全局设置为懒加载时让某个bean立即加载:

@Configuration
@Lazy
class VehicleFactoryConfig {

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

2.8 @Lookup

带@Lookup注解的方法告诉Spring在调用该方法时返回该方法返回类型的实例。

2.9 @Primary

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

我们早已看到处理这种情况的方式:通过@Qualifier并指定需要bean的名称。

然而,大多数情况下我们需要一个指定的bean而不是其他的。我们可以使用@Primary简化这种场景:我们将频繁使用的bean标注为@Primary,它将会被优先注入:

@Component
@Primary
class Car implements Vehicle {}

@Component
class Bike implements Vehicle {}

@Component
class Driver {
    @Autowired
    Vehicle vehicle;
}

@Component
class Biker {
    @Autowired
    @Qualifier("bike")
    Vehicle vehicle;
}

在前面的例子中Car被标记为主要的交通工具,因此,在Driver类中Spring将注入Car,当然,在Biker类中将被注入Bike,因为它已经被指定了。

2.10 @Scope

我们使用@Scope定义@Component类或@Bean实例的作用域。它可以被指定为singleton、prototype、request、session、globalSession或其他自定义作用域中的一个。

例如:

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

3. 上下文配置注解

我们可以通过本节描述的注解配置应用上下文信息。

3.1 @Profile

如果我们想使用@Compant或@Bean方法仅当一个指定的profile被激活时,我们可以将其标记为@Profile。

我们可以通过该注解的参数value来配置profile的名字:

@Component
@Profile("sportDay")
class Bike implements Vehicle {}

3.2 @Import

通过此注解我们可以使用没有进行组件扫描的被@Configuration标记的指定类,通过该注解的参数value指定这些类:

@Import(VehiclePartSupplier.class)
class VehicleFactoryConfig {}

3.3 @ImportResource

通过这个注解我们可以导入xml配置。我们可以通过value参数指定xml文件的路径:

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

3.4 @PropertySource

通过此注解可以定义应用配置的属性文件:

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

此注解利用了java8的重复注解功能,因此我们可以同时使用多次:

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

3.5 @PropertySources

使用此注解可以指定多个PropertySource:

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

此功能和java8中的重复注解功能相同。

4.总结

在这篇文章中,我们看到了大部分Spring核心注解的概述。我们看到了如何注入bean和配置环境上下文,如何标记类使其可以被组件扫描发现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值