Spring-BeanFactory

news2024/7/4 5:47:25

Spring

Spring是整个Java体系最核心的框架,没有之一。

核心类图结构

在这里插入图片描述

ApplicationContext

  • ApplicationEventPublisher:提供了一种机制,用于通知应用程序中感兴趣的部分有关其执行过程中发生的特定事件。
  • ListableBeanFactory:是Spring框架中的一个接口,它继承了BeanFactory接口,是一个具有列表查询能力的Bean工厂。
  • HierarchicalBeanFactory:是Spring框架中的另一个接口,它扩展了BeanFactory接口。
  • ResourcePatternResolver:是 Spring Framework 中的一个接口,用于以资源位置模式的格式解析资源。
  • MessageSource:处理国际化资源的组件,用于支持国际化(i18n)和本地胡(l1On)。
  • EnvironmentCapable:是 Spring Framework 中的一个接口,用于表示一个对象是否具备获取环境(Environment)的能力。
  • FunctionalInterface:是 Java 8 引入的一个新的接口类型,它是一个特殊的接口,只能有一个抽象方法(可以有默认方法和静态方法),用于支持函数式编程。
  • BeanFactory:是 Spring 框架的核心接口之一,主要负责对Bean的配置和管理功能,具体的创建功能是由子类来实现注入的。
  • ResourceLoader:Spring Framework 中的一个接口,用于加载资源(Resource)的抽象。

BeanFactory

它是 Spring IoC(Inversion of Control,控制反转)容器的基础。IoC 容器负责管理和组装应用程序中的对象(也称为 Bean)。
在 Spring 中,BeanFactory 提供了以下主要功能:

  • 实例化对象:BeanFactory 负责根据配置元数据(通常是 XML 或注解)来实例化 Java 对象,这些对象被称为 Beans。它将对象的创建和初始化过程与应用程序代码解耦,使得对象的创建更加灵活和可配置。

  • Bean 的配置管理:BeanFactory 负责管理 Bean 的配置元数据。这些元数据定义了 Bean 的类型、依赖关系和其他属性。配置元数据可以通过 XML 配置文件、Java 注解或 Java 代码进行指定。

  • 依赖注入(Dependency Injection):BeanFactory 通过依赖注入的方式自动解析和设置 Bean 之间的依赖关系。依赖注入消除了硬编码的依赖关系,使得组件之间的协作更加灵活和可维护。

  • 单例和原型模式管理:BeanFactory 可以管理单例(Singleton)和原型(Prototype)两种类型的 Bean。单例 Bean 在容器中只有一个实例,而原型 Bean 每次被请求时都会创建一个新的实例。

  • 生命周期管理:BeanFactory 负责管理 Bean 的生命周期,它在需要的时候创建 Bean、初始化 Bean、调用 Bean 的初始化回调方法,并在容器关闭时销毁 Bean。

BeanFactory 接口定义了一些常用的方法,允许应用程序通过 Bean 名称或类型来访问和管理这些 Bean。常见的实现类包括 DefaultListableBeanFactory 和 XmlBeanFactory。

  • DefaultListableBeanFactory 是 Spring 框架默认的 BeanFactory 实现,支持基于 XML 配置和注解的 Bean 定义( class,scope, 初始化、销毁等信息)。

  • XmlBeanFactory 是较早的实现,它从 XML 配置文件中读取 Bean 定义并实例化相应的 Bean。不过在较新版本的 Spring 中,推荐使用DefaultListableBeanFactory 或者更高级的容器,如 ApplicationContext。

MessageSource

它提供了一种机制,允许应用程序通过统一的接口访问不同语言环境下的文本消息,从而使应用程序可以根据用户的语言偏好显示相应的文本信息。

在国际化和本地化的场景中,不同地区和语言可能有不同的语言、日期格式、货币符号等。通过使用 MessageSource,开发者可以将这些本地化的文本消息抽象出来,而不必硬编码到应用程序代码中,从而方便地实现多语言支持。
主要定义下面方法:

String getMessage(String code, Object[] args, String defaultMessage, Locale locale);
String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;

其中,code 是消息的唯一标识符,args 是替换消息中占位符的参数数组,defaultMessage 是在找不到指定消息时的默认文本。locale 参数用于指定所需的语言环境。

Spring 中的 MessageSource 通常由 ResourceBundleMessageSourceReloadableResourceBundleMessageSource 等实现类来支持,这些实现类可以从属性文件(通常是 .properties 文件)或者其他资源中加载本地化消息。

简单的示例:

  1. 在属性文件中定义不同语言环境的消息(例如 messages_en.properties 和 messages_fr.properties):
  • messages_en.properties:
    greeting=Hello!
    
  • messages_fr.properties:
    greeting=Bonjour!
    
  1. 创建一个 Spring Bean,并注入 MessageSource:
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.MessageSource;
    import org.springframework.stereotype.Component;
    
    import java.util.Locale;
    
    @Component
    public class GreetingService {
    
        private final MessageSource messageSource;
    
        @Autowired
        public GreetingService(MessageSource messageSource) {
            this.messageSource = messageSource;
        }
    
        public void printGreeting(Locale locale) {
            String greeting = messageSource.getMessage("greeting", null, "Default Greeting", locale);
            System.out.println(greeting);
        }
    }
    
  2. 在应用程序中使用 GreetingService:
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    import java.util.Locale;
    
    public class MainApp {
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
            GreetingService greetingService = context.getBean(GreetingService.class);
    
            greetingService.printGreeting(Locale.US); // Output: Hello!
            greetingService.printGreeting(Locale.FRENCH); // Output: Bonjour!
    
            context.close();
        }
    }
    
    在上面的示例中,GreetingService 中的 printGreeting 方法会根据传入的 locale 参数获取对应的消息。如果指定的消息未找到,将会返回默认的消息(“Default Greeting”)。

总结
通过 MessageSource,我们可以轻松实现多语言支持,使得应用程序可以根据不同用户的语言偏好提供合适的本地化文本信息。

ResourcePatternResolver

它是 Spring 核心框架的一部分,提供了一种方便的方式来定位资源,例如文件、类路径资源、URL 等,基于给定的模式。
Spring Framework 提供了多种 ResourcePatternResolver 接口的实现,以支持不同的资源定位策略。其中一些常用的实现包括:

  • PathMatchingResourcePatternResolver:这是在 Spring 应用程序中最常用的实现。它可以使用 Ant 风格的路径匹配模式来解析资源,例如 classpath*:com/example/**/*.xml,用于查找 com/example/ 包及其子包中的所有 XML 文件。

  • ServletContextResourcePatternResolver:此实现特定于 Web 应用程序,并允许您相对于 ServletContext 来解析资源。

  • FileSystemResourcePatternResolver:此解析器允许您使用文件系统路径来解析资源,在需要处理类路径之外的资源时很有用。

ResourcePatternResolver 接口提供了几种资源解析的方法,例如 getResources(String locationPattern) 可以获取与指定模式匹配的资源列表,getResource(String location) 可以根据位置获取单个资源等。

Spring 应用程序中使用 ResourcePatternResolver 的示例:

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import java.io.IOException;

public class ResourceResolverExample {

    public static void main(String[] args) {
        // 创建资源解析器
        PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();

        try {
            // 使用 Ant 风格的模式解析资源
            Resource[] resources = resourceResolver.getResources("classpath*:com/example/**/*.xml");

            // 处理资源
            for (Resource resource : resources) {
                System.out.println("资源:" + resource.getFilename());
                // 在此处处理资源
            }
        } catch (IOException e) {
            // 处理异常
            e.printStackTrace();
        }
    }
}

ApplicationEventPublisher

它是 Spring 的事件驱动编程模型的一部分,可以在Sring应用程序中发布一些事件,对于订阅该特定类型的事件的的相关组件都可以订阅这些事件。允许 Spring 应用程序内的组件以松散耦合的方式进行通信和交互,通过事件来实现。

  1. 创建一个事件类
// 创建一个事件类
import org.springframework.context.ApplicationEvent;

public class CustomEvent extends ApplicationEvent {
    public CustomEvent(Object source) {
        super(source);
    }

    // 根据需要添加自定义属性和方法。
}
  1. 创建一个事件发布者
// 创建一个事件发布者
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;

public class CustomEventPublisher implements ApplicationEventPublisherAware {

    private ApplicationEventPublisher eventPublisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    public void doSomethingAndPublishEvent() {
        // 做一些重要的事情...
        
        // 创建并发布事件
        CustomEvent customEvent = new CustomEvent(this);
        eventPublisher.publishEvent(customEvent);
    }
}
  1. 创建一个事件监听器
// 创建一个事件监听器:
import org.springframework.context.ApplicationListener;

public class CustomEventListener implements ApplicationListener<CustomEvent> {

    @Override
    public void onApplicationEvent(CustomEvent event) {
        // 在这里处理自定义事件
        // 当事件被发布时,该方法将被调用。
    }
}

  1. 将监听器和发布器注入到容器中
<bean id="customEventPublisher" class="com.example.CustomEventPublisher" />
<bean id="customEventListener" class="com.example.CustomEventListener" />

ListableBeanFactory

ListableBeanFactory还提供了一些用于查询和获取Bean的扩展方法,使得可以方便地获取容器中的所有Bean或按条件进行Bean的查找。

主要的方法包括:

  • getBeanDefinitionCount(): 返回容器中注册的Bean定义的数量。

  • getBeanDefinitionNames(): 返回容器中所有注册的Bean的名称列表。

  • getBeanNamesForType(Class<?> type): 根据给定的类型返回对应的Bean名称列表。

  • getBeansOfType(Class type): 返回容器中给定类型的Bean实例的映射,其中Key为Bean名称,Value为对应的Bean实例。

这些方法使得开发人员可以很方便地根据类型或名称来获取容器中的Bean,而不需要手动遍历整个Bean定义列表。

示例:

假设我们有以下的两个Bean类,使用注解的示例:

@Component
public class User {
    // ...
}

@Component
public class Product {
    // ...
}

然后,我们可以通过ListableBeanFactory来获取容器中的所有Bean或按类型获取Bean:

import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainApp {
    public static void main(String[] args) {
        ListableBeanFactory context = new AnnotationConfigApplicationContext(MainApp.class);
        
        // 获取容器中所有Bean的名称
        String[] beanNames = context.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            System.out.println("Bean Name: " + beanName);
        }
        
        // 按类型获取Bean
        Map<String, User> users = context.getBeansOfType(User.class);
        for (Map.Entry<String, User> entry : users.entrySet()) {
            System.out.println("User Bean Name: " + entry.getKey());
        }
    }
}

HierarchicalBeanFactory

HierarchicalBeanFactory定义了一种层次结构,可以用于组织和管理多个BeanFactory实例,从而构建更复杂的容器结构。
在Spring中,HierarchicalBeanFactory接口主要用于以下两种场景:

  • 层次性的Bean查找:如果有多个BeanFactory层次相嵌套,可以通过层次性的Bean查找来从一个容器中查找Bean,如果找不到,则会递归地向上级容器查找,直到找到或者到达根容器。
  • 属性覆盖:层次性的BeanFactory允许子容器覆盖父容器中的Bean定义。在子容器中可以定义一个与父容器相同ID的Bean定义,从而覆盖父容器中的对应Bean。

通常情况下,ApplicationContext接口实现了HierarchicalBeanFactory接口,因此,ApplicationContext可以利用HierarchicalBeanFactory提供的功能。
如何使用层次性的BeanFactory:

import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class MainApp {
    public static void main(String[] args) {
        // 创建父容器,并加载配置文件beans-parent.xml
        HierarchicalBeanFactory parentBeanFactory = new XmlBeanFactory(new ClassPathResource("beans-parent.xml"));
        
        // 创建子容器,并加载配置文件beans-child.xml
        XmlBeanFactory childBeanFactory = new XmlBeanFactory(new ClassPathResource("beans-child.xml"), parentBeanFactory);
        
        // 在子容器中获取名为"user"的Bean
        User user = (User) childBeanFactory.getBean("user");
        
        // 调用User的方法
        user.greet();
    }
}

EnvironmentCapable

是一个表示应用程序当前运行环境的接口。它可以用于获取配置属性、激活的配置文件、配置文件的属性值等。Spring 应用程序可以有多个不同的环境,例如开发、测试、生产环境等,并且根据不同环境进行配置和运行。
EnvironmentCapable 接口定义了一个方法:

Environment getEnvironment();

实现该接口的类需要提供这个方法的具体实现,以返回一个 Environment 实例。通过实现此接口,对象可以获取与应用程序配置相关的环境信息,并相应地调整其行为。
示例:

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.Environment;

public class EnvironmentExample {

    public static void main(String[] args) {
        // 创建并初始化 Spring 应用程序上下文
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        // 获取环境信息
        Environment environment = context.getEnvironment();

        // 获取配置属性值
        String propertyValue = environment.getProperty("app.name");
        System.out.println("应用程序名称:" + propertyValue);
    }
}

ResourceLoader

它是 Spring 的资源加载机制的核心接口,提供了一种统一的方式来获取不同类型的资源,如文件、类路径资源、URL 等。
ResourceLoader 接口定义了一个方法:

Resource getResource(String location);

实现该接口的类需要提供这个方法的具体实现,以根据给定的资源位置(location)加载相应的资源。Resource 是 Spring 框架中另一个重要的接口,它代表一个可访问的资源,可以是文件、类路径资源、URL 等。

Spring 提供了多个实现 ResourceLoader 接口的类,包括:

  • DefaultResourceLoader: 默认的资源加载器,用于加载资源,支持类路径资源、文件系统资源等。
  • ClassPathResourceLoader: 用于加载类路径资源。
  • ServletContextResourceLoader: 用于在 Web 应用程序中加载 ServletContext 资源。
  • UrlResourceLoader: 用于加载 URL 资源。
  • 其他自定义的实现类,根据需要加载其他类型的资源。

在 Spring 应用程序中,通常通过 ResourceLoader 来加载资源,以获得更灵活的资源管理和访问方式。这样可以使代码与具体的资源位置解耦,并且能够轻松地在不同环境中切换资源的加载方式。

以下是一个简单的示例,展示如何使用 ResourceLoader 接口加载资源:

import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.DefaultResourceLoader;

public class ResourceLoaderExample {

    public static void main(String[] args) {
        // 创建资源加载器
        ResourceLoader resourceLoader = new DefaultResourceLoader();

        // 加载资源
        Resource resource = resourceLoader.getResource("classpath:example.txt");

        // 判断资源是否存在
        if (resource.exists()) {
            // 处理资源
            // ...
        } else {
            System.out.println("资源不存在。");
        }
    }
}

使用 DefaultListableBeanFactory

  • AnnotationConfigUtils.registerAnnotationConfigProcessors
    加一些后置处理器,@Bean @Configuration @Autowired @Resource 等后置处理器。
  • BeanFactoryPostProcessor
    允许在BeanFactory标准初始化之后,对BeanFactory进行进一步的自定义修改。
  • BeanPostProcessor
    用于在Bean实例化和初始化过程中进行扩展和处理。它允许开发者在Bean的生命周期的特定阶段插入自定义逻辑,以对Bean进行额外的处理和操作。
package com.dengsheng.a02;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;

import javax.annotation.Resource;

/**
 * 
 */
public class TestBeanFactory {

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean定义
        // 类型:class,单列还是多例:scope,初始化:方法,销毁:方法)
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
                .genericBeanDefinition(Config.class).setScope("singleton")
                .getBeanDefinition();
        // 注册
        beanFactory.registerBeanDefinition("config", beanDefinition);

        // 注册自定义的BeanFactoryPostProcessor
        beanFactory.registerSingleton("myBeanFactoryPostProcessor", new MyBeanFactoryPostProcessor());


        //  beanfactory添加一些后置处理器 例如@Bean @Configuration
        //  @Bean是将没有的添加到容器中,而Autowired是将有的注入导另外一个类的属性中
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);


//        System.out.println("Bean3:"+beanFactory.getBean(Bean3.class));// 报错 No qualifying bean of type 'com.dengsheng.a02.TestBeanFactory$Bean3' available

        // 执行bean工厂处理器,补充一些Bean的定义
        System.out.println("BeanFactoryPostProcessor, pre:");
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().
                stream().sorted(beanFactory.getDependencyComparator()).// 逆转 beanfactory加载 后置处理器的 的顺序
                forEach( beanFactoryPostProcessor ->{
            System.out.println(">>>>"+beanFactoryPostProcessor);
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);// 添加绑定关系
        });




        System.out.println("BeanFactoryPostProcessor, after:");
//        System.out.println(">>>>Bean1:"+beanFactory.getBeansOfType(Bean1.class));
//        System.out.println(">>>>Bean1.getBean2:"+(beanFactory.getBeansOfType(Bean1.class).size()==0?null:beanFactory.getBeansOfType(Bean1.class).get("bean1").getBean2()));//  这里并没有注入Bean1里面的bean2属性? 由于没有添加bean的后置处理器,导致无法加载Bean1里面的bean2


//        beanFactory.removeBeanDefinition("bean1");
        System.out.println(">>>>BeanPostProcessor:");
        // 针对bean的生命周期的各个阶段提供扩展, 处理 @Autowired @Resource
        beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanPostProcessor -> {// 调用后能让beanFactory处理Bean内部一些信息
            System.out.println(">>>>"+beanPostProcessor);
            beanFactory.addBeanPostProcessor(beanPostProcessor);
        });



//        System.out.println("Bean2:"+beanFactory.getBean(Bean2.class));
//        Bean1 newBean1 = beanFactory.getBean(Config.class).bean1();
//        System.out.println(">>>>Config.Bean1:"+bean1);
//        System.out.println(">>>>Config.Bean1.getBean2:"+newBean1.getBean2());

//        bean1 = beanFactory.getBean(Bean1.class);
//        System.out.println("Bean1:"+bean1);
        System.out.println("Bean1.getBean2:"+beanFactory.getBean(Bean1.class).getBean2());


        /**
         * BeanFacotoryPostProcessor
         *
         * 允许我们在实例化bean之前(在调用bean的构造函数创建对象之前执行)拿到bean定义信息,然后修改它,比如可以修改bean的属性值,或者往容器中注入一些其他的bean定义信息
         *
         * BeanPostProcessor
         *
         * 允许我们在bean初始化之前、或者初始化之后,修改bean实例信息,比如生成bean的动态代理对象,提供需要注入的Bean
         */


//        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
//            System.out.println(beanDefinitionName);
//        }
        System.out.println(">>>>preInstantiateSingletons, pre");
        beanFactory.preInstantiateSingletons();//默认懒加载,使用之后可以提前准备好所有的单利对象
        System.out.println(">>>>preInstantiateSingletons, after");
        System.out.println(beanFactory.getBean(Bean1.class).getBean2());
        System.out.println(beanFactory.getBean(Bean1.class).getInter());
        System.out.println(beanFactory.getBean(Bean4.class));// 为空原因是:Bean4没有任何路径被容器当作bean处理,即使添加了Autowired注解。


        /**
         * beanFactory 不会做什么是
         *  1. 不会主动调用BeanFactory 后处理器
         *  2. 不会主动调用 Bean 后处理器
         *  3. 不会主动初始化单例
         *  4. 不会解析beanFactory 还不会解析 ${} 与 ${}
         *
         * bean 后处理器会有排序的逻辑
         *
         */

    }

    @Configuration
    static class Config{
        @Bean
        public Bean1 bean1(){
            System.out.println("@Bean:Bean1");
            return new Bean1();
        }

        @Bean
        public Bean2 bean2(){
            System.out.println("@Bean:Bean2");
            return new Bean2();
        }

        @Autowired
        Bean3 bean3;

        @Bean
        public Bean3 bean3(){
            System.out.println("@Bean:Bean3");
            return new Bean3();
        }

//        @Bean
//        public Bean4 bean4(){
//            System.out.println("@Bean:Bean4");
//            return new Bean4();
//        }
    }



    static class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("MyBeanFactoryPostProcessor");
            // 添加一个新的Bean定义
            beanFactory.registerSingleton("bean4", new Bean4());
        }
    }




    interface Inter{

    }

    static class Bean3 implements Inter{
        public Bean3() {
            System.out.println("构造 Bean3()");
        }
    }

    static class Bean4 implements Inter{
        public Bean4() {
            System.out.println("构造 Bean4()");
        }
    }

    static class Bean2 {
        public Bean2() {
            System.out.println("构造 Bean2()");
        }
    }

    static class Bean1{

        public Bean1() {
            System.out.println("构造 Bean1()");
        }

        @Autowired
        private Bean2 bean2;

        public Bean2 getBean2() {
            return bean2;
        }


        @Resource(name="bean4")// 容器存在 类型为 Inter的两个bean,bean3,bean4, 会使用bean4
        @Autowired
        private Inter bean3; // 容器存在 类型为 Inter的两个bean,bean3,bean4, 会使用bean3
//        private Inter inter; //根据类型或者 属性名来匹配,发现bean3,bean4 都是同样的类型,就会报错 NoUniqueBeanDefinitionException
        // 同时存在Autowired比、Resource,Autowired比Resource的优先级高,bean的Id即为Autowired修饰的属性名


        public Inter getInter() {
            return bean3;
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

P3855 [TJOI2008] Binary Land(BFS)(内附封面)

[TJOI2008] Binary Land 题目背景 Binary Land是一款任天堂红白机上的经典游戏&#xff0c;讲述的是两只相爱的企鹅Gurin和Malon的故事。两只企鹅在一个封闭的迷宫中&#xff0c;你可以控制他们向上下左右四个方向移动。但是他们的移动有一个奇怪的规则&#xff0c;即如果你按…

cloudstack之basic network

本章则主要尝试basic network模式的使用。 基础环境搭建见cloudstack测试环境搭建 1、概念介绍 cloudstack的网络模式主要分为两种&#xff1a; basic network&#xff1a;一个zone中仅有一个guest network来承载客户虚拟机的流量&#xff0c;可以理解为一个简单的二层网络。…

【EI/SCOPUS征稿】2023年算法、图像处理与机器视觉国际学术会议(AIPMV2023)

2023年算法、图像处理与机器视觉国际学术会议&#xff08;AIPMV2023&#xff09; 2023 International Conference on Algorithm, Image Processing and Machine Vision&#xff08;AIPMV2023&#xff09; 2023年算法、图像处理与机器视觉国际学术会议&#xff08;AIPMV2023&am…

Django学习记录:使用ORM操作MySQL数据库并完成数据的增删改查

Django学习记录&#xff1a;使用ORM操作MySQL数据库并完成数据的增删改查 数据库操作 MySQL数据库pymysql Django开发操作数据库更简单&#xff0c;内部提供了ORM框架。 安装第三方模块 pip install mysqlclientORM可以做的事&#xff1a; 1、创建、修改、删除数据库中的…

maven如何打包你会吗?

1.新建一个maven项目&#xff0c;在main/java中建立Main类 public class Main {public static void main(String[] args) {System.out.println("hello java ...");} } 2.添加依赖&#xff0c;使其成为可执行包 <build><plugins><!--打包成为可执行包-…

uniapp app端 echarts 设置tooltip的formatter不生效问题以及解决办法

需求一&#xff1a; y轴数据处理不同数据增加不同单位 需求二&#xff1a; 自定义图表悬浮显示的内容 需求一&#xff1a;实现方式 在yAxis里面添加formatter yAxis: [{//y轴显示value的设置axisLabel: {show: true,formatter (value, index) > {var valueif (value > 1…

Uboot实现PSCI

快速链接: . &#x1f449;&#x1f449;&#x1f449; 【目录】ARM/TEE/ATF/SOC微信群问题记录 &#x1f448;&#x1f448;&#x1f448; 付费专栏-付费课程 【购买须知】: 问 &#xff1a; 8核的A72 多核启动 目前用的spin-table的方式&#xff0c;想尝试一下psci方式&…

Redis事务、管道

一.Redis事务 1.概念 可以一次执行多个命令&#xff0c;本质是一组命令的集合。一个事务中的所有命令都会序列化&#xff0c;按顺序地串行化执行而不会被其它命令插入&#xff0c;不许加塞 2.Redis事务与数据库事物的区别 3.常用命令 4.事务执行情况 正常执行 即整个过程…

全国高校招投标信息在哪里看?

很多投标人在查询招标信息的时候常常没有找到合适的&#xff0c;但是现在网上查询投标信息的网站是很多的。而学校招标信息获取的渠道是比较少的&#xff0c;企业的反而更多一些&#xff0c;那么我们能在那些渠道获取这些信息&#xff1f; 1.教育部网站 教育部提供了招标信息…

LeetCode 周赛上分之旅 # 36 KMP 字符串匹配殊途同归

⭐️ 本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 和 BaguTree Pro 知识星球提问。 学习数据结构与算法的关键在于掌握问题背后的算法思维框架&#xff0c;你的思考越抽象&#xff0c;它能覆盖的问题域就越广&#xff0c;理解难度…

Java精通 —— 一篇文章弄懂锁

前言 在Java中为了保证操作线程的安全性&#xff0c;我们引入了锁的概念&#xff0c;但随之而来的性能问题让我们在不愿意放弃安全性保证的前提下提出了优化过的锁。在这篇文章中&#xff0c;荔枝会着重梳理不同的锁的概念和普通锁的执行机制相关知识&#xff0c;同时也会对Jav…

【CAS6.6源码解析】深度解析票据淘汰与过期策略-探究数据淘汰策略的设计

票据作为一种时效很敏感的数据&#xff0c;其过期策略的设计对其功能性和性能影响很大。本文将深度解析票据淘汰与过期策略&#xff0c;并基于此探究数据淘汰策略的设计&#xff0c;让我们一起走进企业级中央认证中心CAS的源码&#xff0c;分析其设计的巧妙之处。 文章重点分析…

二十三种设计模式第二十二篇--中介者模式

说到这个模式就有趣了&#xff0c;不知道大家在生活中喷到过中介没&#xff1f;其实中介这个词吧&#xff0c;我也说不上好还是坏&#xff0c;有时候他可以帮助人们更快的达到某个目的&#xff0c;但有的时候吧&#xff0c;这个有贼坑人&#xff0c;相信网络上有各种被中介坑的…

Redis场景应用:详细实现网站粉丝关注与展示的功能

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。多年电商行业从业经验&#xff0c;对系统架构&#xff0c;数据分析处理等大规模应用场景有丰富经验。 &#x1f3c6;本文…

嵌入式Linux下 i2c-tool工具的使用方法 包括i2cdetect、i2cget、i2cset、i2cdump、i2ctransfer

要想用Linux i2c-tools必须安装如下套件&#xff0c;安装后就可以使用i2cdetect、i2cdump、i2cset、i2cget、i2ctransfer了。 sudo apt install i2c-tools -yi2cdetect命令 该命令用于扫描I2C总线上的设备。 语法&#xff1a;i2cdetect [-y] [-a] [-q|-r] i2cbus [first las…

[论文笔记] chatgpt系列 2.6 DeepSpeed-chat 数据集

一、FT数据集 & Reward model数据集 Deepspeed-chat 源代码的数据集: Dahoas/rm-static: 这是一个用于强化学习的静态环境数据集,包含了一个机器人在一个固定环境中的运动轨迹。该数据集旨在用于评估强化学习算法在静态环境下的表现。 Dahoas/full-hh-rlhf: 这是一个用于…

二十三种设计模式第二十四篇--访问者模式(完结撒花)

在访问者模式&#xff08;Visitor Pattern&#xff09;中&#xff0c;我们使用了一个访问者类&#xff0c;它改变了元素类的执行算法。 通过这种方式&#xff0c;元素的执行算法可以随着访问者改变而改变。 这种类型的设计模式属于行为型模式。根据模式&#xff0c;元素对象已接…

openGauss学习笔记-27 openGauss 高级数据管理- JOIN

文章目录 openGauss学习笔记-27 openGauss 高级数据管理- JOIN27.1 交叉连接27.2 内连接27.3 左外连接27.4 右外连接27.5 全外连接 openGauss学习笔记-27 openGauss 高级数据管理- JOIN JOIN子句用于把来自两个或多个表的行结合起来&#xff0c;基于这些表之间的共同字段。 在…

SLA探活工具EaseProbe

工具介绍 EaseProbe可以做三种工作&#xff1a;探测、通知和报告。 项目地址&#xff1a;https://github.com/megaease/easeprobe 1、安装 [rootlocalhost ]# yum -y install unzip go [rootlocalhost ]# unzip easeprobe-main.zip [rootlocalhost ]# cd easeprobe-main [r…

如祺出行冲刺自动驾驶商业化,人少的地方机会多?

网约车&#xff0c;正在迎来让人“不明觉厉”的新一轮竞赛。 网约车监管信息交互系统的数据显示&#xff0c;截至今年6月30日&#xff0c;全国共有318家网约车平台公司取得网约车平台经营许可&#xff0c;环比增加5家&#xff1b;网约车监管信息交互系统6月份共收到订单信息7.…