当前位置: 首页 > news >正文

Springboot - 1.什么是springboot

👀Spring的核心模块

Spring Framework是一个功能强大的开源框架,用于构建Java企业级应用程序。它提供了多个核心模块,每个模块都提供不同的功能,用于解决应用程序开发中的各种问题。以下是Spring Framework的核心模块的全面解析:

✌1. spring-core:

spring-core是Spring Framework的核心模块之一,提供了Spring框架的基本功能,包括控制反转(IoC)和依赖注入(DI)的实现,以及其他一些基础设施。它是其他许多Spring模块的基础,为整个Spring生态系统提供了支持。以下是有关spring-core模块的详细解释:

✍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;@Autowiredpublic 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 {@Beanpublic 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 {@Autowiredprivate AnotherService anotherService;@Beanpublic 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 {@Autowiredprivate 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 {@Autowiredprivate 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;@Autowiredpublic 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;@Autowiredpublic 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注解结合集合类型(如List<Plugin>Set<Plugin>Map<String, Plugin>等)进行集合注入。

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

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

✍2. BeanFactory

在Spring Boot中,BeanFactory是Spring Framework的核心接口之一,用于管理和维护应用程序中的Bean实例。它是Spring IoC容器的基础,负责创建、初始化、装配和管理Bean。在Spring Boot中,BeanFactory的实现主要是DefaultListableBeanFactory。以下是结合Spring Boot详细解释BeanFactory的重要概念和用法

🎷1. BeanFactory接口:

BeanFactory接口是Spring IoC容器的根接口,用于从容器中获取Bean。

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class MyComponent {private final BeanFactory beanFactory;@Autowiredpublic MyComponent(BeanFactory beanFactory) {this.beanFactory = beanFactory;}public void useBean() {MyService myService = beanFactory.getBean(MyService.class);myService.doSomething();}
}

🎷2. 默认实现:

在Spring Boot中,默认的BeanFactory实现是DefaultListableBeanFactory

🎷3. Bean的生命周期:

BeanFactory负责管理Bean的生命周期,如实例化、属性注入和初始化。这个过程会根据配置进行。

🎷4. Bean的获取:

使用getBean()方法从容器中获取Bean。

MyService myService = beanFactory.getBean(MyService.class);

🎷5. 延迟初始化:

默认情况下,BeanFactory支持延迟初始化,只有在需要时才创建Bean实例。

🎷6. 扩展和自定义:

您可以实现BeanPostProcessor接口来自定义Bean的创建和初始化过程。

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;@Component
public class MyBeanPostProcessor implements BeanPostProcessor {// Override methods for customizing bean initialization
}

🎷7. 注解配置:

使用注解定义Bean。

import org.springframework.stereotype.Component;@Component
public class MyService {// Bean implementation
}

🎷8. 注解扫描:

使用注解扫描自动注册标记了@Component的Bean。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication
public class Application {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);MyService myService = context.getBean(MyService.class);myService.doSomething();}
}

🎷9. 自动装配:

使用@Autowired注解进行自动装配。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class MyController {private final MyService myService;@Autowiredpublic MyController(MyService myService) {this.myService = myService;}// Controller logic
}

✍3. 如何使用BeanFactory:

在Spring Boot中,BeanFactory是Spring IoC容器的根接口。它提供了配置框架和基本功能,如获取Bean的实例。

🎷1. 注入BeanFactory:

  • 我们可以通过实现BeanFactoryAware接口或者直接在Bean中注入BeanFactory来使用它。

    @Component
    public class ExampleBean implements BeanFactoryAware {private BeanFactory beanFactory;@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {this.beanFactory = beanFactory;}public void doSomething() {// 使用beanFactoryAnotherBean anotherBean = (AnotherBean) beanFactory.getBean(AnotherBean.class);anotherBean.doSomething();}}@Component
    public class AnotherBean {public void doSomething() {System.out.println("AnotherBean doSomething 方法被调用");}}
    

    在这个示例中,ExampleBean实现了BeanFactoryAware接口,这样Spring容器会自动注入BeanFactory。然后,在doSomething方法中,我们使用beanFactory获取AnotherBean的实例,并调用它的doSomething方法。

🎷2. 使用@Autowired注解:

  • 我们可以使用@Autowired注解直接在Bean中注入BeanFactory

    @Component
    public class ExampleBean {@Autowiredprivate BeanFactory beanFactory;public void doSomething() {// 使用beanFactoryAnotherBean anotherBean = (AnotherBean) beanFactory.getBean(AnotherBean.class);anotherBean.doSomething();}}@Component
    public class AnotherBean {public void doSomething() {System.out.println("AnotherBean doSomething 方法被调用");}}
    

    在这个示例中,我们使用@Autowired注解直接在ExampleBean中注入BeanFactory。然后,在doSomething方法中,我们使用beanFactory获取AnotherBean的实例,并调用它的doSomething方法。

✍4. ApplicationContext:

当在Spring Boot中使用ApplicationContext时,您可以遵循以下详细示例来了解每个概念和用法,同时考虑了Spring Boot的自动配置和便利性:

🎷1. ApplicationContext接口:

ApplicationContext是Spring IoC容器的更高级别接口,除了BeanFactory的功能外,还提供了更多的功能,如国际化、事件传播等。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;@Component
public class MyComponent {private final ApplicationContext applicationContext;@Autowiredpublic MyComponent(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}public void useBean() {MyService myService = applicationContext.getBean(MyService.class);myService.doSomething();}
}

🎷2. 默认实现:

在Spring Boot中,默认的ApplicationContext实现是AnnotationConfigApplicationContext,用于基于注解的配置。

🎷3. Bean的生命周期:

ApplicationContext也负责管理Bean的生命周期,与BeanFactory相同。

🎷4. Bean的获取:

使用getBean()方法从容器中获取Bean,与BeanFactory相同。

MyService myService = applicationContext.getBean(MyService.class);

🎷5. 延迟初始化:

默认情况下,ApplicationContext同样支持延迟初始化,只有在需要时才创建Bean实例。

🎷6. 扩展和自定义:

您可以实现BeanPostProcessor接口等来自定义Bean的创建和初始化过程,与BeanFactory相同。

🎷7. 注解配置:

使用注解定义Bean。

import org.springframework.stereotype.Component;@Component
public class MyService {// Bean implementation
}

🎷8. 注解扫描:

使用注解扫描自动注册标记了@Component的Bean,与BeanFactory相同。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication
public class Application {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);MyService myService = context.getBean(MyService.class);myService.doSomething();}
}

🎷9. 自动装配:

使用@Autowired注解进行自动装配,与BeanFactory相同。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class MyController {private final MyService myService;@Autowiredpublic MyController(MyService myService) {this.myService = myService;}// Controller logic
}

通过这些详细示例,您可以更深入地理解在Spring Boot中如何使用ApplicationContext来管理和使用Bean,同时利用Spring Boot的自动配置和便利性。ApplicationContext提供了更多的功能,如事件传播和国际化,使得应用程序更加灵活和功能丰富。

✍5. 如何使用ApplicationContext:

在Spring Boot中,ApplicationContext是一个中央接口,它提供了应用程序运行时的配置信息。ApplicationContextBeanFactory的子接口,它添加了更多的企业级功能,比如从一个属性文件中解析文本信息。

🎷1. 注入ApplicationContext:

  • 我们可以通过实现ApplicationContextAware接口或者直接在Bean中注入ApplicationContext来使用它。

    @Component
    public class ExampleBean implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}public void doSomething() {// 使用applicationContextAnotherBean anotherBean = (AnotherBean) applicationContext.getBean(AnotherBean.class);anotherBean.doSomething();}}@Component
    public class AnotherBean {public void doSomething() {System.out.println("AnotherBean doSomething 方法被调用");}}
    

    在这个示例中,ExampleBean实现了ApplicationContextAware接口,这样Spring容器会自动注入ApplicationContext。然后,在doSomething方法中,我们使用applicationContext获取AnotherBean的实例,并调用它的doSomething方法。

🎷2. 使用@Autowired注解:

  • 我们可以使用@Autowired注解直接在Bean中注入ApplicationContext

    @Component
    public class ExampleBean {@Autowiredprivate ApplicationContext applicationContext;public void doSomething() {// 使用applicationContextAnotherBean anotherBean = (AnotherBean) applicationContext.getBean(AnotherBean.class);anotherBean.doSomething();}}@Component
    public class AnotherBean {public void doSomething() {System.out.println("AnotherBean doSomething 方法被调用");}}
    

    在这个示例中,我们使用@Autowired注解直接在ExampleBean中注入ApplicationContext。然后,在doSomething方法中,我们使用applicationContext获取AnotherBean的实例,并调用它的doSomething方法。

🎷3. 使用ApplicationListener接口:

  • 我们可以实现ApplicationListener接口来监听应用程序的事件。

    @Component
    public class ExampleBean implements ApplicationListener<ContextRefreshedEvent> {@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {System.out.println("应用程序上下文刷新");}}
    

    在这个示例中,ExampleBean实现了ApplicationListener接口,这样它会监听ContextRefreshedEvent事件。当应用程序上下文刷新时,onApplicationEvent方法会被调用。

✍4. Bean的生命周期:

当然,我会详细描述每一步的作用。

🎷1. 实例化Bean:

  • 这是Bean生命周期的第一步。Spring容器通过反射机制创建Bean的实例。
    public class ExampleBean {// ...
    }
    

🎷2. 设置Bean的属性:

  • Spring容器将根据配置文件设置Bean的属性。这是通过调用Bean的setter方法完成的。
    public class ExampleBean {private String name;public void setName(String name) {this.name = name;}// ...
    }
    

🎷3. 调用BeanNameAwaresetBeanName方法:

  • 如果Bean实现了BeanNameAware接口,Spring容器将调用setBeanName方法,传递Bean的ID。这允许Bean知道它在Spring容器中的ID。
    public class ExampleBean implements BeanNameAware {private String beanName;@Overridepublic void setBeanName(String name) {this.beanName = name;}// ...
    }
    

🎷4. 调用BeanFactoryAwaresetBeanFactory方法:

  • 如果Bean实现了BeanFactoryAware接口,Spring容器将调用setBeanFactory方法,传递自身。这允许Bean知道它所属的容器。
    public class ExampleBean implements BeanFactoryAware {private BeanFactory beanFactory;@Overridepublic void setBeanFactory(BeanFactory beanFactory) {this.beanFactory = beanFactory;}// ...
    }
    

🎷5. 调用ApplicationContextAwaresetApplicationContext方法:

  • 如果Bean实现了ApplicationContextAware接口,Spring容器将调用setApplicationContext方法,传递自身。这允许Bean知道它所属的应用上下文。
    public class ExampleBean implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}// ...
    }
    

🎷6. 调用BeanPostProcessorpostProcessBeforeInitialization方法:

  • 如果Bean实现了BeanPostProcessor接口,Spring容器将在初始化方法之前调用postProcessBeforeInitialization方法。这允许对Bean的属性进行更改。
    public class CustomBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {// ...return bean;}// ...
    }
    

🎷7. 调用InitializingBeanafterPropertiesSet方法:

  • 如果Bean实现了InitializingBean接口,Spring容器将在所有属性设置完成后调用afterPropertiesSet方法。
    public class ExampleBean implements InitializingBean {@Overridepublic void afterPropertiesSet() throws Exception {// ...}// ...
    }
    

🎷8. 调用自定义的初始化方法:

  • 如果在Bean的定义中指定了自定义的初始化方法,Spring容器将调用它。
    public class ExampleBean {public void init() {// ...}// ...
    }
    

🎷9. 调用BeanPostProcessorpostProcessAfterInitialization方法:

  • 如果Bean实plement了BeanPostProcessor接口,Spring容器将在初始化方法之后调用postProcessAfterInitialization方法。
    public class CustomBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {// ...return bean;}// ...
    }
    

🎷10. Bean的使用:

  • 现在,Bean已经准备好了,可以被应用程序使用。

🎷11. 调用DisposableBeandestroy方法:

  • 如果Bean实现了DisposableBean接口,Spring容器将在容器关闭时调用destroy方法。
    public class ExampleBean implements DisposableBean {@Overridepublic void destroy() throws Exception {// ...}// ...
    }
    

🎷12. 调用自定义的销毁方法:

  • 如果在Bean的定义中指定了自定义的销毁方法,Spring容器将在容器关闭时调用它。
    public class ExampleBean {public void destroy() {// ...}// ...
    }
    

🎷13. 下面是一个简单的Java配置示例:

@Configuration
public class AppConfig {@Bean(initMethod = "init", destroyMethod = "destroy")public ExampleBean exampleBean() {return new ExampleBean();}}
  • 在这个示例中,ExampleBean是一个简单的Java类,它有initdestroy方法,分别作为初始化和销毁方法。

🎷14. 流程图如下:

+-------------------+
|   实例化Bean       |
+-------------------+|v
+-------------------+
|  设置Bean的属性     |
+-------------------+|v
+-------------------+
| 调用BeanNameAware  |
| 的setBeanName方法   |
+-------------------+|v
+-------------------+
| 调用BeanFactoryAware|
| 的setBeanFactory方法 |
+-------------------+|v
+-------------------+
| 调用ApplicationContextAware|
| 的setApplicationContext方法 |
+-------------------+|v
+-------------------+
| 调用BeanPostProcessor |
| 的postProcessBeforeInitialization方法 |
+-------------------+|v
+-------------------+
| 调用InitializingBean|
| 的afterPropertiesSet方法 |
+-------------------+|v
+-------------------+
| 调用自定义的初始化方法 |
+-------------------+|v
+-------------------+
| 调用BeanPostProcessor |
| 的postProcessAfterInitialization方法 |
+-------------------+|v
+-------------------+
|     Bean的使用      |
+-------------------+|v
+-------------------+
| 调用DisposableBean |
| 的destroy方法       |
+-------------------+|v
+-------------------+
| 调用自定义的销毁方法  |
+-------------------+

✍5. 如何使用Bean的生命周期:

在Spring Boot中,我们可以使用Java配置、注解和自定义的BeanPostProcessor来使用Bean的生命周期。

🎷1. 使用Java配置:

  • 我们可以使用@Bean注解的initMethoddestroyMethod属性来指定Bean的初始化和销毁方法。

    @Configuration
    public class AppConfig {@Bean(initMethod = "init", destroyMethod = "destroy")public ExampleBean exampleBean() {return new ExampleBean();}}public class ExampleBean {public void init() {System.out.println("ExampleBean 初始化");}public void destroy() {System.out.println("ExampleBean 销毁");}}
    

    在这个示例中,ExampleBean是一个简单的Java类,它有initdestroy方法,分别作为初始化和销毁方法。

🎷2. 使用@PostConstruct@PreDestroy注解:

  • 我们可以使用@PostConstruct注解来标记Bean的初始化方法,使用@PreDestroy注解来标记Bean的销毁方法。

    @Component
    public class ExampleBean {@PostConstructpublic void init() {System.out.println("ExampleBean 初始化");}@PreDestroypublic void destroy() {System.out.println("ExampleBean 销毁");}}
    

    在这个示例中,ExampleBean是一个简单的Java类,它有initdestroy方法,分别作为初始化和销毁方法。

🎷3. 使用InitializingBeanDisposableBean接口:

  • 我们可以让Bean实现InitializingBean接口和DisposableBean接口。

    @Component
    public class ExampleBean implements InitializingBean, DisposableBean {@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("ExampleBean 初始化");}@Overridepublic void destroy() throws Exception {System.out.println("ExampleBean 销毁");}}
    

    在这个示例中,ExampleBean是一个简单的Java类,它实现了InitializingBean接口和DisposableBean接口。

🎷4. 使用自定义的BeanPostProcessor:

  • 我们可以创建一个自定义的BeanPostProcessor,并在postProcessBeforeInitialization方法和postProcessAfterInitialization方法中添加自定义的逻辑。

    @Component
    public class CustomBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof ExampleBean) {System.out.println("ExampleBean 初始化之前");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof ExampleBean) {System.out.println("ExampleBean 初始化之后");}return bean;}}@Component
    public class ExampleBean {// ...}
    

    在这个示例中,CustomBeanPostProcessor是一个自定义的BeanPostProcessor,它在ExampleBean的初始化之前和之后添加了自定义的逻辑。

✍6. AOP:

在Spring Boot中,AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,它允许我们将横切关注点(如日志、事务管理)从业务逻辑中分离出来。Spring框架提供了一个AOP框架,它允许我们定义切面、连接点、通知、切点等。

🎷1. 切面(Aspect):

  • 切面是一个模块化的关注点。它定义了通知和切点。

    示例:

    @Aspect
    @Component
    public class LoggingAspect {// ...}
    

    在这个示例中,LoggingAspect是一个切面,它定义了通知和切点。

🎷2. 连接点(Joinpoint):

  • 连接点是程序执行的某个位置,如方法的调用或异常的抛出。

    示例:

    @AfterReturning(pointcut = "serviceMethods()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {// ...
    }
    

    在这个示例中,logAfterReturning方法的joinPoint参数是一个连接点。

🎷3. 通知(Advice):

  • 通知是切面的一部分,它是在特定的连接点上执行的代码。有五种类型的通知:前置通知、后置通知、返回通知、异常通知、环绕通知。

    示例:

    @Before("serviceMethods()")
    public void logBefore(JoinPoint joinPoint) {// ...
    }@After("serviceMethods()")
    public void logAfter(JoinPoint joinPoint) {// ...
    }@AfterReturning(pointcut = "serviceMethods()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {// ...
    }@AfterThrowing(pointcut = "serviceMethods()", throwing = "exception")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable exception) {// ...
    }@Around("serviceMethods()")
    public Object logAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {// ...
    }
    

    在这个示例中,logBefore方法是一个前置通知,logAfter方法是一个后置通知,logAfterReturning方法是一个返回通知,logAfterThrowing方法是一个异常通知,logAround方法是一个环绕通知。

🎷4. 切点(Pointcut):

  • 切点是一组连接点的集合。它定义了通知应该在哪些连接点上执行。

    示例:

    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceMethods() {}
    

    在这个示例中,serviceMethods方法是一个切点,它匹配com.example.service包下的所有方法。

🎷5. 目标对象(Target Object):

  • 目标对象是被一个或多个切面通知的对象。

    示例:

    @Service
    public class ExampleService {public String doSomething(String name) {return "Hello, " + name;}}
    

    在这个示例中,ExampleService是一个目标对象,它被LoggingAspect切面通知。

🎷6. 代理(Proxy):

  • 代理是一个对象,它是目标对象的代理,它将调用转发到目标对象,并在调用之前或之后执行通知。

    在上面的示例中,当我们调用ExampleServicedoSomething方法时,实际上是调用了它的代理对象的doSomething方法。

🎷7. 织入(Weaving):

  • 织入是将切面和目标对象连接在一起的过程。

    在Spring Boot中,AOP的织入过程是在Spring容器完成Bean的初始化之后,也就是在postProcessAfterInitialization阶段。

  • 这些是Spring Boot中AOP的各个组成部分的示例和解释。在这个示例中,AOP的织入过程是在Spring容器完成Bean的初始化之后,也就是在postProcessAfterInitialization阶段。这是因为AOP需要在目标对象被完全初始化之后,才能创建它的代理对象。

🎷8. AopProxyUtils:

AopProxyUtils类是Spring AOP框架的一个工具类,它提供了一些静态方法,用于处理代理对象和目标对象。

  1. getSingletonTarget(Object candidate):
    这个方法用于获取单例bean的目标对象。

    示例:

    ExampleService targetObject = (ExampleService) AopProxyUtils.getSingletonTarget(exampleService);
    

    在这个示例中,exampleServiceExampleService的代理对象。我们使用AopProxyUtils.getSingletonTarget方法获取exampleService的目标对象。

    注意:这个方法只适用于单例bean。如果bean的作用域不是单例,这个方法将返回null

  2. getTargetClass(Object candidate):
    这个方法用于获取代理对象的目标类。

    示例:

    Class<?> targetClass = AopProxyUtils.getTargetClass(exampleService);
    

    在这个示例中,exampleServiceExampleService的代理对象。我们使用AopProxyUtils.getTargetClass方法获取exampleService的目标类。

    注意:这个方法返回的是目标类,而不是目标对象。

  3. ultimateTargetClass(Object candidate):
    这个方法用于获取代理对象的最终目标类。

    示例:

    Class<?> ultimateTargetClass = AopProxyUtils.ultimateTargetClass(exampleService);
    

    在这个示例中,exampleServiceExampleService的代理对象。我们使用AopProxyUtils.ultimateTargetClass方法获取exampleService的最终目标类。

    注意:这个方法返回的是最终目标类,而不是目标对象。如果代理对象有多层代理,这个方法将返回最终的目标类。

这些是AopProxyUtils类的一些常用方法。这个类还有一些其他方法,但它们通常不需要在应用程序代码中直接使用。

注意:通常我们不需要直接访问目标对象。代理对象会将调用转发到目标对象,并在调用之前或之后执行通知。所以,通常我们应该使用代理对象,而不是目标对象。直接访问目标对象会绕过代理,这意味着切面的通知将不会被执行。

这个类还包含一些其他的方法,但是它们主要用于内部使用,通常不需要在应用程序代码中直接使用。例如,AopProxyUtils.completeProxiedInterfaces方法用于确定给定的代理配置的完整代理接口集,包括从目标类继承的接口。这个方法通常用于在创建代理对象时确定代理接口。

✍7. 事件处理:

在Spring框架中,事件处理是通过ApplicationEvent类和ApplicationListener接口实现的。

🎷1. ApplicationEvent类:

  • ApplicationEvent是一个抽象类,它是所有应用程序事件的基类。

    示例:

    public class CustomEvent extends ApplicationEvent {private String message;public CustomEvent(Object source, String message) {super(source);this.message = message;}public String getMessage() {return message;}}
    

    在这个示例中,我们创建了一个CustomEvent类,它继承了ApplicationEvent类。CustomEvent类包含一个message属性,它可以用于传递事件的信息。

🎷2. ApplicationListener接口:

  • ApplicationListener是一个接口,它定义了一个onApplicationEvent方法,这个方法会在事件发布时被调用。

    示例:

    @Component
    public class CustomEventListener implements ApplicationListener<CustomEvent> {@Overridepublic void onApplicationEvent(CustomEvent event) {System.out.println("Received custom event - " + event.getMessage());}}
    

    在这个示例中,我们创建了一个CustomEventListener类,它实现了ApplicationListener接口。CustomEventListener类定义了onApplicationEvent方法,这个方法会在CustomEvent事件发布时被调用。

🎷3. 事件发布:

  • 事件可以通过ApplicationEventPublisher接口的publishEvent方法发布。

    示例:

    @Service
    public class ExampleService {@Autowiredprivate ApplicationEventPublisher applicationEventPublisher;public void doSomething() {System.out.println("Doing something...");CustomEvent customEvent = new CustomEvent(this, "This is a custom event");applicationEventPublisher.publishEvent(customEvent);}}
    

    在这个示例中,ExampleService类包含一个doSomething方法,这个方法会发布一个CustomEvent事件。

这是一个简单的Spring Boot应用程序示例,它包括事件的创建、监听和发布。

注意:Spring 4.2引入了一个新的@EventListener注解,它可以用于简化事件监听。使用@EventListener注解,我们可以直接在方法上定义事件监听,而不需要实现ApplicationListener接口。

示例:

@Component
public class CustomEventListener {@EventListenerpublic void handleCustomEvent(CustomEvent event) {System.out.println("Received custom event - " + event.getMessage());}}

在这个示例中,我们使用@EventListener注解定义了一个handleCustomEvent方法,这个方法会在CustomEvent事件发布时被调用。

✍8. 资源管理:

在Spring框架中,资源管理是通过Resource接口和ResourceLoader接口实现的。

🎷1. Resource接口:

  • Resource是一个接口,它定义了一些方法,用于访问底层资源的内容。

    Spring提供了一些Resource接口的实现类,例如ClassPathResourceFileSystemResourceUrlResource等。

    示例:

    @Service
    public class ExampleService {@Autowiredprivate ResourceLoader resourceLoader;public void doSomething() throws IOException {Resource resource = resourceLoader.getResource("classpath:example.txt");String content = new String(Files.readAllBytes(resource.getFile().toPath()));System.out.println(content);}}
    

    在这个示例中,ExampleService类包含一个doSomething方法,这个方法会读取classpath:example.txt文件的内容,并打印到控制台。

🎷2. ResourceLoader接口:

  • ResourceLoader是一个接口,它定义了一个getResource方法,用于加载资源。

    ApplicationContext接口扩展了ResourceLoader接口,因此,ApplicationContext也可以用作ResourceLoader

    示例:

    @Autowired
    private ResourceLoader resourceLoader;
    

    在这个示例中,我们注入了一个ResourceLoader,并使用它的getResource方法加载资源。

这是一个简单的Spring Boot应用程序示例,它包括资源的加载和读取。

注意:ResourceLoadergetResource方法根据资源路径的前缀来确定使用哪个Resource实现类。例如,classpath:前缀会使用ClassPathResource实现类,file:前缀会使用FileSystemResource实现类,没有前缀会使用ServletContextResource实现类。

另外,@Value注解也可以用于注入资源。

示例:

@Service
public class ExampleService {@Value("classpath:example.txt")private Resource resource;public void doSomething() throws IOException {String content = new String(Files.readAllBytes(resource.getFile().toPath()));System.out.println(content);}}

在这个示例中,我们使用@Value注解注入了一个Resource,并读取它的内容。

✍9. 验证:

在Spring框架中,验证是通过Validator接口实现的。

🎷1. Validator接口:

  • Validator是一个接口,它定义了两个方法:supportsvalidate

    supports方法用于检查给定的类是否可以被这个验证器验证。

    validate方法用于验证给定的对象。

    示例:

    public class PersonValidator implements Validator {@Overridepublic boolean supports(Class<?> clazz) {return Person.class.equals(clazz);}@Overridepublic void validate(Object target, Errors errors) {Person person = (Person) target;if (person.getAge() < 0) {errors.rejectValue("age", "negativevalue");} else if (person.getAge() > 110) {errors.rejectValue("age", "too.darn.old");}}}
    

    在这个示例中,我们创建了一个PersonValidator类,它实现了Validator接口。PersonValidator类定义了supports方法和validate方法。

🎷2. 使用Validator:

  • Validator可以在服务层或控制层使用。

    示例:

    @Service
    public class PersonService {private final Validator validator;@Autowiredpublic PersonService(Validator validator) {this.validator = validator;}public void doSomething(Person person) {DataBinder dataBinder = new DataBinder(person);dataBinder.setValidator(validator);dataBinder.validate();BindingResult bindingResult = dataBinder.getBindingResult();if (bindingResult.hasErrors()) {System.out.println(bindingResult.getAllErrors());} else {System.out.println("Person is valid");}}}
    

    在这个示例中,PersonService类包含一个doSomething方法,这个方法会验证Person对象。

这是一个简单的Spring Boot应用程序示例,它包括验证的创建和使用。

注意:Spring Boot自动配置了一个LocalValidatorFactoryBean,它是javax.validation.Validator的一个实现。因此,我们可以直接注入javax.validation.Validator,而不需要自定义一个Validator

另外,Spring MVC也支持javax.validation。我们可以在控制器的处理方法参数上添加@Valid注解,然后Spring MVC会在绑定请求参数到模型对象之后,对模型对象进行验证。

示例:

@RestController
public class PersonController {@PostMapping("/persons")public ResponseEntity<?> createPerson(@Valid @RequestBody Person person, BindingResult bindingResult) {if (bindingResult.hasErrors()) {return ResponseEntity.badRequest().body(bindingResult.getAllErrors());}// ...return ResponseEntity.ok(person);}}

在这个示例中,createPerson方法会验证Person对象。如果Person对象不合法,createPerson方法会返回一个包含所有错误的响应。

✍10. 数据绑定:

在Spring框架中,数据绑定是通过DataBinder类实现的。

🎷1. DataBinder类:

  • DataBinder是一个类,它用于绑定请求参数到目标对象,并对目标对象进行验证。

    示例:

    @Service
    public class PersonService {private final Validator validator;@Autowiredpublic PersonService(Validator validator) {this.validator = validator;}public void doSomething(Map<String, String> parameters) {Person person = new Person();DataBinder dataBinder = new DataBinder(person);dataBinder.setValidator(validator);dataBinder.bind(new MutablePropertyValues(parameters));dataBinder.validate();BindingResult bindingResult = dataBinder.getBindingResult();if (bindingResult.hasErrors()) {System.out.println(bindingResult.getAllErrors());} else {System.out.println("Person is valid");}}}
    

    在这个示例中,PersonService类包含一个doSomething方法,这个方法会绑定请求参数到Person对象,并对Person对象进行验证。

🎷2. 使用DataBinder:

  • DataBinder可以在服务层或控制层使用。

    示例:

    @RestController
    public class PersonController {private final PersonService personService;@Autowiredpublic PersonController(PersonService personService) {this.personService = personService;}@PostMapping("/persons")public ResponseEntity<?> createPerson(@RequestBody Map<String, String> parameters) {personService.doSomething(parameters);return ResponseEntity.ok().build();}}
    

    在这个示例中,PersonController类包含一个createPerson方法,这个方法会调用PersonServicedoSomething方法。

这是一个简单的Spring Boot应用程序示例,它包括数据绑定的创建和使用。

注意:Spring MVC也支持数据绑定。我们可以在控制器的处理方法参数上添加@ModelAttribute注解,然后Spring MVC会绑定请求参数到模型对象。

示例:

@RestController
public class PersonController {@PostMapping("/persons")public ResponseEntity<?> createPerson(@ModelAttribute Person person, BindingResult bindingResult) {if (bindingResult.hasErrors()) {return ResponseEntity.badRequest().body(bindingResult.getAllErrors());}// ...return ResponseEntity.ok(person);}}

在这个示例中,createPerson方法会绑定请求参数到Person对象。如果Person对象不合法,createPerson方法会返回一个包含所有错误的响应。

✍11. 类型转换:

在Spring框架中,类型转换是通过ConversionService接口实现的。

🎷1. ConversionService接口:

  • ConversionService是一个接口,它定义了两个方法:canConvertconvert

    canConvert方法用于检查一个类型是否可以转换到另一个类型。

    convert方法用于将一个对象转换到另一个类型。

    示例:

    @Service
    public class ExampleService {private final ConversionService conversionService;@Autowiredpublic ExampleService(ConversionService conversionService) {this.conversionService = conversionService;}public void doSomething(String input) {if (conversionService.canConvert(String.class, Integer.class)) {Integer output = conversionService.convert(input, Integer.class);System.out.println(output);} else {System.out.println("Cannot convert from String to Integer");}}}
    

    在这个示例中,ExampleService类包含一个doSomething方法,这个方法会将一个String对象转换到Integer对象。

🎷2. 使用ConversionService:

  • ConversionService可以在服务层或控制层使用。

    示例:

    @RestController
    public class ExampleController {private final ExampleService exampleService;@Autowiredpublic ExampleController(ExampleService exampleService) {this.exampleService = exampleService;}@GetMapping("/example")public ResponseEntity<?> getExample(@RequestParam String input) {exampleService.doSomething(input);return ResponseEntity.ok().build();}}
    

    在这个示例中,ExampleController类包含一个getExample方法,这个方法会调用ExampleServicedoSomething方法。

这是一个简单的Spring Boot应用程序示例,它包括类型转换的创建和使用。

注意:Spring Boot自动配置了一个ConversionService,它是DefaultConversionService的一个实例。因此,我们可以直接注入ConversionService,而不需要自定义一个ConversionService

另外,我们也可以自定义类型转换器。自定义类型转换器需要实现Converter接口。

示例:

public class StringToIntegerConverter implements Converter<String, Integer> {@Overridepublic Integer convert(String source) {return Integer.valueOf(source);}}

在这个示例中,我们创建了一个StringToIntegerConverter类,它实现了Converter接口。StringToIntegerConverter类定义了convert方法,这个方法会将一个String对象转换到Integer对象。

然后,我们可以将自定义的类型转换器添加到ConversionService

示例:

@Bean
public ConversionService conversionService() {DefaultConversionService conversionService = new DefaultConversionService();conversionService.addConverter(new StringToIntegerConverter());return conversionService;
}

在这个示例中,我们创建了一个ConversionServiceBean,并将StringToIntegerConverter添加到ConversionService

✍12. 表达式语言:

Spring Expression Language (SpEL) 是Spring框架的一个强大的表达式语言,它可以用于查询和操作对象图。

🎷1. SpEL表达式:

  • SpEL表达式是一个字符串,它可以包含字面量、属性、方法、数组、集合、索引器、运算符、变量、类型等。

    示例:

    String expression = "name == 'John Doe'";
    

    在这个示例中,expression是一个SpEL表达式,它比较name属性的值是否等于John Doe

🎷2. Expression接口:

  • Expression是一个接口,它定义了一些方法,用于解析和求值SpEL表达式。

    示例:

    ExpressionParser parser = new SpelExpressionParser();
    Expression expression = parser.parseExpression("name == 'John Doe'");
    

    在这个示例中,我们创建了一个SpelExpressionParser对象,并使用它的parseExpression方法解析SpEL表达式。

🎷3. 求值SpEL表达式:

  • SpEL表达式可以在一个上下文中求值。上下文可以是一个对象、一个数组、一个集合、一个字典等。

    示例:

    Person person = new Person();
    person.setName("John Doe");
    Boolean result = expression.getValue(person, Boolean.class);
    System.out.println(result);
    

    在这个示例中,我们创建了一个Person对象,并设置它的name属性。然后,我们使用ExpressiongetValue方法在Person对象的上下文中求值SpEL表达式。

这是一个简单的Spring Boot应用程序示例,它包括SpEL表达式的创建、解析和求值。

注意:SpEL也可以用于配置文件、注解、XML配置等。

示例:

@Value("#{systemProperties['java.home']}")
private String javaHome;

在这个示例中,我们使用@Value注解和SpEL表达式注入java.home系统属性的值。

另外,SpEL也可以用于@Query注解。

示例:

@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {@Query("select p from Person p where p.name = :#{#person.name}")List<Person> findByName(@Param("person") Person person);}

在这个示例中,我们使用@Query注解和SpEL表达式定义了一个查询方法。

✍13. 国际化:

Spring框架通过MessageSource接口支持国际化,这样应用程序可以根据不同的地区显示不同的消息。

🎷1. MessageSource接口:

  • MessageSource接口定义了几个方法来解析消息。最常用的是getMessage方法,它可以根据消息的键、参数和地区解析消息。

    示例:

    @Service
    public class ExampleService {private final MessageSource messageSource;@Autowiredpublic ExampleService(MessageSource messageSource) {this.messageSource = messageSource;}public void doSomething(Locale locale) {String message = messageSource.getMessage("example.message", null, locale);System.out.println(message);}}
    

    在这个示例中,ExampleService类有一个doSomething方法,该方法会解析example.message消息。

🎷2. 使用MessageSource:

  • MessageSource可以在服务层或控制层使用。

    示例:

    @RestController
    public class ExampleController {private final ExampleService exampleService;@Autowiredpublic ExampleController(ExampleService exampleService) {this.exampleService = exampleService;}@GetMapping("/example")public ResponseEntity<?> getExample(Locale locale) {exampleService.doSomething(locale);return ResponseEntity.ok().build();}}
    

    在这个示例中,ExampleController类有一个getExample方法,该方法会调用ExampleServicedoSomething方法。

这是一个简单的Spring Boot应用程序示例,它包括国际化的创建和使用。

注意:Spring Boot自动配置了一个MessageSource,它是ResourceBundleMessageSource的一个实例。因此,我们可以直接注入MessageSource,而不需要自定义一个MessageSource

另外,我们可以在application.propertiesapplication.yml文件中配置MessageSource的属性。

示例:

spring.messages.basename=messages
spring.messages.cache-duration=3600

在这个示例中,我们配置了MessageSourcebasename属性和cacheDuration属性。

basename属性是一个逗号分隔的列表,它包含了消息资源的基本名称。cacheDuration属性是消息资源的缓存持续时间,单位是秒。

另外,我们也可以在@Value注解中使用MessageSource

示例:

@Value("#{messageSource.getMessage('example.message', null, locale)}")
private String message;

在这个示例中,我们使用@Value注解和MessageSource注入example.message消息的值。

🎷3. 为什么要这样做?

国际化是软件开发的一个重要组成部分,它使得软件可以根据不同的地区显示不同的消息。这对于开发全球化的应用程序是非常重要的。

Spring框架通过MessageSource接口支持国际化,这样我们可以在应用程序中使用不同的消息资源,而不需要修改代码。

MessageSource接口提供了一个灵活的方式来解析消息。我们可以根据消息的键、参数和地区解析消息。这样,我们可以在一个地方管理所有的消息,而不需要在代码中硬编码消息。

此外,MessageSource接口也支持消息的参数化,这样我们可以在消息中插入动态的值。

总的来说,MessageSource接口提供了一个强大的方式来支持应用程序的国际化。

✌2. spring-beans:

Spring Beans 是 Spring 框架的核心组件。Beans 是 Spring IoC 容器中的对象。IoC(Inversion of Control)是一种编程思想,它将对象的创建、配置和管理交给了 IoC 容器,而不是传统的在代码中直接 new 一个对象。

🎷1. Bean 的定义

在 Spring 中,Bean 是由 Spring IoC 容器实例化、组装和管理的对象。除了应用程序对象之外,IoC 容器本身也是一个 Bean。Bean 是 Spring 的一个重要组成部分,它是 Spring 框架的基础。

🎷2. Bean 的配置

Bean 可以通过 XML 文件、注解、Java 配置类等方式进行配置。在 XML 文件中,可以使用 <bean> 标签来定义一个 Bean。例如:
xml <bean id="exampleBean" class="com.example.ExampleBean"/>
在这个例子中,id 是 Bean 的唯一标识符,class 是 Bean 的全限定类名。

🎷3. Bean 的作用域:Spring 支持以下五种作用域:

- Singleton:默认作用域,每个 Spring IoC 容器中只有一个 Bean 的实例。
- Prototype:每次请求都会创建一个新的 Bean 实例。
- Request:每次 HTTP 请求都会产生一个新的 Bean,该 Bean 仅在当前 HTTP request 内有效。
- Session:同一个 HTTP session 共享一个 Bean。
- Global session:全局 session 作用域,一般用于 portlet context。

🎷4. Bean 的生命周期:Bean 的生命周期包括以下几个步骤:

- 实例化:Spring IoC 容器创建 Bean 的实例。
- 填充属性:Spring IoC 容器通过依赖注入填充 Bean 的属性。
- 调用初始化方法:Spring IoC 容器调用 Bean 的初始化方法。
- Bean 可用:此时 Bean 已经准备好,可以被应用程序使用了。
- 调用销毁方法:当容器关闭时,Spring IoC 容器会调用 Bean 的销毁方法。

🎷5. 依赖注入

依赖注入是 Spring 框架的核心功能之一。它是一种设计模式,目的是减少代码之间的耦合。Spring IoC 容器负责将依赖关系注入到 Bean 中。

🎷6. Bean 的自动装配

Spring 可以自动装配 Bean 的属性。这意味着 Spring IoC 容器可以自动为 Bean 的属性、setter 方法、构造函数等注入依赖关系。

🎷7. 注解

Spring 提供了一系列的注解,例如 @Autowired, @Component, @Service, @Repository, @Controller 等,这些注解可以用来自动装配 Bean、定义 Bean 的作用域、生命周期等。

🎷8. Java 配置

除了 XML 配置外,Spring 还支持 Java 配置。可以使用 @Configuration@Bean 注解来配置 Bean。

✌3. spring-context:

spring-context模块扩展了spring-corespring-beans,提供了应用程序上下文和IOC容器。它支持国际化、资源加载、事件驱动编程、应用程序配置等功能。该模块也包含了ApplicationContext接口,用于管理和装配应用程序中的各种Bean。

当然,这里是每个点的作用和使用场景:

🎷1. ApplicationContext:

  • 作用:ApplicationContext 是 Spring 的 IoC 容器,它负责管理 Spring 应用中的 beans。
  • 使用场景:当你需要访问应用上下文,例如获取 beans、发布事件、访问资源等。
  • 示例:
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Component;@Component
    public class MyComponent implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}
    }
    

🎷2. 事件传播:

  • 作用:Spring 提供了一个强大的事件传播机制,你可以定义自己的事件、监听器和发布器。
  • 使用场景:当你需要在应用中传播事件,例如用户注册事件、订单支付事件等。
  • 示例:
    import org.springframework.context.ApplicationEvent;
    import org.springframework.context.ApplicationListener;
    import org.springframework.context.event.EventListener;
    import org.springframework.stereotype.Component;public class MyEvent extends ApplicationEvent {public MyEvent(Object source) {super(source);}
    }@Component
    public class MyEventListener implements ApplicationListener<MyEvent> {@Overridepublic void onApplicationEvent(MyEvent event) {System.out.println("Received: " + event);}
    }@Component
    public class MyEventPublisher {private final ApplicationContext applicationContext;public MyEventPublisher(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}public void publishEvent() {MyEvent event = new MyEvent(this);applicationContext.publishEvent(event);}
    }
    

🎷3. 资源加载:

  • 作用:Spring 提供了一个统一的资源加载抽象,你可以使用它来加载文件、类路径资源、URL 资源等。
  • 使用场景:当你需要加载资源,例如配置文件、图片、音频、视频等。
  • 示例:
    import org.springframework.context.ApplicationContext;
    import org.springframework.core.io.Resource;
    import org.springframework.stereotype.Component;import java.io.IOException;
    import java.io.InputStream;@Component
    public class MyResourceLoader {private final ApplicationContext applicationContext;public MyResourceLoader(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}public void loadResource(String location) throws IOException {Resource resource = applicationContext.getResource(location);try (InputStream inputStream = resource.getInputStream()) {// ...}}
    }
    

🎷4. 国际化:

  • 作用:Spring 提供了一个消息解析的抽象,你可以使用它来实现应用的国际化。
  • 使用场景:当你需要实现应用的国际化,例如显示不同语言的用户界面、发送不同语言的邮件等。
  • 示例:
    import org.springframework.context.MessageSource;
    import org.springframework.stereotype.Component;import java.util.Locale;@Component
    public class MyMessageSource {private final MessageSource messageSource;public MyMessageSource(MessageSource messageSource) {this.messageSource = messageSource;}public String getMessage(String code, Object[] args, Locale locale) {return messageSource.getMessage(code, args, locale);}
    }
    

🎷5. 任务调度:

  • 作用:Spring 提供了一个任务调度的抽象,你可以使用它来执行定时任务。
  • 使用场景:当你需要执行定时任务,例如每天凌晨备份数据库、每小时检查服务器的健康状态等。
  • 示例:
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;@Component
    public class MyScheduledTask {@Scheduled(fixedRate = 1000)public void run() {System.out.println("Running...");}
    }
    

🎷6. 访问 JNDI:

  • 作用:Spring 提供了一个 JNDI 访问的抽象,你可以使用它来访问 JNDI 资源。
  • 使用场景:当你需要访问 JNDI 资源,例如数据源、EJB、JMS 等。
  • 示例:
    import org.springframework.jndi.JndiTemplate;
    import org.springframework.stereotype.Component;import javax.naming.NamingException;@Component
    public class MyJndiAccessor {private final JndiTemplate jndiTemplate;public MyJndiAccessor(JndiTemplate jndiTemplate) {this.jndiTemplate = jndiTemplate;}public Object lookup(String name) throws NamingException {return jndiTemplate.lookup(name);}
    }
    

🎷7. 访问 EJB:

  • 作用:Spring 提供了一个 EJB 访问的抽象,你可以使用它来访问远程的 EJB。
  • 使用场景:当你需要访问远程的 EJB,例如调用远程的业务逻辑、获取远程的数据等。
  • 示例:
    import org.springframework.remoting.ejb.SimpleRemoteStatelessSessionProxyFactoryBean;
    import org.springframework.stereotype.Component;import javax.ejb.EJBHome;
    import javax.ejb.EJBObject;
    import java.rmi.RemoteException;@Component
    public class MyEjbAccessor {private final SimpleRemoteStatelessSessionProxyFactoryBean ejbProxyFactory;public MyEjbAccessor(SimpleRemoteStatelessSessionProxyFactoryBean ejbProxyFactory) {this.ejbProxyFactory = ejbProxyFactory;}public EJBObject create() throws RemoteException {EJBHome ejbHome = (EJBHome) ejbProxyFactory.getObject();return ejbHome.create();}
    }
    

🎷8. 远程访问:

  • 作用:Spring 提供了一个远程访问的抽象,你可以使用它来访问远程的服务。

  • 使用场景:当你需要访问远程的服务,例如调用远程的 REST API、访问远程的 RMI 服务等。

  • 示例:

    import org.springframework.remoting.rmi.RmiProxyFactoryBean;
    import org.springframework.stereotype.Component;@Component
    public class MyRmiClient {private final RmiProxyFactoryBean rmiProxyFactory;public MyRmiClient(RmiProxyFactoryBean rmiProxyFactory) {this.rmiProxyFactory = rmiProxyFactory;}public MyService getMyService() {return (MyService) rmiProxyFactory.getObject();}
    }public interface MyService {void doSomething();
    }
    

🎷9. 缓存抽象:

  • 作用:Spring 提供了一个缓存抽象,你可以使用它来缓存方法的结果。
  • 使用场景:当你需要缓存方法的结果,例如缓存数据库查询的结果、缓存远程服务的结果等。
  • 示例:
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.stereotype.Component;@Component
    public class MyService {@Cacheable("myCache")public String doSomething(String input) {return "Hello, " + input;}
    }
    

这些示例展示了如何在 Spring Boot 中使用 spring-context 的一些关键功能。这些示例可以作为你在 Spring Boot 中使用 spring-context 的起点。

✌4. spring-context-support:

spring-context-support模块提供了对特定环境(如Java EE)的支持,包括对JNDI查找、EJB访问、邮件发送等功能的集成。
spring-context-support 是 Spring 框架的一个模块,它提供了对第三方库的集成支持,例如缓存、邮件、调度、模板引擎等。

在 Spring Boot 中使用 spring-context-support 的一些关键点如下:

🎷1. 缓存支持:

  • 作用:Spring 提供了一个缓存抽象,它支持多种缓存库,例如 EhCache、Guava、JCache 等。
  • 使用场景:当你需要缓存方法的结果,例如缓存数据库查询的结果、缓存远程服务的结果等。
  • 示例:
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.stereotype.Component;@Component
    public class MyService {@Cacheable("myCache")public String doSomething(String input) {return "Hello, " + input;}
    }
    
    在这个示例中,MyService 类使用 @Cacheable 注解来缓存 doSomething 方法的结果。

🎷2. 邮件发送:

  • 作用:Spring 提供了一个邮件发送的抽象,你可以使用它来发送简单的邮件、附件邮件、富文本邮件等。
  • 使用场景:当你需要发送邮件,例如发送注册确认邮件、发送密码重置邮件、发送订单确认邮件等。
  • 示例:
    import org.springframework.mail.MailSender;
    import org.springframework.mail.SimpleMailMessage;
    import org.springframework.stereotype.Component;@Component
    public class MyMailSender {private final MailSender mailSender;public MyMailSender(MailSender mailSender) {this.mailSender = mailSender;}public void sendMail(String to, String subject, String text) {SimpleMailMessage message = new SimpleMailMessage();message.setTo(to);message.setSubject(subject);message.setText(text);mailSender.send(message);}
    }
    
    在这个示例中,MyMailSender 类使用 MailSender 来发送简单的邮件。

🎷3. 任务调度:

  • 作用:Spring 提供了一个任务调度的抽象,你可以使用它来执行定时任务。
  • 使用场景:当你需要执行定时任务,例如每天凌晨备份数据库、每小时检查服务器的健康状态等。
  • 示例:
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;@Component
    public class MyScheduledTask {@Scheduled(fixedRate = 1000)public void run() {System.out.println("Running...");}
    }
    
    在这个示例中,MyScheduledTask 类使用 @Scheduled 注解来定义一个定时任务。

🎷4. 模板引擎集成:

  • 作用:Spring 提供了对多种模板引擎的集成支持,例如 FreeMarker、Velocity、Thymeleaf 等。
  • 使用场景:当你需要渲染模板,例如渲染网页、渲染邮件正文、渲染报表等。
  • 示例:
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;@Controller
    public class MyController {@GetMapping("/hello")public String hello(Model model) {model.addAttribute("name", "World");return "hello";}
    }
    
    在这个示例中,MyController 类使用 @Controller 注解来定义一个控制器,hello 方法返回一个视图名,Spring 会使用配置的模板引擎来渲染这个视图。

这些示例展示了如何在 Spring Boot 中使用 spring-context-support 的一些关键功能。这些示例可以作为你在 Spring Boot 中使用 spring-context-support 的起点。

✌5. spring-expression:

spring-expression模块提供了Spring表达式语言(SpEL),用于在运行时进行属性的动态计算和值的查询。它支持在XML配置文件和注解中使用表达式。
spring-expression 模块,也称为 SpEL(Spring Expression Language),是 Spring 框架的一部分,它提供了一个强大的表达式语言,用于在运行时查询和操作对象图。

在 Spring Boot 中使用 spring-expression 的一些关键点如下:

🎷1. 基本使用:

  • 作用:SpEL 可以用于查询对象、调用方法、计算值等。
  • 使用场景:当你需要在运行时动态计算值、查询对象、调用方法等。
  • 示例:
    import org.springframework.expression.ExpressionParser;
    import org.springframework.expression.spel.standard.SpelExpressionParser;
    import org.springframework.stereotype.Component;@Component
    public class MySpelEvaluator {private final ExpressionParser parser = new SpelExpressionParser();public Object evaluate(String expression) {return parser.parseExpression(expression).getValue();}
    }
    
    在这个示例中,MySpelEvaluator 类使用 SpelExpressionParser 来解析和计算 SpEL 表达式。

🎷2. 集合选择:

  • 作用:SpEL 提供了一种简洁的语法来从集合中选择元素。
  • 使用场景:当你需要从集合中选择元素,例如从列表中选择满足条件的元素、从映射中选择满足条件的键值对等。
  • 示例:
    import org.springframework.expression.ExpressionParser;
    import org.springframework.expression.spel.standard.SpelExpressionParser;
    import org.springframework.stereotype.Component;import java.util.List;
    import java.util.Map;@Component
    public class MySpelEvaluator {private final ExpressionParser parser = new SpelExpressionParser();public List<?> selectFromList(List<?> list, String expression) {return (List<?>) parser.parseExpression(expression).getValue(list);}public Map<?, ?> selectFromMap(Map<?, ?> map, String expression) {return (Map<?, ?>) parser.parseExpression(expression).getValue(map);}
    }
    
    在这个示例中,MySpelEvaluator 类使用 SpelExpressionParser 来从列表和映射中选择元素。

🎷3. 方法调用:

  • 作用:SpEL 提供了一种简洁的语法来调用方法。
  • 使用场景:当你需要在运行时动态调用方法,例如调用对象的方法、调用静态方法等。
  • 示例:
    import org.springframework.expression.ExpressionParser;
    import org.springframework.expression.spel.standard.SpelExpressionParser;
    import org.springframework.stereotype.Component;@Component
    public class MySpelEvaluator {private final ExpressionParser parser = new SpelExpressionParser();public Object callMethod(Object root, String expression) {return parser.parseExpression(expression).getValue(root);}
    }
    
    在这个示例中,MySpelEvaluator 类使用 SpelExpressionParser 来调用方法。
  1. 属性访问:
    • 作用:SpEL 提供了一种简洁的语法来访问属性。
    • 使用场景:当你需要在运行时动态访问属性,例如访问对象的属性、访问映射的键值对等。
    • 示例:
      import org.springframework.expression.ExpressionParser;
      import org.springframework.expression.spel.standard.SpelExpressionParser;
      import org.springframework.stereotype.Component;@Component
      public class MySpelEvaluator {private final ExpressionParser parser = new SpelExpressionParser();public Object accessProperty(Object root, String expression) {return parser.parseExpression(expression).getValue(root);}
      }
      
      在这个示例中,MySpelEvaluator 类使用 SpelExpressionParser 来访问属性。

这些示例展示了如何在 Spring Boot 中使用 spring-expression 的一些关键功能。这些示例可以作为你在 Spring Boot 中使用 spring-expression 的起点。

✌6. spring-aop:

spring-aop 模块是 Spring 框架的一部分,它提供了面向切面编程(AOP)的功能。AOP 是一种编程范式,它允许你定义“切面”,这些切面可以插入到对象的方法调用中。

在 Spring Boot 中使用 spring-aop 的一些关键点如下:

🎷1. 定义切面:

  • 作用:你可以定义一个切面,这个切面包含了一组通知和一个切点。
  • 使用场景:当你需要在方法调用的前后插入代码,例如记录日志、事务管理、权限检查等。
  • 示例:
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.stereotype.Component;@Aspect
    @Component
    public class MyAspect {@Before("execution(* com.example.MyService.*(..))")public void before() {System.out.println("Before method execution");}
    }
    
    在这个示例中,MyAspect 类使用 @Aspect 注解来定义一个切面,before 方法使用 @Before 注解来定义一个前置通知。

🎷2. 定义通知:

  • 作用:你可以定义不同类型的通知,例如前置通知、后置通知、返回通知、异常通知、环绕通知等。
  • 使用场景:当你需要在方法调用的不同阶段插入代码,例如在方法调用前、方法调用后、方法返回、方法抛出异常等。
  • 示例:
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.springframework.stereotype.Component;@Aspect
    @Component
    public class MyAspect {@After("execution(* com.example.MyService.*(..))")public void after() {System.out.println("After method execution");}@AfterReturning("execution(* com.example.MyService.*(..))")public void afterReturning() {System.out.println("After method returning");}@AfterThrowing("execution(* com.example.MyService.*(..))")public void afterThrowing() {System.out.println("After method throwing");}@Around("execution(* com.example.MyService.*(..))")public Object around(ProceedingJoinPoint pjp) throws Throwable {System.out.println("Before method execution");Object result = pjp.proceed();System.out.println("After method execution");return result;}
    }
    
    在这个示例中,MyAspect 类定义了四个通知:after 方法是一个后置通知,afterReturning 方法是一个返回通知,afterThrowing 方法是一个异常通知,around 方法是一个环绕通知。

🎷3. 定义切点:

  • 作用:你可以定义一个切点,这个切点确定了通知应该应用到哪些方法上。
  • 使用场景:当你需要精确控制通知应该应用到哪些方法上,例如应用到所有的服务方法上、应用到所有的存储库方法上等。
  • 示例:
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;@Aspect
    @Component
    public class MyAspect {@Pointcut("execution(* com.example.MyService.*(..))")public void myPointcut() {}@Before("myPointcut()")public void before() {System.out.println("Before method execution");}
    }
    
    在这个示例中,MyAspect 类使用 @Pointcut 注解来定义一个切点,before 方法使用 @Before 注解来定义一个前置通知。

这些示例展示了如何在 Spring Boot 中使用 spring-aop 的一些关键功能。这些示例可以作为你在 Spring Boot 中使用 spring-aop 的起点。

✌7. spring-aspects:

spring-aspects模块提供了使用AspectJ实现的Spring方面库,用于更强大和灵活的AOP功能。
在 Spring Boot 中使用 spring-aspects 主要是为了集成 Spring 的面向切面编程(AOP)功能。AOP 是一种编程范式,允许你在不改变业务逻辑的情况下,通过将横切关注点(如日志记录、安全性、事务管理等)从主要业务逻辑中分离出来,从而提高代码的模块性和可维护性。spring-aspects 模块是 Spring Framework 提供的一个模块,它帮助你将 AOP 功能集成到 Spring 应用中。

以下是在 Spring Boot 中使用 spring-aspects 的步骤:

🎷1. 添加依赖:在项目的 Maven 或 Gradle 构建文件中,添加对 spring-aspects 模块的依赖。

Maven 依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Gradle 依赖:

implementation 'org.springframework.boot:spring-boot-starter-aop'

🎷2. 创建切面类:

定义一个类作为切面,其中包含定义切入点和通知(Advice)的代码。通知是在切入点处执行的代码,比如 @Before@After@Around 等。

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Aspect
@Component
public class MyAspect {@Before("execution(* com.example.demo.service.*.*(..))")public void beforeAdvice() {System.out.println("Before method execution");}
}

🎷3. 启用切面:

在 Spring Boot 应用的主类上添加 @EnableAspectJAutoProxy 注解,启用自动代理功能,使切面生效。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@SpringBootApplication
@EnableAspectJAutoProxy
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}

现在,MyAspect 中定义的切面将会在 com.example.demo.service 包下的方法执行之前执行。

区别 between spring-aspects 和 AOP:

  1. spring-aspects 是 Spring 框架提供的模块:它是 Spring 框架中用于集成 AOP 功能的一部分。它使用 AspectJ 来实现 AOP 的各种功能。

  2. AOP 是编程范式:AOP 是一种编程范式,可以用于任何支持该范式的编程语言和框架。spring-aspects 是 Spring 框架特定的实现,用于将 AOP 集成到 Spring 应用中。

  3. AspectJ 支持更强大的切面功能:AspectJ 是一个独立的 AOP 框架,它比 Spring AOP 提供了更多的切面功能。如果你需要更高级的 AOP 功能,可以直接使用 AspectJ。

  4. Spring AOP 是运行时代理:Spring AOP 通过运行时代理实现切面。它主要使用 JDK 动态代理和 CGLIB 来创建代理对象。AspectJ 则可以进行更细粒度的静态织入,但需要在编译时进行额外的处理。

综上所述,spring-aspects 是 Spring 框架中用于集成 AOP 功能的模块,它使用 AspectJ 实现 AOP。AOP 是一种编程范式,可以用于任何支持该范式的环境。AspectJ 提供更多功能,而 Spring AOP 则更简单并且与 Spring 框架集成得更紧密。

✌8. spring-jdbc:

spring-jdbc模块提供了JDBC访问和错误处理的支持。它简化了JDBC的使用,提供了异常处理、事务管理和连接池等功能。
在 Spring Boot 中使用 spring-jdbc 模块,你可以轻松地进行数据库操作,包括连接管理、SQL 查询和更新等。spring-jdbc 提供了一种简化和抽象的方式来访问关系型数据库,以及处理与数据库相关的操作。以下是在 Spring Boot 中使用 spring-jdbc 的详细步骤:

🎷1. 添加依赖:

在项目的 Maven 或 Gradle 构建文件中,添加对 spring-boot-starter-jdbc 模块的依赖。

Maven 依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

Gradle 依赖:

implementation 'org.springframework.boot:spring-boot-starter-jdbc'

🎷2. 配置数据源:

application.propertiesapplication.yml 文件中配置数据库连接信息,如数据库 URL、用户名、密码等。

spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

🎷3. 创建 DAO(数据访问对象):

编写数据库访问相关的代码。可以使用 Spring 的 JdbcTemplate 类来执行 SQL 查询和更新。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;@Repository
public class UserDao {private final JdbcTemplate jdbcTemplate;@Autowiredpublic UserDao(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}public String findUserNameById(int userId) {String sql = "SELECT username FROM users WHERE id = ?";return jdbcTemplate.queryForObject(sql, String.class, userId);}public void insertUser(String username, String email) {String sql = "INSERT INTO users (username, email) VALUES (?, ?)";jdbcTemplate.update(sql, username, email);}
}

🎷4. 使用 DAO:在服务类或控制器中使用 DAO 类进行数据库操作。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {private final UserDao userDao;@Autowiredpublic UserService(UserDao userDao) {this.userDao = userDao;}public String getUsernameById(int userId) {return userDao.findUserNameById(userId);}public void createUser(String username, String email) {userDao.insertUser(username, email);}
}

🎷5. 在主类中启动应用:

在 Spring Boot 的主类中添加 @SpringBootApplication 注解,启动应用。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}

通过以上步骤,你就可以在 Spring Boot 中使用 spring-jdbc 模块来进行数据库操作了。JdbcTemplate 提供了许多便利的方法来执行 SQL 查询和更新,同时还支持参数绑定、结果映射等功能,从而简化了数据库操作的流程。

✌9. spring-tx:

当使用 spring-tx 模块进行事务管理时,有几个核心的功能和用法,以及相应的使用场景。以下是不同的事务管理功能、其作用、使用场景以及可能出现问题的情况:

🎷1. 声明式事务管理(@Transactional 注解)

  • 作用:允许你通过注解声明事务的范围,从而自动管理事务的开始、提交、回滚等操作,将事务和业务逻辑解耦。

  • 使用场景:适用于简单的事务场景,例如在服务层的方法上添加 @Transactional 注解来实现事务管理。

  • 示例

    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;@Service
    public class UserService {@Transactionalpublic void transferFunds(int fromAccountId, int toAccountId, double amount) {// Perform fund transfer}
    }
    
  • 问题和注意事项:在一个方法内部多次调用被 @Transactional 注解标记的其他方法时,事务可能无法正常工作。这是因为 Spring 默认会使用代理来实现事务管理。在这种情况下,要么将被调用的方法提取到一个独立的类中,要么使用 self-invocation 属性解决问题。

🎷2. 编程式事务管理(PlatformTransactionManager 接口)

  • 作用:允许你在代码中手动管理事务,提供更细粒度的控制。

  • 使用场景:适用于需要更多控制的复杂事务场景,例如多个方法需要在同一个事务内执行。

  • 示例

    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.TransactionStatus;
    import org.springframework.transaction.support.DefaultTransactionDefinition;
    import org.springframework.stereotype.Service;@Service
    public class UserService {private final PlatformTransactionManager transactionManager;public UserService(PlatformTransactionManager transactionManager) {this.transactionManager = transactionManager;}public void transferFunds(int fromAccountId, int toAccountId, double amount) {TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());try {// Perform fund transfertransactionManager.commit(status);} catch (Exception e) {transactionManager.rollback(status);}}
    }
    
  • 问题和注意事项:编程式事务需要手动处理事务的开始、提交、回滚等操作,可能导致遗漏或错误。此外,如果在事务内发生了未捕获的异常,事务可能不会回滚。

🎷3. 事务传播行为(Propagation)

  • 作用:定义了事务方法在被其他事务方法调用时,如何处理事务。

  • 使用场景:适用于有多个方法相互调用,需要管理不同事务传播行为的场景。

  • 示例

    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.stereotype.Service;@Service
    public class UserService {@Transactional(propagation = Propagation.REQUIRED)public void transferFunds(int fromAccountId, int toAccountId, double amount) {// Perform fund transfer}
    }
    
  • 问题和注意事项:不同的传播行为可能会导致事务的不同状态,例如 REQUIRES_NEW 可能会导致新事务的创建,而 REQUIRED 则会加入当前事务。

🎷4. 事务隔离级别(Isolation)

  • 作用:定义了事务之间的隔离程度,以避免并发操作引起的数据问题。

  • 使用场景:在多线程或并发访问的环境下,需要控制事务隔离级别的场景。

  • 示例

    import org.springframework.transaction.annotation.Isolation;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.stereotype.Service;@Service
    public class UserService {@Transactional(isolation = Isolation.READ_COMMITTED)public void updateAccountBalance(int accountId, double newBalance) {// Update account balance}
    }
    
  • 问题和注意事项:较高的隔离级别可能会导致性能降低,应根据实际需要选择合适的隔离级别。

🎷5. 事务超时(Timeout)

  • 作用:定义事务在超过指定时间后自动回滚,以防止事务长时间占用资源。

  • 使用场景:适用于需要限制事务执行时间的场景,避免资源占用。

  • 示例

    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.stereotype.Service;@Service
    public class UserService {@Transactional(timeout = 5) // Timeout in secondspublic void performCriticalOperation() {// Perform critical operation}}
    
  • 问题和注意事项:设置过小的超时时间可能导致事务无法完成,而设置过大的超时时间可能导致资源浪费。

在使用 spring-tx 进行事务管理时,可能会出现以下问题:

  • 脏读(Dirty Read):一个事务读取了另一个事务尚未提交的数据,如果另一个事务回滚,读取的数据就是无效的。

  • 不可重复读(Non-repeatable Read):一个事务在多次读取同一数据时,由于其他事务修改了该数据,读取结果不一致。

  • 幻读(Phantom Read):一个事务在读取一系列数据时,其他事务插入了新的数据,导致读取结果不一致。

  • 死锁(Deadlock):多个事务相互等待对方释放资源,造成无法继续进行的情况。

✌10. spring-orm:

spring-orm模块提供了对对象关系映射(ORM)框架的集成支持,如Hibernate、JPA、JDO等。
在 Spring Boot 中使用 spring-orm 模块,你可以集成和使用不同的持久化技术,主要包括 Hibernate 和 JPA(Java Persistence API)。这个模块使得在 Spring Boot 应用中管理持久化数据变得更加简便。下面将详细解释如何在 Spring Boot 中使用 spring-orm 模块,以及其中涉及的核心功能和用法。

🎷1. 配置数据源:

application.propertiesapplication.yml 配置文件中设置数据库连接信息,如数据库URL、用户名、密码等。

spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

🎷2. 引入依赖:

在 Maven 或 Gradle 构建配置中,引入 spring-boot-starter-data-jpaspring-boot-starter-data-jpa 依赖,它们包含了 spring-orm 模块。

Maven:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

Gradle:

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

🎷3. 创建实体类:

创建与数据库表对应的实体类,使用 JPA 注解来映射实体属性和数据库表结构。

import javax.persistence.*;@Entity
@Table(name = "users")
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(name = "username")private String username;@Column(name = "email")private String email;// Getter and setter methods
}

🎷4. 创建 Repository 接口:

创建一个继承自 JpaRepository 的接口,该接口提供了一组内置的 CRUD 操作方法。

import org.springframework.data.jpa.repository.JpaRepository;public interface UserRepository extends JpaRepository<User, Long> {// Custom query methods, if needed
}

🎷5. 使用 Repository:

在服务层或控制层中使用自动生成的 Repository 接口,执行数据持久化操作。

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {private final UserRepository userRepository;public UserService(UserRepository userRepository) {this.userRepository = userRepository;}@Transactionalpublic User createUser(User user) {return userRepository.save(user);}@Transactionalpublic User updateUser(User user) {return userRepository.save(user);}@Transactional(readOnly = true)public User getUserById(Long userId) {return userRepository.findById(userId).orElse(null);}@Transactionalpublic void deleteUser(Long userId) {userRepository.deleteById(userId);}
}

🎷6. 配置 JPA 属性:

application.propertiesapplication.yml 中,可以配置 JPA 相关属性,如显示 SQL、DDL 自动创建等。

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update

以上是在 Spring Boot 中使用 spring-orm 模块的基本步骤。它将帮助你更轻松地集成和操作数据库,同时利用 Spring Boot 的自动配置和简化开发流程的特性。

注意:在实际应用中,你可以根据需要选择 Hibernate、JPA 或其他持久化技术,然后进行相应的配置和代码编写。

✌11. spring-web:

spring-web模块提供了基本的Web支持,包括上传文件、MVC(Model-View-Controller)架构、HTTP请求和响应等功能。

在 Spring Boot 中使用 spring-web 模块,可以构建和开发 Web 应用程序,实现控制器、处理请求、视图解析等功能。spring-web 模块为开发 Web 应用提供了基础架构,包括处理 HTTP 请求、响应、路由、视图渲染等功能。以下是在 Spring Boot 中使用 spring-web 模块的详细步骤、作用和使用场景。

🎷1. 引入依赖:

在 Maven 或 Gradle 构建配置中,引入 spring-boot-starter-web 依赖,它包含了 spring-web 相关的组件和配置。

Maven:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

Gradle:

implementation 'org.springframework.boot:spring-boot-starter-web'

🎷2. 创建控制器:

创建控制器类,处理来自客户端的 HTTP 请求,并返回相应的数据或视图。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class HelloWorldController {@GetMapping("/hello")public String sayHello() {return "Hello, Spring Boot!";}
}

🎷3. 运行应用:

使用 Spring Boot 的自动配置和嵌入式 Web 服务器,可以直接运行应用程序。启动应用后,控制器的映射将会生效。

🎷4. 处理请求:

当客户端发送 HTTP 请求到指定的 URL 时,控制器将根据映射的方法处理请求,并返回响应数据。

🎷5. 视图解析:

使用 ThymeleafJSP 等模板引擎,可以将控制器处理的数据渲染成 HTML 视图。

🎷6. 处理静态资源:

spring-web 模块还能处理静态资源,如 CSS、JavaScript、图片等,使这些资源能够被客户端请求到。

🎷7. 作用和使用场景

  • 构建 Web 应用: 通过创建控制器和处理请求,可以构建功能完整的 Web 应用程序,用于展示数据、接受用户输入等。

  • RESTful API: 使用 @RestController@RequestMapping 注解,可以构建 RESTful 风格的 API,处理客户端的 API 请求和响应。

  • 视图渲染: 使用模板引擎(如 Thymeleaf、FreeMarker、JSP 等)将控制器处理的数据渲染成 HTML 视图,用于前端展示。

  • 静态资源管理: 可以通过 spring-web 处理静态资源,使得静态文件(如 CSS、JavaScript、图片)能够被客户端访问。

  • 国际化和本地化: spring-web 提供了国际化和本地化的支持,使得 Web 应用可以根据用户的地区或语言显示不同的内容。

  • 异常处理: 可以通过异常处理机制来捕获和处理在控制器中发生的异常,返回适当的错误信息给客户端。

总之,spring-web 模块为开发 Web 应用程序提供了必要的基础设施,能够帮助你构建和管理各种类型的 Web 应用,从简单的页面到复杂的 RESTful API。在 Spring Boot 中使用该模块,可以更加高效地进行 Web 开发。

✌12. spring-webmvc:

在 Spring Boot 中使用 spring-webmvc 模块,你可以构建和开发基于 Model-View-Controller (MVC) 设计模式的 Web 应用程序。spring-webmvc 模块为开发 Web 应用提供了丰富的功能,包括控制器、视图解析、请求映射、表单处理等。以下是在 Spring Boot 中使用 spring-webmvc 模块的详细步骤、作用和使用场景。

🎷1. 引入依赖:

在 Maven 或 Gradle 构建配置中,引入 spring-boot-starter-web 依赖,它包含了 spring-webmvc 相关的组件和配置。

Maven:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

Gradle:

implementation 'org.springframework.boot:spring-boot-starter-web'

🎷2. 创建控制器:

创建控制器类,处理来自客户端的 HTTP 请求,并返回相应的数据或视图。

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;@Controller
public class GreetingController {@GetMapping("/greeting")public String greeting(@RequestParam(name = "name", required = false, defaultValue = "World") String name, Model model) {model.addAttribute("name", name);return "greeting";}
}

🎷3. 创建视图模板:

使用模板引擎(如 Thymeleaf、FreeMarker、JSP 等)创建视图模板,将控制器处理的数据渲染成 HTML 视图。

🎷4. 运行应用:

使用 Spring Boot 的自动配置和嵌入式 Web 服务器,可以直接运行应用程序。启动应用后,控制器的映射将会生效。

🎷5. 处理请求:

当客户端发送 HTTP 请求到指定的 URL 时,控制器将根据映射的方法处理请求,并返回响应数据。

🎷6. 表单处理:

使用 @RequestParam@ModelAttribute 等注解来处理表单提交数据,进行数据绑定和验证。

🎷7. 视图解析:

使用模板引擎解析控制器处理的数据,将其渲染成 HTML 视图,返回给客户端。

🎷8. 静态资源管理:

spring-webmvc 模块能够处理静态资源,使得静态文件(如 CSS、JavaScript、图片)能够被客户端访问。

🎷9. 作用和使用场景

  • MVC 架构: 使用 spring-webmvc 模块构建基于 MVC 设计模式的 Web 应用,将业务逻辑、数据展示和用户交互分离。

  • 视图渲染: 使用模板引擎将控制器处理的数据渲染成 HTML 视图,用于前端页面展示。

  • 表单处理: 使用注解和工具来处理表单提交的数据,进行数据绑定、验证和处理。

  • RESTful API: 使用 @RestController 注解和 @RequestMapping 注解构建 RESTful 风格的 API,处理客户端的 API 请求和响应。

  • 国际化和本地化: spring-webmvc 提供了国际化和本地化的支持,使得 Web 应用可以根据用户的地区或语言显示不同的内容。

  • 异常处理: 可以通过异常处理机制来捕获和处理在控制器中发生的异常,返回适当的错误信息给客户端。

总之,spring-webmvc 模块为开发 Web 应用程序提供了丰富的功能和基础设施,能够帮助你构建和管理各种类型的 Web 应用,从传统的页面应用到 RESTful API。在 Spring Boot 中使用该模块,可以更加高效地进行 Web 开发。

✌13. spring-websocket:

当在 Spring Boot 中使用 spring-websocket 模块,你可以简单地集成 WebSocket 技术,实现双向通信和实时消息传递。WebSocket 是一种在客户端和服务器之间建立持久性连接的通信协议,适用于需要实时更新的应用场景,如聊天应用、实时通知等。

以下是在 Spring Boot 中使用 spring-websocket 模块的详细步骤,包含注释和示例代码:

🎷1. 引入依赖:

在 Maven 或 Gradle 构建配置中,引入 spring-boot-starter-websocket 依赖,它包含了 spring-websocket 相关的组件和配置。

Maven:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

Gradle:

implementation 'org.springframework.boot:spring-boot-starter-websocket'

🎷2. 创建 WebSocket 配置类:

创建一个配置类,继承 WebSocketMessageBrokerConfigurer 接口,配置 WebSocket 相关参数和消息处理。

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {// 配置消息代理,指定消息的目的地前缀@Overridepublic void configureMessageBroker(MessageBrokerRegistry config) {config.enableSimpleBroker("/topic");config.setApplicationDestinationPrefixes("/app");}// 注册 Stomp 协议的 WebSocket 端点,使用 SockJS 支持@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {registry.addEndpoint("/websocket").withSockJS();}
}

🎷3. 创建消息处理器:

创建消息处理器类,处理客户端发送的消息并发送响应消息。

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;@Controller
public class WebSocketController {// 监听客户端发送的消息,并发送响应消息到特定的目的地@MessageMapping("/hello")@SendTo("/topic/greetings")public Greeting greeting(HelloMessage message) throws Exception {Thread.sleep(1000); // 模拟延迟return new Greeting("Hello, " + message.getName() + "!");}
}

🎷4. 创建前端页面:

创建前端页面,使用 JavaScript 或其他适当的库连接到 WebSocket 服务器,接收和发送消息。

示例 HTML 文件(使用 SockJS 和 STOMP):

<!DOCTYPE html>
<html>
<head><title>WebSocket Example</title><script src="/webjars/sockjs-client/sockjs.min.js"></script><script src="/webjars/stomp-websocket/stomp.min.js"></script>
</head>
<body><script>var stompClient = null;function connect() {var socket = new SockJS('/websocket');stompClient = Stomp.over(socket);stompClient.connect({}, function(frame) {console.log('Connected: ' + frame);stompClient.subscribe('/topic/greetings', function(greeting) {showMessage(JSON.parse(greeting.body).content);});});}function showMessage(message) {var p = document.createElement('p');p.appendChild(document.createTextNode(message));document.getElementById('output').appendChild(p);}function sendName() {var name = document.getElementById('name').value;stompClient.send("/app/hello", {}, JSON.stringify({ 'name': name }));}window.onload = function() {connect();};</script><input type="text" id="name" placeholder="Your Name"><button onclick="sendName()">Send</button><div id="output"></div>
</body>
</html>

🎷5. 运行应用:

使用 Spring Boot 的自动配置和嵌入式 Web 服务器,可以直接运行应用程序。启动应用后,WebSocket 配置将会生效。

🎷6. 前端交互:

前端页面可以使用 WebSocket 客户端库与服务器建立连接,接收和发送消息。

通过 spring-websocket 模块,你可以轻松地在 Spring Boot 应用中集成 WebSocket 技术,实现双向通信和实时消息传递的功能。这对于构建实时通知、聊天应用、实时数据更新等场景非常有用。

👀从springboot将Spring的核心模块

当使用Spring Boot时,您实际上是在构建基于Spring Framework的应用程序,并且Spring Boot在很大程度上简化了配置和部署过程。Spring Boot集成了Spring Framework的核心模块,同时还提供了一些自动配置和约定,使得开发过程更加快速和便捷。下面是Spring Framework的核心模块如何结合Spring Boot的全面解析:

🎷1. spring-core和spring-beans:

这两个模块提供了Spring Framework的基础,用于依赖注入和控制反转。Spring Boot继承了这两个模块,使得您无需手动配置Bean的装配和依赖注入。通过@Component@Autowired等注解,Spring Boot会自动扫描和装配Bean,简化了开发过程。

🎷2. spring-context和spring-context-support:

这两个模块提供了应用程序上下文、国际化、资源加载等功能。Spring Boot中的应用程序上下文是内嵌的,可以自动扫描和加载应用程序中的Bean。Spring Boot还集成了国际化支持,可以根据用户的语言环境加载相应的资源。

🎷3. spring-aop和spring-aspects:

Spring Boot支持AOP,允许您通过切面和通知实现横切关注点的模块化。您可以使用@Aspect注解定义切面,将通知应用于特定的Bean方法。

🎷4. spring-jdbc、spring-tx和spring-orm:

这些模块提供了数据库访问和事务管理的支持。Spring Boot在数据源的配置方面提供了自动化,您只需在配置文件中配置数据库相关属性,Spring Boot会自动配置数据源和事务管理。

🎷5. spring-web和spring-webmvc:

Spring Boot支持Web应用程序开发,包括基本的Web支持、MVC框架和Web Socket支持。通过@Controller@RestController等注解,您可以定义Web控制器,Spring Boot会自动创建和管理这些控制器。

🎷6. spring-websocket:

Spring Boot还支持WebSocket协议,用于实现实时通信。您可以使用@EnableWebSocket注解来启用WebSocket支持。

综上所述,Spring Boot在构建应用程序时集成了Spring Framework的核心模块,并通过自动配置和约定使得开发过程更加简单。您可以专注于业务逻辑的开发,而无需过多关注繁琐的配置细节。Spring Boot的目标是减少样板代码,提供快速、灵活和易于维护的开发体验。

相关文章:

Springboot - 1.什么是springboot

&#x1f440;Spring的核心模块 Spring Framework是一个功能强大的开源框架&#xff0c;用于构建Java企业级应用程序。它提供了多个核心模块&#xff0c;每个模块都提供不同的功能&#xff0c;用于解决应用程序开发中的各种问题。以下是Spring Framework的核心模块的全面解析&…...

学习微信小程序 Westore

最近&#xff0c;接到小程序需求&#xff0c;并且是在以前公司老项目上改造&#xff0c;打开项目&#xff0c;发现却不是我想象中的那样&#xff0c;不是上来就是 Page({})&#xff0c;而是create(store,{})&#xff0c;纳尼&#xff1f;&#xff1f;&#xff1f;这什么玩意&am…...

CentOS上使用Docker安装和部署kkFileView

&#x1f388;1 参考文档 kkFileView官方文档 &#x1f680;2 安装kkFileView 拉取Redis镜像。 docker pull keking/kkfileview启动docker容器。 docker run -it -d -p 8012:8012 keking/kkfileview --restart always解释&#xff1a; docker run redis # 从kkfileview镜像运行…...

Level-based Foraging 多智能体游戏仿真环境

游戏场景测试 参考链接&#xff1a; https://kgithub.com/semitable/lb-foraging...

LeetCode-53-最大子数组和-贪心算法

贪心算法理论基础&#xff1a; 局部最优推全局最优 贪心无套路~ 没有什么规律~ 重点&#xff1a;每个阶段的局部最优是什么&#xff1f; 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#…...

解决gitee仓库中 .git 文件夹过大的问题

最近&#xff0c;许多项目都迁移到gitee。使用的也越来越频繁&#xff0c;但是今天突然收到一个仓库爆满的提示。让我一脸懵逼。本文将详细为你解答&#xff0c;这种情况如何处理。 1、起因 我收到的报错如下&#xff1a; remote: Powered by GITEE.COM [GNK-6.4] remote: T…...

uniapp 开发小程序,封装一个方法,让图片使用线上地址

1.在main.js文件中&#xff0c;添加以下代码&#xff1a; 复制使用&#xff1a; // 图片使用网络地址 Vue.prototype.localImgSrc function(img){//项目的地址域名&#xff0c;例如百度return "https://baidu.cn/static/index/images/" img; }2.在页面中直接使用&…...

Android 12 源码分析 —— 应用层 三(SystemUIFactory及其Dependency解析)

Android 12 源码分析 —— 应用层 三&#xff08;SystemUIFactory及其Dependency解析&#xff09; 在上一篇文章中&#xff0c;介绍了SystemUI的启动流程&#xff0c;并且简单提及了Dagger2用来管理各个SystemUI中要用的依赖。而这部分代码就在&#xff1a;mContextAvailableC…...

考前冲刺上岸浙工商MBA的备考经验分享

2023年对于许多人来说都是不平凡的一年&#xff0c;历经三年的抗争&#xff0c;我们终于成功结束了疫情。而我也很幸运的被浙工商MBA项目录取&#xff0c;即将开始全新的学习生活。身为一名已在职工作6年的人&#xff0c;能够重回校园真是一种特别令人激动的体验。今天&#xf…...

XmlDocument.SelectNodes 不起作用

今天采用Xpath读取Xml节点&#xff0c;怎么都读不出。 问题分析&#xff1a; 错误代码如下&#xff1a; XmlDocument xmlD new XmlDocument();xmlD.PreserveWhitespace true;xmlD.LoadXml(xStr);xmlD.SelectNodes("job-scheduling-data/schedule/job");经排查 do…...

部署单点elasticsearch

部署elasticsearch 创建网络 因为我们还需要部署kibana容器&#xff0c;因此需要让es和kibana容器互联。这里先创建一个网络 docker network create es-net 拉取镜像 我们采用elasticsearch的7.12.1版本的镜像 docker pull elasticsearch:7.12.1 运行 运行docker命令&a…...

ElementUI浅尝辄止16:Tag 标签

用于标记和选择。 1.如何使用&#xff1f; 由type属性来选择tag的类型&#xff0c;也可以通过color属性来自定义背景色。<el-tag>标签一</el-tag> <el-tag type"success">标签二</el-tag> <el-tag type"info">标签三</e…...

Java虚拟机(JVM)框架

见&#xff1a;GitHub - eHackyd/Java_JVM: Java虚拟机(JVM)框架的学习笔记...

配置Publisher 的编译规则

步骤 1&#xff1a;创建ROS Package 使用以下命令创建一个新的ROS软件包&#xff1a; catkin_create_pkg my_publisher_package roscpp std_msgs步骤 2&#xff1a;编辑 CMakeLists.txt 文件 打开您的ROS软件包的 CMakeLists.txt 文件&#xff0c;通常位于软件包的根目录。您…...

【SpringBoot】接口实现:SpringBoot实现博客系统的文章列表页接口代码

以下是一个简单的Spring Boot博客系统的文章列表页接口代码示例&#xff1a; java RestController RequestMapping("/articles") public class ArticleController {Autowiredprivate ArticleService articleService;GetMapping("/")public List<Artic…...

如何使用SQL系列 之 如何在SQL中插入数据

简介 结构化查询语言&#xff0c;通常被称为SQL&#xff0c;在允许您将数据插入表中方面提供了极大的灵活性。例如&#xff0c;你可以使用VALUES关键字指定单独的行数据&#xff0c;使用SELECT查询从现有表中复制整组数据&#xff0c;以及以使SQL自动插入数据的方式定义列。 …...

【LeetCode题目详解】1281题 整数的各位积和之差 面试题 01.01. 判定字符是否唯一 python题解(作业一二)

本文章以python为例! 一、力扣第1281题&#xff1a;整数的各位积和之差 问题描述&#xff1a; 1281. 整数的各位积和之差 给你一个整数 n&#xff0c;请你帮忙计算并返回该整数「各位数字之积」与「各位数字之和」的差。 示例 1&#xff1a; 输入&#xff1a;n 234 输出…...

1.12 进程注入ShellCode套接字

在笔者前几篇文章中我们一直在探讨如何利用Metasploit这个渗透工具生成ShellCode以及如何将ShellCode注入到特定进程内&#xff0c;本章我们将自己实现一个正向ShellCodeShell&#xff0c;当进程被注入后&#xff0c;则我们可以通过利用NC等工具连接到被注入进程内&#xff0c;…...

MySQL 日志系统

重要日志模块 日志文件bin logredo log**关于循环写入和擦除的checkpoint 规则**redo log 怎么刷入磁盘的 binlog 和 redo log 有什么区别&#xff1f;undo log 日志文件 错误日志&#xff08;error log&#xff09;&#xff1a; 错误日志文件对 MySQL 的启动、运行、关闭过程进…...

LeetCode刷题---Two Sum(一)

文章目录 &#x1f340;题目&#x1f340;解法一&#x1f340;解法二&#x1f340;哈希表 &#x1f340;题目 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每…...

算法通关村第十七关——插入区间

LeetCode435,给定一个区间的集合&#xff0c;找到需要移除区间的最小数量&#xff0c;使剩余区间互不重叠。 示例1&#xff1a; 输入&#xff1a;interva1s[[1,3],[6,9]],newInterva1[2,5] 输出&#xff1a;[[1,5]&#xff0c;[6,9]] 解释&#xff1a;新区间[2,5]与[1,3]重…...

Jenkins java8安装版本安装

一、首先准备Jenkins、Jdk8、Tomcat9安装包 根据Jenkins官网介绍&#xff0c;Jenkins支持Java8的版本如下&#xff1a; 我们选择2.164版本进行安装&#xff0c;根据版本号支持输入下载地址&#xff1a;https://archives.jenkins.io/war/2.164/jenkins.war&#xff0c;进行下载…...

线上问诊:数仓开发(二)

系列文章目录 线上问诊&#xff1a;业务数据采集 线上问诊&#xff1a;数仓数据同步 线上问诊&#xff1a;数仓开发(一) 线上问诊&#xff1a;数仓开发(二) 文章目录 系列文章目录前言一、DWS1.最近1日汇总表1.交易域医院患者性别年龄段粒度问诊最近1日汇总表2.交易域医院患者…...

Ansible自动化运维工具(三)

目录 Ansible 的脚本 --- playbook 剧本 ​编辑2.vars模块实战实例 3.指定远程主机sudo切换用户 4.when模块实战实例 5.with_items迭代模块实战实例 6.Templates 模块实战实例 &#xff08;1&#xff09;先准备一个以 .j2 为后缀的 template 模板文件&#xff0c;设置引用…...

ChatGPT在创新和创业中的应用如何?

ChatGPT是一种基于大规模预训练的语言模型&#xff0c;它在创新和创业中有着广泛的应用。作为一种具备自然语言处理能力的模型&#xff0c;ChatGPT可以与用户进行对话&#xff0c;并提供相关的信息、建议和创意。以下是ChatGPT在创新和创业中的一些应用&#xff1a; 创意生成和…...

Log4j2 配置日志记录发送到 kafka 中

前言 log4j2 在 2.11.0 之后的版本&#xff0c;已经内置了 KafkaAppender 支持可以将打印的日志直接发送到 kafka 中&#xff0c;在这之前如果想要集中收集应用的日志&#xff0c;就需要自定义一个 Layout 来实现&#xff0c;相对来说还是比较麻烦的。 官网文档&#xff1a;L…...

Linux用户与组管理(03)(八)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、组管理 1、概述 2、用户信息查看 总结 前言 今天是学习用户与组管理的最后一节课&#xff0c;这节课主要是组管理的内容&#xff0c;希望能一起学习&#xff…...

Java自定义异常

Java标准库定义的常用异常包括&#xff1a; 当我们在代码中需要抛出异常时&#xff0c;尽量使用JDK已定义的异常类型。例如&#xff0c;参数检查不合法&#xff0c;应该抛出IllegalArgumentException&#xff1a; static void process1(int age) {if (age < 0) {throw new…...

vscode远程调试php

使用vscode远程调试php的方法 1.安装remote ssh插件 2.连接服务器 可以点击左下角的绿色按钮&#xff0c;或者ctrlshiftp打开命令框输入remote ssh应该也有。 3.在服务器端vscode安装php debug插件 4.安装xdebug xdebug是用来调试php的软件&#xff0c;原本和vscode没什么关…...

C语言:截断+整型提升练习

详情关于整型提升与截断见文章&#xff1a;《C语言&#xff1a;整型提升》 一、代码一 int main() { char a -1; signed char b -1; unsigned char c -1; printf("%d %d %d", a, b, c); return 0; } 求输出结果 解析如下代码&#xff1a; int mai…...

网站建设需要注册什么类型的公司/淄博seo网站推广

在同一个类中&#xff0c;一个方法调用另外一个有注解(比如Async)的方法&#xff0c;注解是不会生效的。比如&#xff0c;下面代码例子中&#xff0c;有两方法&#xff0c;一个有Async注解&#xff0c;一个没有。第一次如果调用了有注解的test()方法&#xff0c;会启动Async注解…...

钢管网站建设/最新百度快速收录技术

FOB价格是当货物越过船舷&#xff0c;卖方即完成交货。FOB价格术语仅适用于海运或内河运输。在国际贸易中&#xff0c;FOB价格是比较常用的一种&#xff0c;FOB价格作为众多贸易中的一种需要外贸人员熟悉掌握。FOB价格是当货物越过船舷&#xff0c;卖方即完成交货。FOB价格术语…...

网站建设骗子/教师遭网课入侵直播录屏曝光广场舞

合作信息处理模型 介绍&#xff1a;B业务经理的到来A公司洽谈合作&#xff0c;A公司老板接待、会晤&#xff0c;经&#xff08;握手完毕&#xff09;老板会做下一个和后续的管理C。允许C直接地A进入谈判&#xff0c;然后&#xff0c;C找了几个技术人员&#xff08;C1、C2、C3&…...

做网站要给ftp密码吗/开鲁seo服务

2019独角兽企业重金招聘Python工程师标准>>> 项目上对图像处理需要用到点高斯算法&#xff0c;网上找到一篇对原理及部分问题分析讲解的还不错的文章&#xff0c;分享一下&#xff0c;后付自己的一段代码 - 理论 - 高斯分布函数可表示为一个一维的函数G(x) 或者一个…...

wordpress 批量 发布/搜索引擎优化seo网站

根据html5实现的简单的音频播放&#xff0c;还是挺好的&#xff0c;可以借鉴&#xff0c;下面上代码了html5 audio音频播放*{ margin: 0; padding:0;}body{-webkit-tap-highlight-color: rgba(0,0,0,0); font-family: "微软雅黑"}h1{ width: 100%; font-size: 1.5em;…...

scf900色带/南宁百度seo排名公司

在百度控制台发布自定义样式并复制样式ID 添加 setMapStyleV2 功能 map.setMapStyleV2({styleId:76c03cdd35fa1e24f39edeb18849f04e}) 完整代码如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><script type"text/javascript&…...