Springboot - 2.控制反转(IoC)和 依赖注入(DI)

✍1. 控制反转(IoC)和 依赖注入(DI):

  • 控制反转(IoC): spring-core模块实现了IoC容器,它是Spring框架的核心概念之一。IoC指的是将对象的创建和依赖关系的管理交给容器来处理,而不是在代码中硬编码。Spring的IoC容器负责管理Bean的生命周期、依赖关系以及Bean的装配。

  • 依赖注入(DI): spring-core模块通过依赖注入将Bean之间的依赖关系注入到容器中,从而解耦了组件之间的紧密耦合。使用DI,开发者可以通过构造函数、Setter方法或字段注入等方式将依赖关系注入到Bean中。

1. 定义Bean:

在Spring Boot中,您可以使用@Component及其衍生注解(如@Service@Repository@Controller等)来定义Bean。这些注解标记了一个类作为Spring容器中的一个Bean。例如:

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

2. 依赖注入:

Spring Boot通过IOC容器来实现依赖注入。您可以使用@Autowired注解将依赖对象注入到需要它们的地方。例如,在构造函数、Setter方法、字段上使用@Autowired注解:

@Service
public class MyService {
    private final AnotherService anotherService;

    @Autowired
    public MyService(AnotherService anotherService) {
        this.anotherService = anotherService;
    }

    // ...
}

3. 配置注入:

Spring Boot推荐使用Java配置类来配置Bean,而不是XML配置文件。您可以使用@Configuration注解标记配置类,并在方法上使用@Bean注解来定义Bean。例如:

  • 在Spring Boot中,配置类是一种使用Java代码来配置应用程序的方式,取代了传统的XML配置文件。配置类使用@Configuration注解进行标记,通常使用@Bean注解来定义Bean,以及其他配置相关的注解来实现各种功能。以下是关于配置类在Spring Boot中的详细解释和示例:

    • 创建配置类: 首先,您需要创建一个Java类并使用@Configuration注解来标记它,使其成为一个配置类。

      import org.springframework.context.annotation.Configuration;
      
      @Configuration
      public class AppConfig {
          // Configuration related methods will be defined here
      }
      
    • 定义Bean: 在配置类中,您可以使用@Bean注解来定义Bean。方法的返回值类型将成为该Bean的类型,方法名将成为该Bean的名称。

      import org.springframework.context.annotation.Bean;
      
      @Configuration
      public class AppConfig {
          @Bean
          public MyService myService() {
              return new MyService();
          }
      }
      
    • 依赖注入其他Bean: 在配置类中,您可以使用@Autowired注解来依赖注入其他Bean,就像在其他普通的组件类中一样。

      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      
      @Configuration
      public class AppConfig {
          @Autowired
          private AnotherService anotherService;
      
          @Bean
          public MyService myService() {
              return new MyService(anotherService);
          }
      }
      
    • 使用外部属性: 配置类还可以使用@Value注解来注入外部属性值,或者使用@ConfigurationProperties注解来绑定属性配置。

      import org.springframework.boot.context.properties.ConfigurationProperties;
      import org.springframework.stereotype.Component;
      
      @Component
      @ConfigurationProperties(prefix = "app.config")
      public class AppConfigProperties {
          private String greetingMessage;
          private int maxRetry;
          private int timeout;
      
          // Getter and setter methods for the properties
      }
      
      
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.context.ConfigurableApplicationContext;
      
      @SpringBootApplication
      public class Application {
      
          @Autowired
          private AppConfigProperties appConfig;
      
          public static void main(String[] args) {
              ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
              Application application = context.getBean(Application.class);
              application.printConfig();
          }
      
          public void printConfig() {
              System.out.println("Greeting message: " + appConfig.getGreetingMessage());
              System.out.println("Max retry: " + appConfig.getMaxRetry());
              System.out.println("Timeout: " + appConfig.getTimeout());
          }
      }
      
      
    • 组合配置类: 多个配置类可以组合在一起,形成一个综合的配置。Spring Boot会自动将这些配置类合并成一个应用程序上下文。

      @Configuration
      public class DatabaseConfig {
          // Define database-related beans and configurations
      }
      
      @Configuration
      public class MessagingConfig {
          // Define messaging-related beans and configurations
      }
      
      @Configuration
      @Import({DatabaseConfig.class, MessagingConfig.class})
      public class AppConfig {
          // Main configuration and other beans
      }
      
      import org.springframework.context.annotation.AnnotationConfigApplicationContext;
      
      public class MainApp {
          public static void main(String[] args) {
              AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
              // Get and use beans from the application context
          }
      }
      
    • 总结:组合配置类是一种将多个配置类组合在一起的方法,使配置更加清晰、模块化和可维护。通过创建主配置类并使用@Import注解来导入其他配置类,您可以在应用程序中有效地管理配置。这种方法有助于降低配置的复杂性,并提高了应用程序的可扩展性和可维护性。

4. 属性注入:

除了构造函数和Setter方法注入外,您还可以使用@Autowired注解在属性上进行依赖注入。这样,Spring Boot会自动将依赖注入到属性中。

@Service
public class MyService {
    @Autowired
    private AnotherService anotherService;

    // ...
}

5. Qualifiers和Primary:

如果存在多个实现相同接口的Bean,您可以使用@Qualifier注解指定要注入的具体Bean。另外,您还可以使用@Primary注解标记一个主要的Bean,它将被首选用于注入。

  • 当您在Spring Boot中使用依赖注入时,可能会遇到多个相同类型的Bean的情况,例如,有多个实现了相同接口的类。在这种情况下,为了告诉Spring容器应该注入哪个具体的Bean,您可以使用@Qualifier注解和@Primary注解。

    • @Qualifier 注解:
      @Qualifier注解用于在存在多个相同类型的Bean时,明确指定要注入的Bean的名称。通过指定@Qualifier的值,您可以告诉Spring容器应该注入哪个具体的Bean。

      • 示例:
      @Service
      public class MyService {
          private final AnotherService primaryAnotherService;
          private final AnotherService secondaryAnotherService;
      
          @Autowired
          public MyService(@Qualifier("primary") AnotherService primaryAnotherService,
                           @Qualifier("secondary") AnotherService secondaryAnotherService) {
              this.primaryAnotherService = primaryAnotherService;
              this.secondaryAnotherService = secondaryAnotherService;
          }
      
          // ...
      }
      
    • @Primary 注解:
      @Primary注解用于标记一个Bean为首选的Bean,当存在多个相同类型的Bean时,被标记为@Primary的Bean将会被优先注入。如果没有指定@Qualifier,那么@Primary注解的Bean将作为默认选择。

      • 示例:
      @Service
      @Primary
      public class PrimaryAnotherService implements AnotherService {
          // ...
      }
      
      @Service
      public class SecondaryAnotherService implements AnotherService {
          // ...
      }
      
      @Service
      public class MyService {
          private final AnotherService anotherService;
      
          @Autowired
          public MyService(AnotherService anotherService) {
              this.anotherService = anotherService;
          }
      
          // ...
      }
      
    • 总结:在Spring Boot中,当存在多个相同类型的Bean时,您可以使用@Qualifier注解来指定要注入的具体Bean。另外,您还可以使用@Primary注解来标记一个Bean为首选Bean,优先注入。这些注解有助于在多个候选Bean之间进行选择,从而满足您的依赖注入需求。

6. 可选依赖:

如果依赖对象可能不存在,您可以使用@Autowired(required = false)来标记注入的依赖为可选的。如果找不到匹配的Bean,注入的字段将为null

@Service
public class MyService {
    @Autowired(required = false)
    private AnotherService optionalAnotherService;

    // ...
}

7. 属性值注入:

Spring Boot还支持将属性值注入到Bean中,您可以使用@Value注解来实现。这在配置文件中配置的属性值会注入到Bean的字段或方法参数中。

属性值注入是一种在Spring Boot中将外部属性值注入到Bean中的机制。这样,您可以将配置信息从代码中分离出来,使您的应用程序更加灵活和可配置。Spring Boot通过@Value注解来实现属性值注入。

  • 以下是属性值注入在Spring Boot中的详细解释和示例:

    • 在配置文件中定义属性值: 首先,在application.propertiesapplication.yml配置文件中定义属性值。例如,在application.properties文件中:

      app.greeting.message=Hello from properties file!
      
    • 在Bean中使用 @Value 注解: 然后,您可以在Bean的字段、构造函数参数、方法参数等地方使用@Value注解来注入属性值。注解的值是从配置文件中读取的属性的名称。

      • 示例:
      @Service
      public class MyService {
          @Value("${app.greeting.message}")
          private String greetingMessage;
      
          public void printGreeting() {
              System.out.println(greetingMessage);
          }
      }
      
    • 使用 SpEL 表达式: @Value注解还支持使用Spring表达式语言(SpEL)来计算属性值。您可以在注解中使用${expression}来引用SpEL表达式。

      • 示例:
      @Service
      public class MyService {
          @Value("#{T(java.lang.Math).random()}")
          private double randomNumber;
      
          public void printRandomNumber() {
              System.out.println(randomNumber);
          }
      }
      
    • 默认值: 如果属性在配置文件中不存在,您可以使用@Value注解的defaultValue属性来设置默认值。

      • 示例:
      @Service
      public class MyService {
          @Value("${app.nonexistent.property:Default Value}")
          private String defaultValue;
      
          public void printDefaultValue() {
              System.out.println(defaultValue);
          }
      }
      
    • 总结:属性值注入是Spring Boot中的一个重要特性,通过使用@Value注解,您可以将外部属性值注入到Bean中,从而使您的应用程序更具灵活性和可配置性。您可以从配置文件中读取属性值,并使用SpEL表达式进行计算。另外,您还可以设置默认值,以防属性在配置文件中不存在。

8. 集合注入:

如果需要注入多个相同类型的依赖,您可以使用ListSetMap等集合来进行集合注入。

  • 在Spring Boot中,集合注入是一种将多个相同类型的依赖对象注入到一个集合中的机制。这种机制非常适用于场景,其中您需要处理多个实现了相同接口或父类的依赖对象。Spring Boot通过使用@Autowired注解结合ListSetMap等集合类型,使集合注入变得非常方便。

    • 以下是集合注入在Spring Boot中的详细解释和示例:

    • 定义多个实现类: 首先,假设您有多个实现了同一个接口的类,例如:

      public interface Plugin {
          void execute();
      }
      
      @Service
      public class PluginA implements Plugin {
          // ...
      }
      
      @Service
      public class PluginB implements Plugin {
          // ...
      }
      
    • 在Bean中使用集合注入: 然后,您可以在需要依赖注入这些实现类的Bean中,使用@Autowired注解结合集合类型(如ListSetMap等)进行集合注入。

      • 示例:
      @Service
      public class PluginManager {
          private final List<Plugin> plugins;
      
          @Autowired
          public PluginManager(List<Plugin> plugins) {
              this.plugins = plugins;
          }
      
          public void executeAllPlugins() {
              for (Plugin plugin : plugins) {
                  plugin.execute();
              }
          }
      }
      
    • 在上面的示例中,PluginManager类通过构造函数注入了一个List集合,该集合包含了所有实现了Plugin接口的Bean。集合注入是Spring Boot中的一个强大特性,它允许您将多个相同类型的依赖对象注入到一个集合中,使您能够方便地处理多个实现了相同接口或父类的依赖。通过使用@Autowired注解和集合类型,您可以在Bean中轻松地实现集合注入,从而更好地管理和处理依赖关系。

  • 总结:在Spring Boot应用程序中,依赖注入是一种重要的设计模式,通过使用@Autowired@Qualifier@Value等注解,您可以实现将依赖关系从代码中解耦,从而使代码更具可维护性和可扩展性。结合Spring Boot的自动配置功能,依赖注入可以更加便捷地实现,使您能够更专注于业务逻辑的开发。

你可能感兴趣的:(Springboot-详解,spring,boot,后端,java)