Mr. Cappuccino的第60杯咖啡——Spring之BeanFactory和ApplicationContext

Spring之BeanFactory和ApplicationContext

    • 类图
    • BeanFactory
      • 概述
      • 功能
        • 项目结构
        • 项目代码
        • 运行结果
        • 总结
    • ApplicationContext
      • 概述
      • 功能
        • MessageSource(国际化的支持)
          • 概述
          • 项目结构
          • 项目代码
          • 运行结果
        • ResourcePatternResolver(匹配资源路径)
          • 概述
          • 项目结构
          • 项目代码
          • 运行结果
        • EnvironmentCapable(环境变量配置)
          • 项目结构
          • 项目代码
          • 运行结果
        • ApplicationEventPublisher(事件发布)
          • 项目结构
          • 项目代码
          • 运行结果
    • ApplicationContext实现类
      • 基于XML方式
        • 项目结构
        • 项目代码
        • 运行结果
      • 基于磁盘目录XML方式
        • 项目结构
        • 项目代码
        • 运行结果
      • 基于注解方式
        • @Import
          • 项目结构
          • 项目代码
          • 运行结果
        • @Conditional
          • 项目结构
          • 项目代码
          • 运行结果

类图

在这里插入图片描述

BeanFactory

概述

  1. BeanFactory,以Factory结尾,表示它是一个工厂类(接口), 它是负责生产和管理bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖;
  2. BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是常用的一种,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。XmlBeanFactory类将持有此XML配置元数据,并用它来构建一个完全可配置的系统或应用;
  3. 它为其他具体的IOC容器提供了最基本的规范,例如DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等具体的容器都是实现了BeanFactory,再在其基础之上附加了其他的功能;
  4. 原始的BeanFactory无法支持Spring的许多插件,如AOP功能、Web应用等。ApplicationContext接口,它由BeanFactory接口派生而来。现在一般使用ApplicationnContext,其不但包含了BeanFactory的作用,同时还进行更多的扩展;

功能

项目结构

在这里插入图片描述

项目代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com</groupId>
    <artifactId>spring-bean-factory</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
    </dependencies>

</project>

AutowireBean.java

package com.spring.bean;

/**
 * @author honey
 * @date 2023-08-10 14:51:07
 */
public class AutowireBean {

    public void autowire(){
        System.out.println("AutowireBean==autowire()");
    }
}

UserBean.java

package com.spring.bean;

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

/**
 * @author honey
 * @date 2023-08-10 14:08:14
 */
public class UserBean {

    @Autowired
    private AutowireBean autowireBean;

    public void to() {
        System.out.println("UserBean==to()");
        autowireBean.autowire();
    }
}

SpringConfig.java

package com.spring.config;

import com.spring.bean.AutowireBean;
import com.spring.bean.UserBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author honey
 * @date 2023-08-10 14:08:44
 */
@Configuration
public class SpringConfig {

    @Bean
    public UserBean userBean(){
        return new UserBean();
    }

    @Bean
    public AutowireBean autowireBean(){
        return new AutowireBean();
    }
}

SpringTest01.java

package com.spring.test;

import com.spring.bean.UserBean;
import com.spring.config.SpringConfig;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;

import java.util.Arrays;
import java.util.Collection;

/**
 * @author honey
 * @date 2023-08-10 14:09:39
 */
public class SpringTest01 {

    public static void main(String[] args) {
        // 初始化BeanFactory
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 获取SpringConfig对应的BeanDefinition
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(SpringConfig.class).getBeanDefinition();
        // 将BeanDefinition注册到BeanFactory中
        beanFactory.registerBeanDefinition("springConfig", beanDefinition);
        // 注册注解相关配置的处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        // 通过BeanFactory后置处理器处理SpringConfig中配置的bean(ConfigurationClassPostProcessor)
        Collection<BeanFactoryPostProcessor> beanFactoryPostProcessors = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values();
        beanFactoryPostProcessors.forEach(
                (beanFactoryPostProcessor) -> beanFactoryPostProcessor.postProcessBeanFactory(beanFactory)
        );
        // 通过Bean对象后置处理器处理依赖注入@Autowired(AutowiredAnnotationBeanPostProcessor)和@Resource(CommonAnnotationBeanPostProcessor)
        Collection<BeanPostProcessor> beanPostProcessors = beanFactory.getBeansOfType(BeanPostProcessor.class).values();
        beanPostProcessors.forEach(
                beanFactory::addBeanPostProcessor
        );
        // 提前初始化单例对象(饿汉式)
        beanFactory.preInstantiateSingletons();
        // 默认情况下延迟加载(懒汉式)
        UserBean userBean = beanFactory.getBean("userBean", UserBean.class);
        userBean.to();
        System.out.println(userBean);

        System.out.println("-------------");

        // 输出所有注册到BeanFactory中的beanName
        Arrays.stream(beanFactory.getBeanDefinitionNames()).forEach((beanName) -> System.out.println("beanName:" + beanName));

    }
}

运行结果

在这里插入图片描述

总结

DefaultListableBeanFactory作为BeanFactory的默认实现类,该类中维护了存储Bean对象的map集合,BeanFactory主要负责生产和管理Bean对象。


// 注册注解相关配置的处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

AnnotationConfigUtils.java

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


// 通过BeanFactory后置处理器处理SpringConfig中配置的bean(ConfigurationClassPostProcessor)
Collection<BeanFactoryPostProcessor> beanFactoryPostProcessors = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values();
beanFactoryPostProcessors.forEach(
        (beanFactoryPostProcessor) -> beanFactoryPostProcessor.postProcessBeanFactory(beanFactory)
);

ConfigurationClassPostProcessor:用于从BeanFactory中检测使用了@Configuration注解的类,并将这些类中使用了@Bean注解的方法生成BeanDefinition,注册到BeanFactory中。

ConfigurationClassPostProcessor.java

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

EventListenerMethodProcessor:主要用于处理@EventListener注解。


// 通过Bean对象后置处理器处理依赖注入@Autowired(AutowiredAnnotationBeanPostProcessor)和@Resource(CommonAnnotationBeanPostProcessor)
Collection<BeanPostProcessor> beanPostProcessors = beanFactory.getBeansOfType(BeanPostProcessor.class).values();
beanPostProcessors.forEach(
        beanFactory::addBeanPostProcessor
);

AutowiredAnnotationBeanPostProcessor: 主要用于处理@Autowired注解。

AutowiredAnnotationBeanPostProcessor.java

在这里插入图片描述

CommonAnnotationBeanPostProcessor:主要用于处理@Resource注解。

CommonAnnotationBeanPostProcessor.java

在这里插入图片描述


// 提前初始化单例对象(饿汉式)
beanFactory.preInstantiateSingletons();

BeanFactory默认采用延迟加载的形式来注入Bean。


BeanFactoryPostProcessor:BeanFactory的后置处理器,是实现spring容器功能扩展的重要接口;
BeanPostProcessor:Bean对象的后置处理器,负责对已创建好的bean对象进行加工处理;

BeanPostProcessor中的两个核心方法:
postProcessBeforeInitialization:在任何初始化方法执行之前执行该方法,如InitializingBean的afterPropertiesSet方法;
postProcessAfterInitialization:在任何初始化方法执行之后执行该方法,如InitializingBean的afterPropertiesSet方法;


ApplicationContext

概述

ApplicationContext的中文意思是“应用程序上下文”,它继承自BeanFactory接口,除了包含BeanFactory的所有功能之外,在国际化支持、资源访问(如URL和文件)、事件传播等方面进行了良好的支持,被推荐为Java EE应用之首选,可应用在Java APP与Java Web中。

  1. MessageSource(国际化的支持)
  2. ResourcePatternResolver(匹配资源路径)
  3. EnvironmentCapable(环境变量配置)
  4. ApplicationEventPublisher(事件发布)

在这里插入图片描述

功能

MessageSource(国际化的支持)

概述

MessageSource是Spring中的转换消息接口,提供了国际化信息的能力。MessageSource用于解析消息,并支持消息的参数化和国际化。Spring包含两个内置的MessageSource实现:ResourceBundleMessageSource和ReloadableResourceBundleMessageSource。

项目结构

在这里插入图片描述

项目代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com</groupId>
    <artifactId>spring-application-context</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
    </dependencies>

</project>

SpringConfig.java

package com.spring.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;

/**
 * @author honey
 * @date 2023-08-11 01:30:48
 */
@Configuration
public class SpringConfig {

    @Bean
    public ResourceBundleMessageSource messageSource() {
        ResourceBundleMessageSource source = new ResourceBundleMessageSource();
        // 设置基础名
        source.setBasenames("messages/message");
        // 设置编码
        source.setDefaultEncoding("UTF-8");
        return source;
    }
}

在resources目录下创建文件夹messages,并在messages文件夹下新增两个配置文件,分别是message_en.properties和message_zh.properties。

message_en.properties

test=test

message_zh.properties

test=测试

SpringTest01.java

package com.spring.test;

import com.spring.config.SpringConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ResourceBundleMessageSource;

import java.util.Locale;

/**
 * @author honey
 * @date 2023-08-11 01:33:10
 */
public class SpringTest01 {

    public static void main(String[] args) {
    	// MessageSource(国际化的支持)
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        ResourceBundleMessageSource messageSource = applicationContext.getBean("messageSource", ResourceBundleMessageSource.class);
        System.out.println("中文:" + messageSource.getMessage("test", null, Locale.CHINESE));
        System.out.println("英文:" + messageSource.getMessage("test", null, Locale.ENGLISH));
    }
}
运行结果

在这里插入图片描述

ResourcePatternResolver(匹配资源路径)

概述

ResourcePatternResolver用于解析带有*等通配符路径的资源文件,是ResourceLoader接口的拓展接口。

classpath: 只会从target/classes目录下查找文件;
classpath*: 不仅会从target/classes目录下查找文件,还会从所依赖的Jar包中查找文件;

项目结构

在这里插入图片描述

项目代码

application.properties

name=honey

SpringTest02.java

package com.spring.test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.io.Resource;

import java.io.IOException;
import java.util.Arrays;

/**
 * @author honey
 * @date 2023-08-11 02:09:51
 */
public class SpringTest02 {

    public static void main(String[] args) throws IOException {
        // ResourcePatternResolver(匹配资源路径)
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        System.out.println("-------------------------------------------------------------");
        System.out.println("读取resources目录下的application.properties");
        Resource[] resources1 = applicationContext.getResources("classpath:application.properties");
        Arrays.stream(resources1).forEach(System.out::println);
        System.out.println("-------------------------------------------------------------");
        System.out.println("读取spring-beans-5.2.1.RELEASE.jar!/META-INF/spring.factories");
        Resource[] resources2 = applicationContext.getResources("classpath*:META-INF/spring.factories");
        Arrays.stream(resources2).forEach(System.out::println);
    }
}
运行结果

在这里插入图片描述

EnvironmentCapable(环境变量配置)

项目结构

在这里插入图片描述

项目代码

SpringTest03.java

package com.spring.test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;

/**
 * @author honey
 * @date 2023-08-11 02:31:12
 */
public class SpringTest03 {

    public static void main(String[] args) {
        // EnvironmentCapable(环境变量配置)
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        String javaHome = environment.getProperty("java_home");
        String env = environment.getProperty("env");
        System.out.println("java_home:" + javaHome);
        System.out.println("env:" + env);
    }
}
运行结果

在启动时需要加上环境变量参数


方式一

在这里插入图片描述


方式二

在这里插入图片描述
在这里插入图片描述


在这里插入图片描述

ApplicationEventPublisher(事件发布)

项目结构

在这里插入图片描述

项目代码

UserInfoEvent.java

package com.spring.event;

import org.springframework.context.ApplicationEvent;

/**
 * @author honey
 * @date 2023-08-11 02:42:37
 */
public class UserInfoEvent extends ApplicationEvent {

    /**
     * source事件源
     *
     * @param source source
     */
    public UserInfoEvent(Object source) {
        super(source);
    }
}

EmailListener.java

package com.spring.listener;

import com.spring.event.UserInfoEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

/**
 * @author honey
 * @date 2023-08-11 02:44:35
 */
@Component
public class EmailListener {

    @EventListener
    public void emailListener(UserInfoEvent userInfoEvent) {
        System.out.println("当前监听器:emailListener,userInfoEvent:" + userInfoEvent);
    }
}

PhoneListener.java

package com.spring.listener;

import com.spring.event.UserInfoEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

/**
 * @author honey
 * @date 2023-08-11 02:46:40
 */
@Component
public class PhoneListener {

    @EventListener
    public void phoneListener(UserInfoEvent userInfoEvent) {
        System.out.println("当前监听器:phoneListener,userInfoEvent:" + userInfoEvent);
    }
}

SpringConfig02.java

package com.spring.config;

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

/**
 * @author honey
 * @date 2023-08-11 02:48:54
 */
@Configuration
@ComponentScan(value = {"com.spring.listener"})
public class SpringConfig02 {
}

SpringTest04.java

package com.spring.test;

import com.spring.config.SpringConfig02;
import com.spring.event.UserInfoEvent;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author honey
 * @date 2023-08-11 02:47:25
 */
public class SpringTest04 {

    public static void main(String[] args) {
        // ApplicationEventPublisher(事件发布)
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig02.class);
        applicationContext.publishEvent(new UserInfoEvent(applicationContext));
    }
}
运行结果

在这里插入图片描述

ApplicationContext实现类

基于XML方式

项目结构

在这里插入图片描述

项目代码

UserBean.java

package com.spring.bean;

/**
 * @author honey
 * @date 2023-08-11 03:11:09
 */
public class UserBean {
}

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userBean" class="com.spring.bean.UserBean"/>

</beans>

SpringTest05.java

package com.spring.test;

import com.spring.bean.UserBean;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author honey
 * @date 2023-08-11 03:11:51
 */
public class SpringTest05 {

    public static void main(String[] args) {
        // 读取spring.xml
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        // 从IOC容器中读取对象
        UserBean userBean = applicationContext.getBean("userBean", UserBean.class);
        System.out.println(userBean);
    }
}

运行结果

在这里插入图片描述

基于磁盘目录XML方式

项目结构

在这里插入图片描述

项目代码

在这里插入图片描述

SpringTest06.java

package com.spring.test;

import com.spring.bean.UserBean;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/**
 * @author honey
 * @date 2023-08-11 03:17:20
 */
public class SpringTest06 {

    public static void main(String[] args) {
        // 从磁盘中读取spring.xml
        FileSystemXmlApplicationContext applicationContext = new FileSystemXmlApplicationContext("F:\\spring.xml");
        // 从IOC容器中读取对象
        UserBean userBean = applicationContext.getBean("userBean", UserBean.class);
        System.out.println(userBean);
    }
}

运行结果

在这里插入图片描述

基于注解方式

  1. @Configuration:配置类
  2. @ComponentScan:扫描指定包中加上了@Controller/@Service/@Reponsitory/@Component等注解的类
  3. @Bean:beanId默认为方法名称
  4. @Import:beanId默认为类的全限定名
    4.1. @Import({A.class,B.class})
    4.2. @Import (MyImportSelector.class),其中MyImportSelector实现了ImportSelector接口
    4.3. @Import (MyImportBeanDefinitionRegistrar.class),其中MyImportBeanDefinitionRegistrar实现了ImportBeanDefinitionRegistrar接口
  5. @Scope:设置作用域(singleton、prototype、request、session)
  6. @Lazy:设置单例对象是否懒加载
  7. @Conditional:根据指定条件判断Bean对象是否加载到IOC容器中

@Import

项目结构

在这里插入图片描述

项目代码

SpringConfig03.java

package com.spring.config;

import com.spring.bean.UserBean;
import org.springframework.context.annotation.Bean;

/**
 * @author honey
 * @date 2023-08-11 03:53:02
 */
public class SpringConfig03 {

    @Bean
    public UserBean userBean03() {
        return new UserBean();
    }
}

SpringConfig04.java

package com.spring.config;

import com.spring.bean.UserBean;
import org.springframework.context.annotation.Bean;

/**
 * @author honey
 * @date 2023-08-11 03:54:27
 */
public class SpringConfig04 {

    @Bean
    public UserBean userBean04() {
        return new UserBean();
    }
}

MyImportSelector.java

package com.spring.bean;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

/**
 * @author honey
 * @date 2023-08-11 03:55:37
 */
public class MyImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.spring.config.SpringConfig04"};
    }
}

MyImportBeanDefinitionRegistrar.java

package com.spring.bean;

import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

/**
 * @author honey
 * @date 2023-08-11 03:55:45
 */
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(UserBean.class);
        registry.registerBeanDefinition("userBean05", rootBeanDefinition);
    }
}

SpringConfig05.java

package com.spring.config;

import com.spring.bean.MyImportBeanDefinitionRegistrar;
import com.spring.bean.MyImportSelector;
import org.springframework.context.annotation.Import;

/**
 * @author honey
 * @date 2023-08-11 04:02:27
 */
@Import({SpringConfig03.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class SpringConfig05 {

}

SpringTest07.java

package com.spring.test;

import com.spring.bean.UserBean;
import com.spring.config.SpringConfig05;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author honey
 * @date 2023-08-11 04:06:39
 */
public class SpringTest07 {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig05.class);
        UserBean userBean03 = annotationConfigApplicationContext.getBean("userBean03", UserBean.class);
        System.out.println(userBean03);
        UserBean userBean04 = annotationConfigApplicationContext.getBean("userBean04", UserBean.class);
        System.out.println(userBean04);
        UserBean userBean05 = annotationConfigApplicationContext.getBean("userBean05", UserBean.class);
        System.out.println(userBean05);
    }
}
运行结果

在这里插入图片描述

@Conditional

项目结构

在这里插入图片描述

项目代码

LinuxCondition.java

package com.spring.condition;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
 * @author honey
 * @date 2023-08-11 04:20:37
 */
public class LinuxCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return System.getProperty("os.name").toLowerCase().contains("linux");
    }
}

WindowsCondition.java

package com.spring.condition;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
 * @author honey
 * @date 2023-08-11 04:22:04
 */
public class WindowsCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return System.getProperty("os.name").toLowerCase().contains("windows");
    }
}

SystemOperation.java

package com.spring.condition;

/**
 * @author honey
 * @date 2023-08-11 04:22:49
 */
public class SystemOperation {

    private final String name;

    public SystemOperation(String name) {
        this.name = name;
    }

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

SpringConfig06.java

package com.spring.config;

import com.spring.condition.LinuxCondition;
import com.spring.condition.SystemOperation;
import com.spring.condition.WindowsCondition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;

/**
 * @author honey
 * @date 2023-08-11 04:23:27
 */
public class SpringConfig06 {

    @Bean
    @Conditional(value = WindowsCondition.class)
    public SystemOperation windowsSystemOperation() {
        return new SystemOperation("执行windows命令");
    }

    @Bean
    @Conditional(value = LinuxCondition.class)
    public SystemOperation linuxSystemOperation() {
        return new SystemOperation("执行linux命令");
    }
}

SpringTest08.java

package com.spring.test;

import com.spring.condition.SystemOperation;
import com.spring.config.SpringConfig06;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Map;

/**
 * @author honey
 * @date 2023-08-11 04:24:39
 */
public class SpringTest08 {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig06.class);
        Map<String, SystemOperation> beansOfType = annotationConfigApplicationContext.getBeansOfType(SystemOperation.class);
        System.out.println(beansOfType);
    }
}
运行结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/73226.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一、初始 Spring MVC

文章目录 一、回顾 MVC 模式二、初始 Spring MVC2.1 Spring MVC 核心组件2.1.1 前端控制器&#xff08;DispatcherServlet&#xff09;2.1.2 处理器映射器&#xff08;HandlerMapping&#xff09;2.1.3 处理器适配器&#xff08;HandlerAdapter&#xff09;2.1.3 后端控制器&am…

前端性能优化之性能优化的指标和工具(chrome devtools、lighthouse、webpagetest)

文章目录 引言一、为什么要进行web性能优化二、RAIL测量模型1. 什么是RAIL2. 性能测量工具 三、性能测量工具的使用和性能指标以及优化目标1. Chrome DevTools1. 打开调试工具方式和配置2. network下的几个性能指标1. requests 请求总数2. transferred实际从服务器下载的数据量…

学会智慧工地有多爽?能省时间又高效?

当今社会&#xff0c;科技的迅速发展正在深刻地改变着各行各业&#xff0c;建筑领域也不例外。在这一背景下&#xff0c;"智慧工地"这一概念应运而生&#xff0c;它代表了将创新技术和数字化解决方案引入建筑工地&#xff0c;以提升效率、安全性和可持续性的愿景。 智…

岛屿的最大面积(力扣)递归 JAVA

给你一个大小为 m x n 的二进制矩阵 grid 。 岛屿 是由一些相邻的 1 (代表土地) 构成的组合&#xff0c;这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0&#xff08;代表水&#xff09;包围着。 岛屿的面积是岛上值为 1 的…

vue3+element-plus点击列表中的图片预览时,图片被表格覆盖

文章目录 问题解决 问题 视觉 点击图片进行预览&#xff0c;但还能继续选中其他的图片进行预览&#xff0c;鼠标放在表格上&#xff0c;那一行表格也会选中&#xff0c;如图所示第一行的效果。 代码 <el-table-column prop"id" label"ID" width"…

回归预测 | MATLAB实现K折交叉验证GRNN广义回归神经网络多输入单输出回归预测

回归预测 | MATLAB实现K折交叉验证GRNN广义回归神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现K折交叉验证GRNN广义回归神经网络多输入单输出回归预测效果一览基本介绍研究内容程序设计参考资料效果一览 基本介绍 回归预测 | MATLAB实现K折交叉验证GRNN广义回归神经…

深入探析设计模式:工厂模式的三种姿态

深入探析设计模式&#xff1a;工厂模式的三种姿态 1. 简单工厂模式1.1 概念1.2 案例1.3 优缺点 2. 抽象工厂模式2.1 概念2.2 案例&#xff1a;跨品牌手机生产2.3 优缺点 3. 超级工厂模式3.1 概念3.2 案例&#xff1a;动物园游览3.3 优缺点 4. 总结 欢迎阅读本文&#xff0c;今天…

“深入解析Maven:安装、创建项目和依赖管理的完全指南“

目录 引言Maven的安装创建Maven项目之前的装备工作Eclipse创建新的Maven项目项目依赖管理 总结 引言 Maven是一个流行的项目管理工具&#xff0c;被广泛用于Java项目的构建、依赖管理和部署。它提供了一种简单而强大的方式来管理项目的各个方面&#xff0c;使开发人员能够更专…

虹科展会 | 自动驾驶展品:上海汽车测试展精彩回顾

2023年8月9日-8月11日&#xff0c;上海国际汽车测试及质量监控博览会在上海圆满落幕。本次展会提供了一个了解最新汽车测试及质量监控技术、产品和趋势的机会&#xff0c;同时也是汽车测试及质量监控领域的专业人士和业内人士的重要交流平台。 雅名特是虹科旗下子公司&#xff…

2023年国赛数学建模思路 - 案例:FPTree-频繁模式树算法

文章目录 算法介绍FP树表示法构建FP树实现代码 建模资料 ## 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模式树算法&#xff0c…

改造旧项目-长安分局人事费用管理系统

一、系统环境搭建 1、搭建前台环境 vue3vite构建项目复制“银税系统”页面结构&#xff0c;包括&#xff1a;路由、vuex存储、菜单、登录&#xff08;复制一个干净的空架子&#xff09; 2、搭建后台环境 新三大框架 SSMP聚合工程&#xff1a;common、admin&#xff0c;新的…

《算法竞赛·快冲300题》每日一题:“房间划分”

《算法竞赛快冲300题》将于2024年出版&#xff0c;是《算法竞赛》的辅助练习册。 所有题目放在自建的OJ New Online Judge。 用C/C、Java、Python三种语言给出代码&#xff0c;以中低档题为主&#xff0c;适合入门、进阶。 文章目录 题目描述题解C代码Java代码Python代码 “ 房…

全文检索与日志管理 Elasticsearch(上)

一、Elasticsearch介绍 1.1 全文检索索引 Elasticsearch是一个全文检索服务器&#xff0c;全文检索是一种非结构化数据的搜索方式。 那么什么是结构化数据和非结构化数据呢&#xff1f; 结构化数据&#xff1a;指具有固定格式固定长度的数据&#xff0c;如数据库中的字段。 …

影响股票数据接口l2传输数据快慢因素有哪些?(l2数据接口)

股票数据接口l2是一种用于获取股票市场相关数据的编程接口。它允许开发者通过编程的方式获取、查询、订阅和更新股票相关数据&#xff0c;如股票价格、成交量、财务数据等&#xff0c;并将这些数据用于自己的应用或系统中。l2数据接口通常提供实时行情数据、历史行情数据、财务…

【深度学习】多粒度、多尺度、多源融合和多模态融合的区别

多粒度&#xff08;multiresolution&#xff09;和多尺度&#xff08;multiscale&#xff09; 多粒度&#xff08;multiresolution&#xff09;和多尺度&#xff08;multiscale&#xff09;都是指在不同的空间或时间尺度上对数据或信号进行分析和处理。其中 多尺度&#xff1…

为什么要学PMP项目管理?

为什么要学习PMP呢&#xff0c;主要有以下五点&#xff1a; 01提升个人能力 PMP是一个系统学习的过程&#xff0c;充分理解各个项目管理的过程以及项目管理的各个过程组、知识领域等&#xff0c;可以从理论上掌握项目经理应具有的理论素质。能够知道如何对执行的项目进行系统…

django实现登录和登录的鉴权

1、创建数据库的管理员表 在models.py 中定义admin表&#xff0c;为了简单&#xff0c;表里只有用户名和密码还有默认加的id 三个字段 from django.db import models# Create your models here.class Admin(models.Model):username models.CharField(verbose_name"用户…

leetcode剑指 Offer 05. 替换空格(两种方法)

题目&#xff1a;leetcode剑指 Offer 05. 替换空格 描述&#xff1a; 请实现一个函数&#xff0c;把字符串 s 中的每个空格替换成"%20"。 示例 1&#xff1a; 输入&#xff1a;s “We are happy.” 输出&#xff1a;“We%20are%20happy.” 思路&#xff1a; 第一…

【vue】alert弹窗太死板?试试这种方法(附代码)

alert(response.data.message); 新方法&#xff1a; this.$message.error(请检查您输入的的用户名和密码&#xff01;);

用户端Web自动化测试-L1

目录&#xff1a; Web自动化测试价值与体系环境安装与使用自动化用例录制自动化测试用例结构分析web浏览器控制常见控件定位方法强制等待与隐式等待常见控件交互方法自动化测试定位策略搜索功能自动化测试用户端Web自动化测试 1.Web自动化测试价值与体系 功能测试场景: UI 自…