SpringBoot2(007):关于Spring beans、依赖注入 和 @SpringBootApplication 注解

Spring Boot2系列文章可以通过这里进行回顾:SpringBoot2(001):入门介绍、官网参考和博客汇总


  本文就 Spring Beans、依赖注入 和 @SpringBootApplication 注解的使用等进行说明,分别参考官方文档: 17. Spring Beans and Dependency Injection 和 18. Using the @SpringBootApplication Annotation 。本文的目录结构如下:

1、关于Spring beans 和 依赖注入(Dependency Injection)

  spring boot 和 SpringFramework 全家桶无缝衔接,开发过程中可以很轻松地使用 SpringFramework 全家桶的技术来定义 beans 及其需要注入的依赖(their injected dependencies)。最常用的比如@ComponentScan (用于扫描和查找 beans ) 和 @Autowired (用于构造器注入),效果都是杠杠的,省去了很多配置。

  如果工程项目按照建议的代码结构来布局(主配置类在 root package 上),不用增加其他的配置参数,单独的 @ComponentScan 就会进行自动扫描,把 root package 下所有有注解声明的 beans (@Component,@Service, @Repository, @Controller 等)都当作 spring beans 自动注册进来。

  当然,很多时候会引入他项目的接口包,而且包结构往往和本项目的包结构会有些差异,这个时候可能就需要配置扫描路径了。比如下面这个例子,主类 com.wpbxin.HelloWorldExample 默认会扫描 com.wpbxin(也就是 root package)下的所有有注解声明的 beans,所以我们就不用专门去配置需要扫描的路径了。但是我引用的其他项目的一个接口包,而这个包里面的路径是 com.wpb.mapper ,很明显不在约定扫描范围内,这个时候就需要使用 @ComponentScan("com.wpb.mapper") 进行导入了,这里建议直接新起一个配置类,比如在根包下的子包 com.wpbxin.config.MapperConfig 。这样就会进行间接的默认扫描了。

package com.wpbxin;

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.web.bind.annotation.*;

@RestController
@EnableAutoConfiguration
public class HelloWorldExample {
    @RequestMapping("/")
    String home() {
        return "Hello World!";
    }
    public static void main(String[] args) {
        SpringApplication.run(HelloWorldExample.class, args);
    }
}

/// 通过配置类的形式导入外部需要扫描的包
package com.wpbxin.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.wpb.mapper")
public class MapperConfig {

}

  下面这个例子,一个 @Service Bean 通过使用构造器注入获取所需的 RiskAssessor bean:

package com.example.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DatabaseAccountService implements AccountService {
    private final RiskAssessor riskAssessor;
    
    @Autowired
    public DatabaseAccountService(RiskAssessor riskAssessor) {
        this.riskAssessor = riskAssessor;
    }
    
    // ...
    
}

   如果 bean 中含有一个构造器,可以忽略 @Autowired:

@Service
public class DatabaseAccountService implements AccountService {

    private final RiskAssessor riskAssessor;
    
    public DatabaseAccountService(RiskAssessor riskAssessor) {
        this.riskAssessor = riskAssessor;
    }
    
    // ...
    
}

  小提示:final 表示赋值之后无法修改只想其他引用了。

2、关于 @SpringBootApplication 注解

  很多开发者在 spring boot 应用中使用 auto-configuration、 component scan,并且可以在应用类(application class)中定义额外的配置。其实直接使用 @SpringBootApplication 注解就可以开启这3个特性了:

  也即是说 @SpringBootApplication 注解在功能上对等于同时使用 @Configuration、@EnableAutoConfiguration 和 @ComponentScan ,而且这3个注解使用默认配置。例子如下:

package com.example.myapplication;

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

@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class Application {

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

   注意点1:@SpringBootApplication 也提供了别名来指定 @EnableAutoConfiguration 和 @ComponentScan 的属性配置。

  注意点2:这几个特性都不是强制性的,可以根据需要进行替换或者直接不开启。例如,不想使用 component scan 功能的话,可以这样写:

package com.example.myapplication;

import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@EnableAutoConfiguration
@Import({ MyConfig.class, MyAnotherConfig.class })
public class Application {

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

  上面这个例子除了有 @Component 注解的类不会被自动扫描检测外,和其他 spring boot 应用没啥两样,并且用户自定义的 beans 需要被显示 import 进来(@Import)。

3、参考

原文地址:https://www.cnblogs.com/wpbxin/p/11963273.html