你真的了解Spring的依赖查找吗?

news2024/10/6 12:26:56

1.写在前面

前面的博客我们介绍了Spring的总览,今天我们来了解下Spring的依赖查找的相关的内容,我们会从它的前世今生来带你了解下,以及各种类型的查找的方式,同时介绍对应的相对比较安全的查找的方式。以及会介绍一些比较常见的面试题,供大家参考。

2.依赖查找的今世前生

那么提到依赖查找,很多人第一个想到的就是Spring中的依赖查找,但是在Spring出来之前,Java中其实已经就有了依赖查找的API了,具体的如下,同时Spring也参考其中的一部分。

单一类型依赖查找

  • JNDI - javax.naming.Context#lookup(javax.naming.Name)
  • JavaBeans - java.beans.beancontext.BeanContext

集合类型依赖查找

  • java.beans.beancontext.BeanContext

层次性依赖查找

  • java.beans.beancontext.BeanContext

单一类型的依赖查找

那么我这儿先带大家看下对应的源码,后面再带着大家写几个例子,首先我们先看对应的Java中的Context类,具体的如下:

在这里插入图片描述

上面的两个方法都是javax.naming.Context提供的Bean的查找的方法。

接下来我们继续看一下BeanContext,这个BeanContextSpring参考对应的实现的方式。具体的内容如下:

在这里插入图片描述

可以看到这接口继承的了Collection接口,我们可以知道这个接口下面所有的Bean都是存在这个集合下面的,对这个集合进行增删改查。

集合类型依赖查找

集合类型查找是根据一个key去查找出来一个集合的类型。

在这里插入图片描述

对应的方法如上图所示,返回的是一个object对象,也就是集合的对象也是可以返回的

层次性依赖查找BeanContext的源码写的比较混乱,这儿我们不做介绍了。

3.单一类型依赖查找

单一类型依赖查找接口 - BeanFactory

  • 根据 Bean 名称查找
    • getBean(String)
    • Spring 2.5 覆盖默认参数: getBean(String,Object…)
  • 根据 Bean 类型查找
    • Bean 实时查找
      • Spring 3.0 getBean(Class)
      • Spring 4.1 覆盖默认参数: getBean(Class,Object…)
    • Spring 5.1 Bean 延迟查找
      • getBeanProvider(Class)
      • getBeanProvider(ResolvableType)
  • 根据 Bean 名称 + 类型查找: getBean(String,Class)

上面的有些的查找的方式我们前面的博客已经介绍过了,上面的覆盖默认参数的方式,我们只要知道有这个方法就行了,不需要做过多的了解,因为这个方法比较危险,它会覆盖默认的参数。

在这里插入图片描述

在这里插入图片描述

我们看一下对应的5.1的延迟查找的API,具体的如下:

在这里插入图片描述

这儿我们可以看到返回的是ObjectProvider,我们点开这个实现类的内容,具体的如下:

在这里插入图片描述

可以发现这个类是继承了ObjectFactory类的,那么一切都那么好理解了。

我们写了一个简单的例子就行,具体的代码如下:

package org.learn.spring.dependency.lookup;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;

// 通过 ObjectProvider 进行依赖查找
public class ObjectProviderDemo {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

        // 将当前类ObjectProviderDemo 作为配置类(configuration class)
        applicationContext.register(ObjectProviderDemo.class);
        // 启动应用上下文
        applicationContext.refresh();

        lookupByObjectProvider(applicationContext);
        applicationContext.close();
    }

    private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {
        ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
        System.out.println(objectProvider.getObject());
    }

    // 方法的名称就是Bean的名称, Bean的名称helloWorld
    @Bean
    public String helloWorld(){
        return "Hello World";
    }
}

还有一个getBeanProvider(ResolvableType)这个方法我们后面再说,ResolvableType这个类型主要是用来处理泛型的。等到后面我们介绍泛型的时候,我们再来详细的介绍。

4.集合类型依赖查找

集合类型依赖查找接口 - ListableBeanFactory

  • 根据 Bean 类型查找
  • 获取同类型 Bean 名称列表
    • getBeanNamesForType(Class)
    • Spring 4.2 getBeanNamesForType(ResolvableType)
  • 获取同类型 Bean 实例列表
    • getBeansOfType(Class) 以及重载方法
  • 通过注解类型查找
    • Spring 3.0 获取标注类型 Bean 名称列表
      • getBeanNamesForAnnotation(Class<? extends Annotation>)
    • Spring 3.0 获取标注类型 Bean 实例列表
      • getBeansWithAnnotation(Class<? extends Annotation>)
    • Spring 3.0 获取指定名称 + 标注类型 Bean 实例
      • findAnnotationOnBean(String,Class<? extends Annotation>)

上面的API我前面都有或多或少的介绍过,我这儿不做赘述了,从上面的API我们可以得到一个结论就是ListableBeanFactory主要用来查找集合的。而方式有两种一种是通过Bean的类型查找,一种是通过注解的类型去查找。集合的列表主要有两种情况,一种查询Bean的名称的集合,一种是查询Bean的实例的集合。

5.层次性依赖查找

层次性依赖查找接口 - HierarchicalBeanFactory 将单一类型的查找和集合类型查找合并到一起去

  • 双亲 BeanFactory: getParentBeanFactory()
  • 层次性查找
    • 根据 Bean 名称查找
      • 基于 containsLocalBean 方法实现
    • 根据 Bean 类型查找实例列表
      • 单一类型: BeanFactoryUtils#beanOfType
      • 集合类型: BeanFactoryUtils#beansOfTypeIncludingAncestors
    • 根据 Java 注解查找名称列表
      • BeanFactoryUtils#beanNamesForTypeIncludingAncestors

具体的代码如下:

package org.learn.spring.dependency.lookup;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

// HierarchicalBeanFactory 层次查找依赖实例
public class HierarchicalDependencyLookup {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

        // 将当前类ObjectProviderDemo 作为配置类(configuration class)
        applicationContext.register(ObjectProviderDemo.class);

        // 1.获取HierarchicalBeanFactory <- ConfigurableBeanFactory <- ConfigurableListableBeanFactory
        ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
        System.out.println("当前BeanFactory 的 Parent BeanFactory:" + beanFactory.getParentBeanFactory());

        // 2.设置ParentBeanFactory
        HierarchicalBeanFactory parentBeanFactory = createParentBeanFactory();
        beanFactory.setParentBeanFactory(parentBeanFactory);
        System.out.println("当前BeanFactory 的 Parent BeanFactory:" + beanFactory.getParentBeanFactory());

        // 启动应用上下文
        applicationContext.refresh();
        displayContainsLocalBean(beanFactory, "user");
        displayContainsLocalBean(parentBeanFactory, "user");

        displayContainsBean(beanFactory, "user");
        displayContainsBean(parentBeanFactory, "user");

        applicationContext.close();
    }

    private static ConfigurableListableBeanFactory createParentBeanFactory() {
        // 创建BeanFactory容器
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        // XML 配置文件的路径
        String location = "classpath:META-INF/dependency-lookup-context.xml";
        // 加载配置
        reader.loadBeanDefinitions(location);
        return beanFactory;
    }

    private static void displayContainsLocalBean(HierarchicalBeanFactory beanFactory, String beanName) {
        System.out.printf("当前 BeanFactory[%s] 是否包含 Local Bean [name : %s] : %s\n", beanFactory, beanName, beanFactory.containsLocalBean(beanName));
    }

    private static void displayContainsBean(HierarchicalBeanFactory beanFactory, String beanName) {
        System.out.printf("当前 BeanFactory[%s] 是否包含 Bean [name : %s] : %s\n", beanFactory, beanName, containsBean(beanFactory, beanName));
    }

    private static boolean containsBean(HierarchicalBeanFactory beanFactory, String beanName) {
        BeanFactory parentBeanFactory = beanFactory.getParentBeanFactory();
        if (parentBeanFactory instanceof HierarchicalBeanFactory) {
            HierarchicalBeanFactory parentHierarchicalBeanFactory = HierarchicalBeanFactory.class.cast(parentBeanFactory);
            if (containsBean(parentHierarchicalBeanFactory, beanName)) {
                return true;
            }
        }
        return beanFactory.containsLocalBean(beanName);
    }
}

上面的代码就是实现了层次的查找,这个时候是有两个工厂,一个是父工厂,一个子工厂,containsBean方法就是通过递归的方式来查找所有的工厂中包含的对应的Bean。

其实BeanFactoryUtils有相应的实现,具体的的代码如下:

在这里插入图片描述

6.延迟依赖查找

Bean 延迟依赖查找接口

  • org.springframework.beans.factory.ObjectFactory
  • org.springframework.beans.factory.ObjectProvider
    • Spring 5 对 Java 8 特性扩展
    • 函数式接口
      • getIfAvailable(Supplier)
      • ifAvailable(Consumer)
    • Stream 扩展 - stream()

具体的代码如下:

package org.learn.spring.dependency.lookup;

import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;

// 通过 ObjectProvider 进行依赖查找
public class ObjectProviderDemo {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

        // 将当前类ObjectProviderDemo 作为配置类(configuration class)
        applicationContext.register(ObjectProviderDemo.class);
        // 启动应用上下文
        applicationContext.refresh();

        lookupByAvailable(applicationContext);
        lookupByStreamOps(applicationContext);
        applicationContext.close();
    }

    private static void lookupByStreamOps(AnnotationConfigApplicationContext applicationContext) {
        ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
        Iterable<String> stringIterable = objectProvider;
        for (String s : stringIterable) {
            System.out.println(s);
        }
        objectProvider.stream().forEach(System.out::println);
    }

    private static void lookupByAvailable(AnnotationConfigApplicationContext applicationContext) {
        ObjectProvider<User> userObjectProvider = applicationContext.getBeanProvider(User.class);
        User user = userObjectProvider.getIfAvailable(User::createUser);
        System.out.println("当前 User 对象:" + user);
    }

  
    @Bean
    @Primary
    public String helloWorld() {
        return "Hello World";
    }

    @Bean
    public String message() {
        return "Message";
    }
}

7.安全依赖查找

依赖查找安全性对比

在这里插入图片描述

注意: 层次性依赖查找的安全性取决于其扩展的单一或集合类型的 BeanFactory 接口

具体的代码如下:

package org.learn.spring.dependency.lookup;

import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

// 类型安全查找的示例
public class TypeSafetyDependencyLookupDemo {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

        // 将当前类ObjectProviderDemo 作为配置类(configuration class)
        applicationContext.register(ObjectProviderDemo.class);
        // 启动应用上下文
        applicationContext.refresh();

        // 演示BeanFactory#getBean方法的安全性 不安全的
        displayBeanFactoryGetBean(applicationContext);

        // 演示ObjectFactory#getObject方法的安全性 不安全的
        displayObjectFactoryGetObject(applicationContext);

        // 演示ObjectProvider#getIfAvailable方法的安全性 安全的
        displayObjectProviderGetIfAvailable(applicationContext);

        // 演示 ListableBeanFactory#getBeansOfType方法的安全性 安全的 也是会抛出BeansException 但是这个只有在Bean创建失败的时候抛出
        displayListableBeanFactoryGetBeansOfType(applicationContext);

        //演示ObjectProvider#StreamOps方法的安全性 安全的
        displayObjectProviderStreamOps(applicationContext);

        // 关闭应用上下文
        applicationContext.close();
    }

    // 不安全的
    public static void displayBeanFactoryGetBean(BeanFactory beanFactory) {
        printBeansException("displayBeanFactoryGetBean", () -> beanFactory.getBean(User.class));
    }

    private static void displayObjectFactoryGetObject(AnnotationConfigApplicationContext applicationContext) {
        // ObjectProvider is ObjectFactory
        ObjectFactory<User> userObjectProvider = applicationContext.getBeanProvider(User.class);
        printBeansException("displayObjectFactoryGetObject", userObjectProvider::getObject);
    }


    private static void displayObjectProviderGetIfAvailable(AnnotationConfigApplicationContext applicationContext) {
        ObjectProvider<User> userObjectProvider = applicationContext.getBeanProvider(User.class);
        printBeansException("displayObjectProviderGetIfAvailable", userObjectProvider::getIfAvailable);
    }

    // 也是会抛出BeansException 但是这个只有在Bean创建失败的时候抛出
    private static void displayListableBeanFactoryGetBeansOfType(ListableBeanFactory beanFactory) {
        printBeansException("displayListableBeanFactoryGetBeansOfType", () -> beanFactory.getBeansOfType(User.class));
    }

    private static void displayObjectProviderStreamOps(AnnotationConfigApplicationContext applicationContext) {
        ObjectProvider<User> userObjectProvider = applicationContext.getBeanProvider(User.class);
        printBeansException("displayObjectProviderStreamOps", () -> userObjectProvider.stream().forEach(System.out::println));
    }

    private static void printBeansException(String source, Runnable runnable) {
        System.err.println("===================================================================");
        System.err.println("Source from " + source);
        try {
            runnable.run();
        } catch (BeansException e) {
            e.printStackTrace();
        }
    }

}

运行结果如下:

在这里插入图片描述

可以看出与上面的表格是一样的。

8.内建可查找的依赖

AbstractApplicationContext 内建可查找的依赖

在这里插入图片描述

注解驱动 Spring 应用上下文内建可查找的依赖( 部分)

在这里插入图片描述

注解驱动 Spring 应用上下文内建可查找的依赖( 续)

在这里插入图片描述

那么这些类在什么地方注册的呢?具体的如下:

在这里插入图片描述

后面在初始化的流程中,我们会详细的分析,上面的代码是AnnotationConfigUtils类中的

9.依赖查找中的经典异常

BeansException 子类型

在这里插入图片描述

具体的代码如下:

演示NoUniqueBeanDefinitionException异常

package org.learn.spring.dependency.lookup;

import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;

// NoUniqueBeanDefinitionException 的异常举例
public class NoUniqueBeanDefinitionExceptionDemo {

    public static void main(String[] args) {
        // 创建BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

        // NoUniqueBeanDefinitionExceptionDemo 作为配置类(configuration class)
        applicationContext.register(NoUniqueBeanDefinitionExceptionDemo.class);

        // 启动应用上下文
        applicationContext.refresh();

        try {
            // 由于应用上下文存在两个String类型的Bean,通过单一查找会抛出异常
            applicationContext.getBean(String.class);
        } catch (NoUniqueBeanDefinitionException e) {
            System.err.printf("Spring 应用上下文存在 %d 个 %s 类型的Bean,具体的原因:%s", e.getNumberOfBeansFound(), e.getBeanType(), e.getMessage());
        }

        // 关闭应用上下文
        applicationContext.close();
    }

    @Bean
    public String bean1() {
        return "bean1";
    }

    @Bean
    public String bean2() {
        return "bean2";
    }
}

演示BeanInstantiationException异常

package org.learn.spring.dependency.lookup;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

// BeanInstantiationException 异常的示例
public class BeanInstantiationExceptionDemo {

    public static void main(String[] args) {
        // 创建BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

        // 注册BeanDefinition Bean Class 是CharSequence的接口
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(CharSequence.class);
        applicationContext.registerBeanDefinition("errorBean", beanDefinitionBuilder.getBeanDefinition());

        // 启动应用上下文
        applicationContext.refresh();

        // 关闭应用上下文
        applicationContext.close();
    }
}

演示BeanCreationException异常

package org.learn.spring.dependency.lookup;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

// BeanCreationException 异常示例
public class BeanCreationExceptionDemo {
    public static void main(String[] args) {
        // 创建BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

        // 注册BeanDefinition Bean Class 是POJO的普通类,不过在初始化方法回调时抛出异常
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(POJO.class);
        applicationContext.registerBeanDefinition("errorBean", beanDefinitionBuilder.getBeanDefinition());

        // 启动应用上下文
        applicationContext.refresh();

        // 关闭应用上下文
        applicationContext.close();
    }

    static class POJO implements InitializingBean {

        @Override
        public void afterPropertiesSet() throws Exception {
            throw new Exception("For purposes....");
        }
    }
}

10.面试题

10.1 ObjectFactory 与 BeanFactory 的区别?

ObjectFactory 与 BeanFactory 均提供依赖查找的能力。

不过 ObjectFactory 仅关注一个或一种类型的 Bean 依赖查找, 并且自身不具备依赖查找的能力, 能力则由 BeanFactory 输出。

BeanFactory 则提供了单一类型、 集合类型以及层次性等多种依赖查找方式。

10.2 BeanFactory.getBean 操作是否线程安全?

BeanFactory.getBean 方法的执行是线程安全的, 操作过程中会增加互斥锁

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

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

相关文章

分布式系统设计模式和一致性协议,你用过哪些?

1、布隆过滤器 Bloom过滤器是一种节省空间的概率数据结构&#xff0c;用于测试元素是否为某集合的成员。它用于我们只需要检查元素是否属于对象的场景。 在BigTable&#xff08;和Cassandra&#xff09;中&#xff0c;任何读取操作都必须从组成Tablet的SSTable中读取。如果这些…

用于光波导耦合的倾斜光栅分析

1. 摘要 因其在确定衍射级上的高衍射效率&#xff0c;倾斜光栅广泛用于将光耦合到光波导中。如今&#xff0c;倾斜光栅广泛用于增强现实和混合现实应用中。本示例中将示范如何使用VirtualLab Fusion分析文献中具有特定参数的某些倾斜光栅的几何形状&#xff08;例如倾斜角、填充…

Word控件Spire.Doc 【图像形状】教程(1) ;如何在 Word 中插入图像(C#/VB.NET)

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

使用OpenCV计算两幅图像的协方差

要计算协方差首先要知道协方差的数学原理。 定义 Cov(X,Y) E{ [X-E(X)][Y-E(Y)] }为随机量X与Y的协方差。 其中E(X)为随机变量X的期望(均值)&#xff0c;E(Y)为随机变量Y的期望(均值)。 我们通常用下面的这个公式计算协方差。 Cov(X,Y)E(XY)-E(X)E(Y) 另外&#xff0c;大家…

【苹果家庭群发推送】软件安装最新的Appletweetios.macosimessage是用于发送Apple文本消息

推荐内容IMESSGAE相关 作者推荐内容iMessage苹果推软件 *** 点击即可查看作者要求内容信息作者推荐内容1.家庭推内容 *** 点击即可查看作者要求内容信息作者推荐内容2.相册推 *** 点击即可查看作者要求内容信息作者推荐内容3.日历推 *** 点击即可查看作者要求内容信息作者推荐…

单商户商城系统功能拆解33—营销中心—包邮活动

单商户商城系统&#xff0c;也称为B2C自营电商模式单店商城系统。可以快速帮助个人、机构和企业搭建自己的私域交易线上商城。 单商户商城系统完美契合私域流量变现闭环交易使用。通常拥有丰富的营销玩法&#xff0c;例如拼团&#xff0c;秒杀&#xff0c;砍价&#xff0c;包邮…

热门Java开发工具IDEA入门指南——从Eclipse迁移到IntelliJ IDEA(三)

IntelliJ IDEA&#xff0c;是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的java开发工具&#xff0c;尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能是非常强大的。 本文…

React 基础

React 基础 1.React概述 目标&#xff1a;了解 React 是什么 官方文档&#xff08;英文&#xff09;,官方文档&#xff08;中文&#xff09; 官方释义&#xff1a; A JavaScript library for building user interfaces &#xff08;一个用于构建用户界面的 JavaScript 库&a…

FT2000+ arm64服务器 kylin server 虚拟机 编译fuse_dfs 解决挂载目录中的故障

服务器搭建 FT2000 arm64服务器 openEuler 部署hadoop单机伪集群并测试基准性能_hkNaruto的博客-CSDN博客 编译fuse相关程序 下载源码 wget https://dlcdn.apache.org/hadoop/common/hadoop-3.3.1/hadoop-3.3.1-src.tar.gz tar -xvf hadoop-3.3.1-src.tar.gz 安装工具、编…

干货!一文搞定无头浏览器的概念以及在selenium中的应用

无头浏览器 无头浏览器&#xff0c;即 Headless Browser&#xff0c;是一种没有界面的浏览器。它拥有完整的浏览器内核&#xff0c;包括 JavaScript 解析引擎、渲染引擎等。与普通浏览器最大的不同是&#xff0c;无头浏览器执行过程中看不到运行的界面&#xff0c;但是我们依然…

目标检测算法——工业缺陷数据集汇总2(附下载链接)

>>>深度学习Tricks&#xff0c;第一时间送达<<< &#x1f680;近期&#xff0c;小海带在空闲之余&#xff0c;收集整理了一批工业缺陷开源数据集供大家参考。 整理不易&#xff0c;小伙伴们记得一键三连喔&#xff01;&#xff01;&#xff01;&#x1f91e…

论微软过程

&#x1f430;作者简介&#xff1a;一位普通高校的在校学生&#xff0c;致力于提高自己的编程能力。 &#x1f34c;个人主页&#xff1a;比昨天强一點的博客_CSDN博客-C语言从0到精通领域博主 &#x1f34d;系列专栏&#xff1a;C语言从0到精通_比昨天强一點的博客-CSDN博客 &a…

Hadoop环境搭建-单机、伪分布式、完全分布式

目录 一、单机安装 二、伪分布式环境搭建 配置SSH免密登录 三、完全分布式环境搭建 设置免密 修改配置文件 本文的所有配置文件&#xff0c;除注释部分都可直接复制粘贴。因为本文的配置文件的语言语法采用的是HTML或JAVA&#xff0c;注释部分可能和linux系统上的不同&#xff…

Arcgis建筑面shp由DSM和DEM获取高度

效果 1、准备数据 DEM、DSM数据精度尽量高一些 1)DEM 2)DSM 3)建筑shp 所有数据坐标统一,而且加载后位置能对上 2、准备数据前的一些操作 1)矢量shp裁剪 2)栅格tif裁剪

【iOS】—— URL Scheme

URL Scheme URL Scheme是一个非常炫酷的东西&#xff0c;用法很简单,在我们平时使用app的时候&#xff0c;经常一不小心就点入广告&#xff0c;打开了其他的app或者打开了浏览器的某个网站&#xff0c;这个东西就用到了URL Scheme。 用法非常非常简单&#xff0c;最重要的只有…

3D 三角形的顶点顺序

在三维空间&#xff0c;一个表面是有正反之分的。WPF只会渲染正面&#xff0c;反面不渲染。 一个三角形有三个顶点&#xff0c;这三个顶点有一个排列顺序。 如下图画一个三角形&#xff0c; 定义顶点坐标&#xff0c;<MeshGeometry3D Positions"-1,0,0 0,-1,0 0,0,-1&…

抗CD4单抗偶联表阿霉素/单克隆抗体Zh805/特异性靶向肽A54偶联阿霉素的制备

小编给大家整理了抗CD4单抗偶联表阿霉素/单克隆抗体Zh805/特异性靶向肽A54偶联阿霉素的制备&#xff0c;一起来看看吧&#xff01; 抗CD4单抗偶联表阿霉素制备方法&#xff1a; 采用低分子右旋糖苷(DextranTl0)作联接桥,将表阿霉素分子偶联到抗CD4单抗上,制备成抗CD4单抗免疫结…

数字信号处理-2-三角函数与谱

1 弧度的定义 为了便于数学上的运算&#xff0c;设以半径为 1 的圆的中心为原点&#xff0c;x 轴正方向为基准测量角度。这样的圆为单位圆&#xff0c;此单位圆的长度为 1&#xff0c;在圆周上取与半径相同长度的圆弧&#xff0c;对应的角度为 1 弧度。 在三角函数中弧度能大大…

TPS63020DSJR(LDO)NCP51200MNTXG IC REG 稳压器参数

1、TPS63020电源管理IC是业界最小和性能最高的buck-boost转换器&#xff0c;具有4-A开关和高达96%的效率。TI TPS63020电源管理IC有助于延长智能手机&#xff0c;便携式医疗设备&#xff0c;DLPpico投影仪和其他电池供电多媒体设备的电池寿命。TI TPS63020 buck-boost转换器工作…

一次请求的来龙去脉 - Tomcat架构解析(二)

> 容器&#xff0c;简单理解就是用来装东西的工具。在Tomcat里面&#xff0c;容器被设计用来装载Servlet&#xff0c; 也就是我们平常写的普通的Servlet &#xff0c;就会存放在容器里面。这也就是咱们平常念叨的Servlet容器&#xff0c;其实从广义上理解&#xff0c;Servle…