Spring注解相關(guān)

Spring注解

EnableConfigurationProperties

如果@ConfigurationProperties是在第三方包中,那么@component是不能注入到容器的。只有@EnableConfigurationProperties才可以注入到容器。

ConditionalOnClass

image.png

componentscan的作用如下:

@ComponentScan告訴Spring 哪個packages 的用注解標(biāo)識的類 會被spring自動掃描并且裝入bean容器。

例如,如果你有個類用@Controller注解標(biāo)識了,那么,如果不加上@ComponentScan,自動掃描該controller,那么該Controller就不會被spring掃描到,更不會裝入spring容器中,因此你配置的這個Controller也沒有意義。

配置文件類比注解

@Configuation等價(jià)于<Beans></Beans>
@Bean 等價(jià)于<Bean></Bean>
@ComponentScan等價(jià)于<context:component-scan base-package="com.dxz.demo"/>
@Component 等價(jià)于<Bean></Bean>

@Bean VS @Component

兩個注解的結(jié)果是相同的,bean都會被添加到Spring上下文中。

  • @Component 標(biāo)注的是類,允許通過自動掃描發(fā)現(xiàn)。@Bean需要在配置類@Configuation中使用。

  • @Component類使用的方法或字段時(shí)不會使用CGLIB增強(qiáng)。而在@Configuration類中使用方法或字段時(shí)則使用CGLIB創(chuàng)造協(xié)作對象
    假設(shè)我們需要將一些第三方的庫組件裝配到應(yīng)用中或者 我們有一個在多個應(yīng)用程序中共享的模塊,它包含一些服務(wù)。并非所有應(yīng)用都需要它們。

  • 如果在這些服務(wù)類上使用@Component并在應(yīng)用程序中使用組件掃描,我們最終可能會檢測到超過必要的bean。導(dǎo)致應(yīng)用程序無法啟動
    但是我們可以使用 @Bean來加載

因此,基本上,使用@Bean將第三方類添加到上下文中。和@Component,如果它只在你的單個應(yīng)用程序中

獲取yml配置文件

/**
對接配置內(nèi)容
 */
@Data
@ConfigurationProperties(prefix = "insurance")
@Component
public class InsuranceDockingConfig {
    /**
     * 是否打印日志
     * 0:否 1:是
     */
    public String consoleType;
    /**
     * 項(xiàng)目負(fù)責(zé)人
     */
    public String projectLeader;
    /**
     * 訂單負(fù)責(zé)人
     */
    public String orderLeader;
}

ConditionalOnProperty 注解

1. 簡介

Spring Boot源碼中大量使用@ConditionalOnProperty來控制Configuration是否生效。

2. 實(shí)戰(zhàn)

2.1 name的用法

user類

public class User {
}

Dept類

public class Dept {
}

配置類


/**
 * @Author: wgs
 * @Date 2022/2/23 16:02
 * @Classname Config1
 * @Description 當(dāng)配置文件中只要出現(xiàn)config1.enable時(shí)(內(nèi)容為空 , 同樣也是有效的),則該配置生效。
 */
@Configuration
@ConditionalOnProperty(name = "config1.enable")
public class Config1 {
    @Bean
    public User user() {
        User user = new User();
        System.err.println("----------------初始化user--------------");
        return user;
    }
}

/**
 * @Author: wgs
 * @Date 2022/2/23 16:05
 * @Classname Config2
 * @Description 當(dāng)配置文件中只要出現(xiàn)config1.enable時(shí)(內(nèi)容為空,同樣也是有效的),則該配置生效。
 */
@Configuration
@ConditionalOnProperty(name = "config2.enable")
public class Config2 {
    @Bean
    public Dept dept() {
        System.err.println("=============dept初始化========");
        return new Dept();
    }
}

配置文件

config1:
  enable: test

啟動項(xiàng)目

2022-02-23 16:24:33.004  INFO 20313 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 459 ms
----------------初始化user--------------
2022-02-23 16:24:33.162  INFO 20313 --- [   

2.2 根據(jù)配置開關(guān)進(jìn)行動態(tài)加載配置(havingValue)

在上述代碼的基礎(chǔ)上,我們首先的Config1和Config2中稍作一些修改。

配置類


/**
 * @Author: wgs
 * @Date 2022/2/23 16:02
 * @Classname Config1
 * @Description 當(dāng)配置文件中只要出現(xiàn)config1.enable時(shí)(內(nèi)容為空 , 同樣也是有效的),則該配置生效。
 */
@Configuration
//  當(dāng)配置文件中config1.enable的值為true才加載,否則就不加載
@ConditionalOnProperty(name = "config1.enable", havingValue = "true")
public class Config1 {
    @Bean
    public User user() {
        User user = new User();
        System.err.println("----------------初始化user--------------");
        return user;
    }
}

/**
 * @Author: wgs
 * @Date 2022/2/23 16:05
 * @Classname Config2
 * @Description 當(dāng)配置文件中只要出現(xiàn)config1.enable時(shí)(內(nèi)容為空,同樣也是有效的),則該配置生效。
 */
@Configuration
//  當(dāng)配置文件中config1.enable的值為true才加載,否則就不加載
@ConditionalOnProperty(name = "config2.enable", havingValue = "true")
public class Config2 {
    @Bean
    public Dept dept() {
        System.err.println("=============dept初始化========");
        return new Dept();
    }
}

配置文件

config1:
  enable: false
config2:
  enable: true

啟動項(xiàng)目

2022-02-23 16:28:38.633  INFO 20439 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-02-23 16:28:38.633  INFO 20439 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 449 ms
=============dept初始化========
2022-02-23 16:28:38.830  INFO 20439 --- [   

2.3 配置缺失加載配置(havingValue)

在上述代碼的基礎(chǔ)上,我們首先的Config1和Config2中稍作一些修改。

配置類

@Configuration
//  當(dāng)配置文件中config2.enable,匹配如果缺失加載
@ConditionalOnProperty(name = "config2.enable", havingValue = "true", matchIfMissing = true)
public class Config2 {
    @Bean
    public Dept dept() {
        System.err.println("=============dept初始化========");
        return new Dept();
    }
}

配置文件

config1:
  enable: false

啟動項(xiàng)目

2022-02-23 16:28:38.633  INFO 20439 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-02-23 16:28:38.633  INFO 20439 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 449 ms
=============dept初始化========
2022-02-23 16:28:38.830  INFO 20439 --- [   

Bean的加載

在Spring Boot應(yīng)用中要讓一個普通類交給Spring容器管理,通常有以下方法:

1、使用 @Configuration與@Bean 注解

2、使用@Controller @Service @Repository @Component 注解標(biāo)注該類并且啟用@ComponentScan自動掃描

3、使用@Import 方法

其中Spring Boot實(shí)現(xiàn)自動配置使用的是@Import注解這種方式,AutoConfigurationImportSelector類的selectImports方法返回一組從META-INF/spring.factories文件中讀取的bean的全類名,這樣Spring Boot就可以加載到這些Bean并完成實(shí)例的創(chuàng)建工作。

2.2.3 自動配置總結(jié)
我們可以將自動配置的關(guān)鍵幾步以及相應(yīng)的注解總結(jié)如下:

1、@Configuration與@Bean:基于Java代碼的bean配置

2、@Conditional:設(shè)置自動配置條件依賴

3、@EnableConfigurationProperties與@ConfigurationProperties:讀取配置文件轉(zhuǎn)換為bean

4、@EnableAutoConfiguration與@Import:實(shí)現(xiàn)bean發(fā)現(xiàn)與加載

2.3 自定義starter

本小節(jié)我們通過自定義兩個starter來加強(qiáng)starter的理解和應(yīng)用。

2.3.1 案例一

2.3.1.1 開發(fā)starter

第一步:創(chuàng)建starter工程hello-spring-boot-starter并配置pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>cn.itcast</groupId>
    <artifactId>hello-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
    </dependencies>
</project>

第二步:創(chuàng)建配置屬性類HelloProperties

package cn.itcast.config;

import org.springframework.boot.context.properties.ConfigurationProperties;

/*
 *讀取配置文件轉(zhuǎn)換為bean
 * */
@ConfigurationProperties(prefix = "hello")
public class HelloProperties {
    private String name;
    private String address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "HelloProperties{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

第三步:創(chuàng)建服務(wù)類HelloService

package cn.itcast.service;

public class HelloService {
    private String name;
    private String address;

    public HelloService(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public String sayHello(){
        return "你好!我的名字叫 " + name + ",我來自 " + address;
    }
}

第四步:創(chuàng)建自動配置類HelloServiceAutoConfiguration

package cn.itcast.config;

import cn.itcast.service.HelloService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/*
* 配置類,基于Java代碼的bean配置
* */

@Configuration
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfiguration {
    private HelloProperties helloProperties;

    //通過構(gòu)造方法注入配置屬性對象HelloProperties
    public HelloServiceAutoConfiguration(HelloProperties helloProperties) {
        this.helloProperties = helloProperties;
    }

    //實(shí)例化HelloService并載入Spring IoC容器
    @Bean
    @ConditionalOnMissingBean
    public HelloService helloService(){
        return new HelloService(helloProperties.getName(),helloProperties.getAddress());
    }
}

第五步:在resources目錄下創(chuàng)建META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.itcast.config.HelloServiceAutoConfiguration

至此starter已經(jīng)開發(fā)完成了,可以將當(dāng)前starter安裝到本地maven倉庫供其他應(yīng)用來使用。

2.3.1.2 使用starter

第一步:創(chuàng)建maven工程myapp并配置pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>cn.itcast</groupId>
    <artifactId>myapp</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--導(dǎo)入自定義starter-->
        <dependency>
            <groupId>cn.itcast</groupId>
            <artifactId>hello-spring-boot-starter</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

第二步:創(chuàng)建application.yml文件

server:
  port: 8080
hello:
  name: xiaoming
  address: beijing

第三步:創(chuàng)建HelloController

package cn.itcast.controller;

import cn.itcast.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class HelloController {
    //HelloService在我們自定義的starter中已經(jīng)完成了自動配置,所以此處可以直接注入
    @Autowired
    private HelloService helloService;

    @GetMapping("/say")
    public String sayHello(){
        return helloService.sayHello();
    }
}

第四步:創(chuàng)建啟動類HelloApplication

package cn.itcast;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

執(zhí)行啟動類main方法,訪問地址http://localhost:8080/hello/say

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容