美文网首页
Spring 核心注解介绍

Spring 核心注解介绍

作者: RaiseHead | 来源:发表于2019-07-18 14:23 被阅读0次

    Spring是一款轻量级的IOC框架,Spring的核心就是Ioc和DI,并通过俩者解耦。Ioc(Inversion of control)控制反转,可以把创建对象和查找依赖对象的权限交给Ioc容器控制,而不是传统的由这些对象的使用方(消费者)进行创建初始化操作。IoC是一种让服务消费者不直接依赖于服务提供者的组件设计方式,是一种减少类与类之间依赖的设计原则。DI(Dependency Injection)依赖注入,指容器复制创建和维护对象之间的依赖关系,而不是通过对象本身复制自己的创建和解决自己的依赖。控制反转是通过依赖注入实现的。

    1 概述

    在Spring中可通过一些注解(Annotation)来使用Spring DI引擎功能,它们定义在org.springframework.beans.factory.annotation 和 org.springframework.context.annotation包中。我们通常将这些称为“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;
        }
    }
    

    Field注入

    class Car {
        @Autowired
        Engine engine;
    }
    

    @Autowired有一个名为required的布尔参数,默认值为true。当它没有找到合适的bean来连接时,Spring 容器将抛出 BeanCreationException 异常。如果为false,表示忽略当前要注入的bean,如果有直接注入,没有跳过,不会报错。

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

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

    2.2 @Bean

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

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

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

    默认情况下bean的名称和方法名称相同,你也可以使用name属性来指定:

    @Bean(name="myEngine")
    Engine engine() {
        return new Engine();
    }
    

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

    2.3 @Qualifier

    使用@Qualifier和@Autowired来提供我们想要在不明确的情况下使用的bean id或bean名称。

    例如,以下两个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;
    }
    
    @Autowired
    @Qualifier("bike")
    void setVehicle(Vehicle vehicle) {
        this.vehicle = vehicle;
    }
    

    使用Field注入:

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

    2.4 @Required

    @Required注解适用于bean属性setter方法,并表示受影响的bean属性必须在XML配置文件在配置时进行填充。否则,容器会抛出一个BeanInitializationException异常。

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

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

    Field注入:

    @Value("8")
    int cylinderCount;
    

    当然,注入静态值是没有用的。因此,可以使用@Value中的占位符字符串来连接外部资源中定义的值,例如,在.properties或.yaml文件中定义的值。

    我们假设.properties文件中定义了:

    engine.fuelType=petrol
    

    我们可以使用以下内容注入engine.fuelType的值:

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

    即使使用SpEL,我们也可以使用@Value。

    2.6 @DependsOn

    指定Spring容器初始化当前Bean之前先初始化所依赖的Bean。

    当依赖项是隐式时,我们只需要这个注释,例如,JDBC驱动程序加载或静态变量初始化。我们可以在依赖类上使用@DependsOn来指定依赖关系bean的名称。

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

    2.7 @Lazy

    一般情况下,Spring容器在启动时会创建所有的Bean对象,使用@Lazy注解可以将Bean对象的创建延迟到第一次使用Bean的时候。

    这个注解会根据放置的位置产生不同的效果:

    • 与@Bean放在一起,用于延迟方法调用
    • 与@Configuration放在一起,影响类中所有@Bean的方法
    • 与@Component放在一起,这个bean将会懒初始化
    • 与@Autowired放在一起,将懒加载依赖项

    此注解具有名为value的参数,其默认值为true。当为false时,代表不延迟立刻加载。

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

    2.8 @Lookup

    @Lookup注解是一个作用在方法上的注解,被其标注的方法会被重写,然后根据其返回值的类型,容器调用BeanFactory的getBean()方法来返回一个bean。

    2.9 @Primary

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

    我们已经看到了一个处理这种情况的方法:用@Qualifier标记所有连接点并指定所需bean的名称。

    但是,大多数时候我们需要一个特定的bean而很少需要其他bean。我们可以使用@Primary来简化这种情况:如果我们用@Primary标记最常用的bean,它将在不确定的情况下作为首选:

    @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 bean。当然,在Biker bean中,指定了值将是一个Bike对象。

    2.10 @Scope

    spring中scope是一个非常关键的概念,简单说就是对象在spring容器(IOC容器)中的生命周期,也可以理解为对象在spring容器中的创建方式。

    目前,scope的取值有5种取值:

    • 在Spring 2.0之前,有singleton和prototype两种;
    • 在Spring 2.0之后,为支持web应用的ApplicationContext,增强另外三种:request,session和global session类型,它们只实用于web程序,通常是和XmlWebApplicationContext共同使用。
    @Component
    @Scope("prototype")
    class Engine {}
    

    3 上下文配置注释

    3.1 @Profile

    们可以在不同的环境中激活不同的配置文件来引导我们需要的bean。使用@Profile注释 - 我们将bean映射到该特定的配置文件。

    假设,一个应用的工作环境有:dev、test、prod。我们有一个bean,它应该只在开发期间处于活动状态,但不会在生产中部署。我们使用“ dev ”配置文件注解该bean ,并且它只会在开发期间出现在容器中 - 在生产中,dev将不会处于活动状态:

    @Component
    @Profile("dev")
    public class DevDatasourceConfig
    

    3.2 @Import

    导入资源。在应用中,有时没有把某个类注入到IOC容器中,但在运用的时候需要获取该类对应的bean,此时就需要用到@Import注解。

    @Import(VehiclePartSupplier.class)
    class VehicleFactoryConfig {}
    

    3.3 @ImportResource

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

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

    3.4 @PropertySource

    使用此注解,我们可以为应用程序设置定义的属性文件,将properties配置文件中的值存储到Spring的Environment中:

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

    @PropertySource引用了Java 8重复注解功能,这意味着我们可以多次使用它标记一个类:

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

    注意,自Java 8以来,我们可以通过如上所述的重复注解功能实现相同的功能。

    4 结论

    在本文中,我们看到了最常见的Spring核心注解的介绍。我们了解了如何配置bean和应用程序上下文,以及如何为组件扫描标记类。

    相关文章

      网友评论

          本文标题:Spring 核心注解介绍

          本文链接:https://www.haomeiwen.com/subject/bvlllctx.html