手写Spring:第9章-Aware感知容器对象

news2024/11/24 13:05:51

文章目录

  • 一、目标:Aware感知容器对象
  • 二、设计:Aware感知容器对象
  • 三、实现:Aware感知容器对象
    • 3.1 工程结构
    • 3.2 Spring感知接口类图
    • 3.3 定义标记接口和容器感知类
      • 3.3.1 定义标记接口
      • 3.3.2 对象工厂感知接口
      • 3.3.3 类加载感知接口
      • 3.3.4 对象名称感知接口
      • 3.3.5 应用上下文感知接口
    • 3.4 包装应用上下文处理器
      • 3.4.1 包装应用上下文处理器
      • 3.4.2 注册 BeanPostProcessor
    • 3.5 感知调用操作
      • 3.5.1 抽象对象工厂
      • 3.5.2 感知调用操作
  • 四、测试:Awrae感知容器对象
    • 4.1 修改UserDao用户对象
    • 4.2 单元测试
  • 五、总结:Aware感知容器对象

一、目标:Aware感知容器对象

💡 如何在获得 Spring 的功能时做些扩展框架的使用该怎么操作?

  • 目前实现的 Spring 框架中,在 Bean 操作上提供的能力,包括:
    • Bean 对象的定义和注册。
    • 操作 Bean 对象过程中执行的 BeanFactoryPostProcessorBeanFactoryPostProcessorInitializingBeanDisposableBean
  • XML 新增的一些配置处理,让我们可以对 Bean 对象有更强的操作性。
  • 那么,如果我们想获得 Spring 框架提供的 BeanFactoryApplicationContextBeanClassLoader 等这些功能做一些扩展框架的使用时该怎么操作呢?
    • 所以我们希望在 Spring 框架中提供一种能感知容器操作的接口,如果谁实现类这样的接口,就可以获取接口入参中的各类能力。

二、设计:Aware感知容器对象

💡 希望拿到 Spring 框架中一些提供的资源,那么首先需要考虑以一个什么方式去获取,之后定义出来的获取方式,在 Spring 该怎么去承接?
实现了这两项内容,就可以扩展出你需要的一些属于 Spring 框架本身的能力了。

  • Bean 对象实例化阶段我们操作过一些额外定义、属性、初始化和销毁的操作,其实如果像获取 Spring 一些如 BeanFactoryApplicationContext 时,也可以通过此类方式进行实现。
    • 需要定义一个标记性的接口,这个接口不需要有方法,它只起到标记作用。
    • 而具体的功能由继承此接口的其他功能性接口定义具体方法,最终这个接口就可以通过 instanceof 进行判断和调用。

在这里插入图片描述

  • 定义接口 Aware,在 Spring 框架中它是一种感知标记性接口,具体的子类定义和实现能感知容器中的相关对象。
    • 也就是通过这个桥梁,向具体的实现类中提供容器服务
  • 继承 Aware 的接口包括:BeanFactoryAwareBeanClassLoaderAwareBeanNameAwareApplicationContextAware
  • 在具体的接口实现过程中看到,
    • 一部分(BeanFactoryAwareBeanClassLoaderAwareBeanNameAware)在 factorysupport 文件夹下。
    • 另外(ApplicationContextAware)是在 contextsupport 中。
  • 这是因为不同的内容获取需要在不同的包下提供。所以:
    • AbstractApplicationContext 的具体实现中会用到向 beanFactory 添加 BeanPostProcessor 内容的 ApplicationContextAwareProcessor 操作。
    • 最后由 AbstractAutowireCapableBeanFactory 创建 createBean 时处理相应的调用操作。

三、实现:Aware感知容器对象

3.1 工程结构

spring-step-08
|-src
	|-main
	|	|-java
	|		|-com.lino.springframework
	|			|-beans
	|			|	|-factory
	|			|	|	|-config
	|			|	|	|	|-AutowireCapableBeanFactory.java
	|			|	|	|	|-BeanDefinition.java
	|			|	|	|	|-BeanFactoryPostProcessor.java
	|			|	|	|	|-BeanPostProcessor.java
	|			|	|	|	|-BeanReference.java
	|			|	|	|	|-ConfigurableBeanFactory.java
	|			|	|	|	|-SingletonBeanRegistry.java
	|			|	|	|-support
	|			|	|	|	|-AbstractAutowireCapableBeanFactory.java
	|			|	|	|	|-AbstractBeabDefinitionReader.java
	|			|	|	|	|-AbstractBeabFactory.java
	|			|	|	|	|-BeabDefinitionReader.java
	|			|	|	|	|-BeanDefinitionRegistry.java
	|			|	|	|	|-CglibSubclassingInstantiationStrategy.java
	|			|	|	|	|-DefaultListableBeanFactory.java
	|			|	|	|	|-DefaultSingletonBeanRegistry.java
	|			|	|	|	|-DisposableBeanAdapter.java
	|			|	|	|	|-InstantiationStrategy.java
	|			|	|	|	|-SimpleInstantiationStrategy.java
	|			|	|	|-support
	|			|	|	|	|-XMLBeanDefinitionReader.java
	|			|	|	|-Aware.java
	|			|	|	|-BeanClassLoaderAware.java
	|			|	|	|-BeanFactory.java
	|			|	|	|-BeanFactoryAware.java
	|			|	|	|-BeanNameAware.java
	|			|	|	|-ConfigurableListableBeanFactory.java
	|			|	|	|-DisposableBean.java
	|			|	|	|-HierarcgicalBeanFactory.java
	|			|	|	|-InitializingBean.java
	|			|	|	|-ListableBeanFactory.java
	|			|	|-BeansException.java
	|			|	|-PropertyValue.java
	|			|	|-PropertyValues.java
	|			|-context
	|			|	|-support
	|			|	|	|-AbstractApplicationContext.java
	|			|	|	|-AbstractRefreshableApplicationContext.java
	|			|	|	|-AbstractXmlApplicationContext.java
	|			|	|	|-ApplicationContextAwareProcessor.java
	|			|	|	|-ClassPathXmlApplicationContext.java
	|			|	|-ApplicationContext.java
	|			|	|-ApplicationContextAware.java
	|			|	|-ConfigurableApplicationContext.java
	|			|-core.io
	|			|	|-ClassPathResource.java
	|			|	|-DefaultResourceLoader.java
	|			|	|-FileSystemResource.java
	|			|	|-Resource.java
	|			|	|-ResourceLoader.java
	|			|	|-UrlResource.java
	|			|-util
	|			|	|-ClassUtils.java
	|-test
		|-java
			|-com.lino.springframework.test
                |-bean
                |	|-UserDao.java
                |	|-UserService.java
                |-ApiTest.java
		|-resources
			|-spring.xml

3.2 Spring感知接口类图

在这里插入图片描述

  • 整个类关系就是关于 Aware 感知的定义和对容器感知的实现。
  • Aware 有四个继承的接口,其他这些接口的继承都是为了继承一个标记,有了标记的存在更方便类的操作和具体判断实现。
  • 另外由于 ApplicationContext 并不是在 AbstractAutowireCapableBeanFactorycreateBean 方法下的内容。
    • 所以需要像容器中注册 addBeanPostProcessor,再由 createBean 统一调用 applyBeanPostProcessorBeforeInitialization 时进行操作。

3.3 定义标记接口和容器感知类

3.3.1 定义标记接口

Aware.java

package com.lino.springframework.beans.factory;

/**
 * @description: 标记类接口,实现该接口可以被Spring容器感知
 */
public interface Aware {
}
  • Spring 中有特别多类似这样的标记接口的设计方式,它们的存在就像是一种标签一样,可以方便统一摘取出属于此类接口的实现类,通常会有 instanceof 一起判断使用。

3.3.2 对象工厂感知接口

BeanFactoryAware.java

package com.lino.springframework.beans.factory;

import com.lino.springframework.beans.BeansException;

/**
 * @description: 实现此接口,即能感知到所属的 BeanFactory
 */
public interface BeanFactoryAware extends Aware {

    /**
     * 设置对象工厂
     *
     * @param beanFactory 对象工厂
     * @throws BeansException 异常
     */
    void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
  • 实现此接口,即能感知到所属的 BeanFactory

3.3.3 类加载感知接口

BeanClassLoaderAware.java

package com.lino.springframework.beans.factory;

/**
 * @description: 实现此接口,即能感知到所属的 ClassLoader
 */
public interface BeanClassLoaderAware extends Aware {

    /**
     * 设置类加载器
     *
     * @param classLoader 类加载器
     */
    void setBeanClassLoader(ClassLoader classLoader);
}
  • 实现此接口,即能感知到所属的 ClassLoader

3.3.4 对象名称感知接口

BeanNameAware.java

package com.lino.springframework.beans.factory;

/**
 * @description: 实现此接口,即能感知到所属的 BeanName
 */
public interface BeanNameAware {

    /**
     * 设置对象名称
     *
     * @param name 对象名称
     */
    void setBeanName(String name);
}
  • 实现此接口,即能感知到所属的 BeanName

3.3.5 应用上下文感知接口

ApplicationContextAware.java

package com.lino.springframework.context;

import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.factory.Aware;

/**
 * @description: 实现此接口,即能感知到所属的 ApplicationContext
 */
public interface ApplicationContextAware extends Aware {

    /**
     * 设置应用上下文
     *
     * @param applicationContext 应用上下文
     * @throws BeansException 异常
     */
    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
  • 实现此接口,即能感知到所属的 ApplicationContext

3.4 包装应用上下文处理器

3.4.1 包装应用上下文处理器

ApplicationContextAwareProcessor.java

package com.lino.springframework.context.support;

import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.factory.config.BeanPostProcessor;
import com.lino.springframework.context.ApplicationContext;
import com.lino.springframework.context.ApplicationContextAware;

/**
 * @description: 通过 BeanPostProcessor 实现类感知应用上下文对象
 */
public class ApplicationContextAwareProcessor implements BeanPostProcessor {

    private final ApplicationContext applicationContext;

    public ApplicationContextAwareProcessor(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(applicationContext);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}
  • 由于 ApplicationContext 的获取并不能直接在创建 Bean 时候就可以拿到,所以需要在 refresh 操作时,把 ApplicationContext 写入到一个包装的 BeanPostProcessor 中去,再由 AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization 方法调用。

3.4.2 注册 BeanPostProcessor

AbstractApplicationContext.java

package com.lino.springframework.context.support;

import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.factory.ConfigurableListableBeanFactory;
import com.lino.springframework.beans.factory.config.BeanFactoryPostProcessor;
import com.lino.springframework.beans.factory.config.BeanPostProcessor;
import com.lino.springframework.context.ConfigurableApplicationContext;
import com.lino.springframework.core.io.DefaultResourceLoader;
import java.util.Map;

/**
 * @description: 抽象应用上下文
 */
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {

    @Override
    public void refresh() throws BeansException {
        // 1.创建 BeanFactory,并加载 BeanDefinition
        refreshBeanFactory();

        // 2.获取 BeanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();

        // 3.添加 ApplicationContextAwareProcessor,让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

        // 4.在 Bean 实例化之前,执行 BeanFactoryPostProcess
        invokeBeanFactoryPostProcessor(beanFactory);

        // 5.BeanPostProcessor 需要提前与其他 Bean 对象实例化之前执行注册操作
        registerBeanPostProcessor(beanFactory);

        // 6.提前实例化单例 Bean 对象
        beanFactory.preInstantiateSingletons();
    }

    ...
}
  • refresh() 方法就是整个 Spring 容器的操作过程,这次新增加了 addBeanPostProcessor 操作。
  • 添加 ApplicationContextAwareProcessor,让继承自 ApplicationContextAwareBean 对象都能感知所属的 ApplicationContext

3.5 感知调用操作

3.5.1 抽象对象工厂

AbstractBeanFactory.java

package com.lino.springframework.beans.factory.support;

import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.factory.config.BeanDefinition;
import com.lino.springframework.beans.factory.config.BeanPostProcessor;
import com.lino.springframework.beans.factory.config.ConfigurableBeanFactory;
import com.lino.springframework.util.ClassUtils;
import java.util.ArrayList;
import java.util.List;

/**
 * @description: 抽象的 Bean 工厂基类,定义模板方法
 */
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements ConfigurableBeanFactory {

    private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();

    private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();

    ...

    public ClassLoader getBeanClassLoader() {
        return this.beanClassLoader;
    }
}
  • 添加 ClassLoader 对像,并提供一个获取对象类加载器的方法。getBeanClassLoader()

3.5.2 感知调用操作

AbstractAutowireCapableBeanFactory.java

package com.lino.springframework.beans.factory.support;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.PropertyValue;
import com.lino.springframework.beans.PropertyValues;
import com.lino.springframework.beans.factory.*;
import com.lino.springframework.beans.factory.config.AutowireCapableBeanFactory;
import com.lino.springframework.beans.factory.config.BeanDefinition;
import com.lino.springframework.beans.factory.config.BeanPostProcessor;
import com.lino.springframework.beans.factory.config.BeanReference;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * @description: 实现默认bean创建的抽象bean工厂超类
 * @author: lingjian
 * @createDate: 2022/11/22 14:39
 */
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

    private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

    ...

    private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {

        // invokeAwareMethods
        if (bean instanceof Aware) {
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(this);
            }
            if (bean instanceof BeanClassLoaderAware) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
            }
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
        }

        // 1.执行 BeanPostProcessor Before 处理
        Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);

        // 执行 Bean 对象的初始化方法
        try {
            invokeInitMethods(beanName, wrappedBean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);
        }

        // 2.执行 BeanPostProcessor After 处理
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        return wrappedBean;
    }

    ...
}
  • 首先在 initializeBean 中,通过判断 bean instanceof Aware,调用三个接口方法。这样就能通知到已经实现了此接口的类。
    • ((BeanFactoryAware) bean).setBeanFactory(this)
    • ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader())
    • ((BeanNameAware) bean).setBeanName(beanName)
  • 另外还向 BeanPostProcessor 中添加了 ApplicationContextAwareProcessor,此时在这个方法中也会被调用到具体的类实现,得到一个 ApplicationContext 属性。

四、测试:Awrae感知容器对象

4.1 修改UserDao用户对象

UserService.java

package com.lino.springframework.test.bean;

import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.factory.*;
import com.lino.springframework.context.ApplicationContext;
import com.lino.springframework.context.ApplicationContextAware;

/**
 * @description: 模拟用户 Bean 对象
 */
public class UserService implements BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware {

    private ApplicationContext applicationContext;
    private BeanFactory beanFactory;

    private String uId;
    private String company;
    private String location;
    private UserDao userDao;

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("ClassLoader: " + classLoader);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("Bean Name is: " + name);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 查询用户信息
     */
    public String queryUserInfo() {
        return userDao.queryUserName(uId) + "," + company + "," + location;
    }

    public String getuId() {
        return uId;
    }

    public void setuId(String uId) {
        this.uId = uId;
    }

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public BeanFactory getBeanFactory() {
        return beanFactory;
    }
}
  • 新增加 BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware 四个感知的实现类,并在类中的实现相应的接口方法。

4.2 单元测试

ApiTest.java

@Test
public void test_xml() {
    // 1.初始化 BeanFactory
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
    applicationContext.registerShutdownHook();

    // 2.获取Bean对象调用方法
    UserService userService = applicationContext.getBean("userService", UserService.class);
    String result = userService.queryUserInfo();
    System.out.println("测试结果:" + result);
    System.out.println("ApplicationContextAware: " + userService.getApplicationContext());
    System.out.println("BeanFactoryAware: " + userService.getBeanFactory());
}
  • 测试方法中添加了一写关于新增 Aware 实现的调用,其他不需要调用的也打印了相应的日志信息,可以在测试结果中看到。

测试结果

执行:init-method
ClassLoader: sun.misc.Launcher$AppClassLoader@18b4aac2
Bean Name is: userService
测试结果:张三,阿里,杭州
ApplicationContextAware: com.lino.springframework.context.support.ClassPathXmlApplicationContext@56cbfb61
BeanFactoryAware: com.lino.springframework.beans.factory.support.DefaultListableBeanFactory@1134affc
执行:destroy-method
  • 从测试结果来看,新增加的感知接口对应的具体实现(BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware),已经可以正常输出结果。

五、总结:Aware感知容器对象

  • 本节关于 Aware 的感知接口的四个继承接口 BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware 的实现,又扩展了 Spring 的功能。
  • 目前关于 Spring 框架的实现中,功能已经越来越趋向于完整,尤其对于 Bean 对象的生命周期。
    在这里插入图片描述

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

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

相关文章

智慧排水监测系统:实时监测城市排水情况

中国智慧城市概念最初由住建部提出&#xff0c;随着智慧城市建设的广泛实践&#xff0c;对其认知也在不断深入与变化。2014年&#xff0c;国家发改委从数字化与技术角度认为:智慧城市是运用物联网、云计算、大数据、空间地理信息集成等新一代信息技术&#xff0c;促进城市规划、…

实现SSE的textevent-stream是什么?和applicationoctet-stream有什么区别?

WEB通讯技术。前端实现SSE长连接&#xff0c;nodejsexpress搭建简单服务器&#xff0c;进行接口调试&#xff0c;通过curl请求数据 点击上面的地址是可以了解轮询和长轮询以及websocket等通信模式&#xff0c;一些基础概念和速成技能&#xff0c;这篇来接着详细聊聊text/event…

电影《孤注一掷》引发观众思考网络安全

近日上映的电影《孤注一掷》深刻地揭示了境外网络诈骗的全产业链&#xff0c;上万起真实诈骗案例为素材&#xff0c;让观众近距离感受这一犯罪行为的阴谋与可怕。影片呈现了从诈骗策划到资金流转的每一个环节&#xff0c;引发了观众的强烈好奇和观看欲望。这种真实性让观众对网…

MITSUBISHI A1SJ51T64电源单元

电源供应&#xff1a;A1SJ51T64 电源单元通常用于为MITSUBISHI PLC系统提供稳定的电源&#xff0c;以确保系统正常运行。 电源输入&#xff1a;它通常支持广泛的电源输入范围&#xff0c;以适应不同地区的电源标准。 电源输出&#xff1a;A1SJ51T64 电源单元通常提供多个电源…

【C++基础】6、常量

文章目录 【 1、常量的分类 】1.1 整型常量1.2 浮点常量1.3 字符常量1.4 字符串常量1.5 布尔常量 【 2、常量的定义 】2.1 #define 预处理器2.2 const 关键字 常量 是固定值&#xff0c;在程序执行期间不会改变。这些固定的值&#xff0c;又叫做字面量。常量可以是任何的基本数…

22行 手写实现promise

面试题 const MyPromise()>{}const myPromise new MyPromise((resolve) > {setTimeout(() > { resolve(hellow world) }, 2000)})myPromise.then((res) > {console.log(res)return "00"}) 手写promise&#xff0c;面试了一个面试题&#xff0c;promise…

【管理运筹学】第 7 章 | 图与网络分析(1,图论背景以及基本概念、术语、矩阵表示)

文章目录 引言一、图与网络的基本知识1.1 图与网络的基本概念1.1.1 图的定义1.1.2 图中相关术语1.1.3 一些特殊图类1.1.4 图的运算 1.2 图的矩阵表示1.2.1 邻接矩阵1.2.2 可达矩阵1.2.3 关联矩阵1.2.4 权矩阵 写在最后 引言 按照正常进度应该学习动态规划了&#xff0c;但我想…

Java/Lombok Slf4j日志配置输出到文件中

1、概述 新项目需要增加日志需求&#xff0c;所以网上找了下日志配置&#xff0c;需求是将日志保存到指定文件中。网上找了下文章&#xff0c;发现没有特别完整的文章&#xff0c;下面自己整理下。 1、Java日志概述 对于一个应用程序来说日志记录是必不可少的一部分。线上问题…

每日刷题(回溯法经典问题之子集)

食用指南&#xff1a;本文为作者刷题中认为有必要记录的题目 前置知识&#xff1a;回溯法经典问题之组合 ♈️今日夜电波&#xff1a;想着你—郭顶 1:09 ━━━━━━️&#x1f49f;──────── 4:15 …

Java“牵手”微店商品列表数据,关键词搜索微店商品数据接口,微店API申请指南

微店商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取微店商品列表和商品详情页面数据&#xff0c;您可以通过开放平台的接口或者直接访问微店商城的网页来获取商品详情信息。以下是两种常用方法的介绍&…

电子元器件采购中的供应链透明度

在电子元器件采购中&#xff0c;供应链透明度是一个至关重要的因素。它指的是能够清晰、实时地了解整个供应链的运作和流程&#xff0c;以及相关的信息和数据。供应链透明度在采购中具有多方面的优势和重要性&#xff0c;包括以下方面&#xff1a; 库存管理&#xff1a; 透明的…

『C语言进阶』指针进阶(一)

&#x1f525;博客主页&#xff1a; 小羊失眠啦 &#x1f516;系列专栏&#xff1a; C语言 &#x1f325;️每日语录&#xff1a;无论你怎么选&#xff0c;都难免会有遗憾。 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 前言 在C语言初阶中&#xff0c;我们对指针有了一定的…

交叉编译嵌入式linux平台的gdb工具

目录 前期准备&#xff1a; 开始编译&#xff1a; 配置编译环境&#xff1a; 配置交叉编译工具链&#xff1a; 创建交叉编译产物的目录&#xff1a; termcap&#xff1a; ncurses&#xff1a; gmp&#xff1a; gdb&#xff1a; 编译产物&#xff1a; 前期准备&#x…

IT设备监控软件有哪些功能

IT设备监控软件通常可以实现以下功能&#xff1a;  设备状态监控&#xff1a;可以实时监测IT设备的运行状态&#xff0c;如设备的温度、湿度、风扇转速等&#xff0c;以及设备的开机、关机、重启等事件。  性能指标监控&#xff1a;可以监测IT设备的各项性能指标&#xff0…

rtthread下spi device架构MCP25625驱动

1.CAN驱动架构 由于采用了RTT的spi device架构&#xff0c;不能再随心所遇的编写CAN驱动 了&#xff0c;之前内核虽然采用了RTT内核&#xff0c;但是驱动并没有严格严格按RTT推荐的架构来做&#xff0c;这次不同了&#xff0c;上次是因为4个MCP25625挂在了4路独立的SPI总线上&…

前端(十六)——Web应用的安全性研究

&#x1f642;博主&#xff1a;小猫娃来啦 &#x1f642;文章核心&#xff1a;Web应用的安全性研究 文章目录 概述常见前端安全漏洞XSS&#xff08;跨站脚本攻击&#xff09;CSRF&#xff08;跨站请求伪造&#xff09; 点击劫持安全性验证与授权用户身份验证授权与权限管理 安全…

“搭载超快闪充、续航自由、天玑8200性能” iQOO Z8系列发布

近日&#xff0c;“天玑 8200 性能小超人”iQOO Z8系列正式发布&#xff0c;包括iQOO Z8和iQOO Z8x两款产品&#xff0c;首销售价1199元起。 “天玑 8200 性能小超人”iQOO Z8倾力打造“最佳千元性能机”&#xff1a;搭载具备巅峰性能的天玑 8200 &#xff0c;携手满血版LPDDR…

熵 | 无线通信知识

文章目录 一、信息论&#xff08;熵、联合熵、条件熵&#xff09;二、Bernoulli熵三、联合熵和条件熵四、互信息五、相对熵(KL距离)常需要的不等式公式 一、信息论&#xff08;熵、联合熵、条件熵&#xff09; 熵定义&#xff1a; H ( X ) E [ − l o g 2 p ( x ) ] − ∑ x…

【算法|链表】移除链表元素

算法|链表-移除链表元素 关于链表的介绍以及相关实现操作&#xff0c;见单链表&#xff0c;双链表 leetcode 203 移除链表元素 题意&#xff1a;删除链表中等于给定值 val 的所有节点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1…

Unity3D之动态生成指定数量带间隔的地面

文章目录 准备代码实现实现效果 准备 空物体生成脚本地面预制体 代码实现 using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; using UnityEngine;public class CreateGround : MonoBehaviour {[SerializeField]public i…