【Spring】Spring IOC DI

Spring IOC & DI

  • IOC DI入门
    • 什么是Spring
      • 什么是容器
      • 什么是IOC
    • IOC介绍
      • 传统程序开发
      • 解决方案
    • DI
  • IOC详解
    • Bean的存储
      • @Controller(控制器存储)
      • @Service(服务存储)
      • @Repository(仓库存储)
      • @Component(组件存储)
      • @Configuration(配置存储)
    • 为什么需要这么多类注解
    • 类注解之间的关系
    • 方法注解@Bean
      • 定义多个对象
    • 重命名Bean
    • 扫描路径
  • DI详解
    • 属性注入
    • 构造方法注入
    • Setter注入
    • 三种注入优缺点分析
    • @Autowired存在问题
      • @Primary
      • @Qualifier
      • @Resource

IOC DI入门

什么是Spring

Spring是一个开源的轻量级Java开发框架,它提供了全面的基础设施支持和广泛的应用程序级特性,使得Java开发变得更加简单和高效。 Spring框架的核心特点包括依赖注入(Dependency Injection)、面向切面编程(AOP)、容器、事务管理等。

依赖注入允许开发人员将组件之间的依赖关系外部化,这样可以降低类之间的耦合度,使得代码更容易维护和测试。面向切面编程则允许开发人员定义横切关注点,比如日志、事务管理等,从而实现模块化的开发。

Spring框架还提供了一个轻量级的IoC容器,用于管理JavaBean的生命周期和配置。此外,Spring还支持各种各样的应用程序级特性,包括Web开发、数据访问、安全性、远程调用等。

总的来说,Spring框架在Java企业应用开发中扮演着重要的角色,它提供了丰富的功能和灵活的设计理念,使得开发人员能够更加高效地编写可维护、可扩展的应用程序。

什么是容器

容器是⽤来容纳某种物品的(基本)装置。
⽣活中的⽔杯, 垃圾桶, 冰箱等等这些都是容器.

• List/Map -> 数据存储容器
• Tomcat -> Web 容器

什么是IOC

IOC(Inverse of Control,控制反转)是面向对象编程中的一种设计原则,它是软件开发中依赖注入(DI)的一种实现方式。在IOC中,控制权从传统的应用程序代码中转移到了外部容器或框架,使得对象之间的依赖关系由外部来管理和注入。

在传统的编程模式中,一个对象通常会直接创建和管理它所依赖的其他对象。而在IOC容器中,对象的依赖关系由容器在创建对象时进行注入,而不是由对象自身负责。这种控制权的转移使得对象之间的耦合度降低,也更有利于代码的可测试性和可维护性。

Spring框架就是一个典型的IOC容器,它通过依赖注入的方式来管理对象之间的依赖关系。开发人员只需要描述组件之间的依赖关系,比如通过配置文件或注解,然后由Spring容器负责实例化对象并注入它们之间的依赖关系。

总的来说,IOC通过将对象之间的依赖关系外部化,使得系统更加灵活、可扩展,并且有利于降低代码之间的耦合度。

IOC介绍

接下来我们通过案例来了解⼀下什么是IoC
需求: 造⼀辆⻋

传统程序开发

我们的实现思路是这样的:
先设计轮⼦(Tire),然后根据轮⼦的⼤⼩设计底盘(Bottom),接着根据底盘设计⻋⾝(Framework),最后根据⻋⾝设计好整个汽⻋(Car)。这⾥就出现了⼀个"依赖"关系:汽⻋依赖⻋⾝,⻋⾝依赖底盘,底盘依赖轮⼦.

在这里插入图片描述
这样的设计看起来没有问题,但是可维护性却很低

例如我们要修改轮胎的尺寸 因为底盘是根据轮胎制造的 所以底盘的尺寸也需要修改 因为车身是根据底盘制造的 车身也需要修改 因为整个车是根据车身来制造的 所以整个车也需要修改 此时我们发现 有一处小修改则整体要受到很大的改变 可维护性很低

解决方案

在上⾯的程序中, 我们是根据轮⼦的尺⼨设计的底盘,轮⼦的尺⼨⼀改,底盘的设计就得修改. 同样因为我们是根据底盘设计的⻋⾝,那么⻋⾝也得改,同理汽⻋设计也得改, 也就是整个设计⼏乎都得改~

我们尝试换⼀种思路, 我们先设计汽⻋的⼤概样⼦,然后根据汽⻋的样⼦来设计⻋⾝,根据⻋⾝来设计底盘,最后根据底盘来设计轮⼦. 这时候,依赖关系就倒置过来了:轮⼦依赖底盘, 底盘依赖⻋⾝,⻋⾝依赖汽⻋
在这里插入图片描述
如何来实现呢:

我们可以尝试不在每个类中⾃⼰创建下级类,如果⾃⼰创建下级类就会出现当下级类发⽣改变操作,⾃⼰也要跟着修改.此时,我们只需要将原来由⾃⼰创建的下级类,改为传递的⽅式(也就是注⼊的⽅式),因为我们不需要在当前类中创建下级类了,所以下级类即使发⽣变化(创建或减少参数),当前类本⾝也⽆需修改任何代码,这样就完成了程序的解耦.

例如这种方式的开发 使程序之间实现解耦 就叫做IOC程序开发

IOC容器
在这里插入图片描述
从上⾯也可以看出来, IoC容器具备以下优点:
资源不由使⽤资源的双⽅管理,⽽由不使⽤资源的第三⽅管理,这可以带来很多好处。第⼀,资源集中管理,实现资源的可配置和易管理。第⼆,降低了使⽤资源双⽅的依赖程度,也就是我们说的耦合度。

  1. 资源集中管理: IoC容器会帮我们管理⼀些资源(对象等), 我们需要使⽤时, 只需要从IoC容器中去取
    就可以了
  2. 我们在创建实例的时候不需要了解其中的细节, 降低了使⽤资源双⽅的依赖程度, 也就是耦合度.
    Spring 就是⼀种IoC容器, 帮助我们来做了这些资源管理.

DI

DI: Dependency Injection(依赖注⼊)
容器在运⾏期间, 动态的为应⽤程序提供运⾏时所依赖的资源,称之为依赖注⼊

程序运行时需要某个资源,此时容器就为其提供这个资源
从这点来看,依赖注入和控制反转是从不同角度描述同一件事情,就是通过引入IOC容器,利用依赖注入的方式,实现对对象的解耦
ioc容器中存放着对象,而我们通过di的方式,来从容器中取出这个对象来使用

IOC详解

Spring 容器 管理的主要是对象, 这些对象, 我们称之为"Bean". 我们把这些对象交由Spring管理, 由Spring来负责对象的创建和销毁. 我们程序只需要告诉Spring, 哪些需要存, 以及如何从Spring中取出对象

通过上⾯的案例, 我们已经知道了Spring IoC 和DI的基本操作, 接下来我们来系统的学习Spring IoC和DI
的操作.前⾯我们提到IoC控制反转,就是将对象的控制权交给Spring的IOC容器,由IOC容器创建及管理对
象。也就是bean的存储.

Bean的存储

在之前的⼊⻔案例中,要把某个对象交给IOC容器管理,需要在类上添加⼀个注解:@Component
⽽Spring框架为了更好的服务web应⽤程序, 提供了更丰富的注解

共有两种注解可以实现

  1. 类注解: @Controller @Service @Repository @Component @Configuration
  2. 方法注解: @Bean

@Controller(控制器存储)

import org.springframework.stereotype.Controller;

@Controller
public class UserController {
    public void sayHi(){
        System.out.println("hi UserController");
    }
}

如何观察这个对象已经存在于Spring容器中了呢?
接下来学习如何从Spring容器中获取对象

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        //获取Spring上下文对象
        ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
        //从Spring上下文中获取对象
        UserController userController = context.getBean(UserController.class);
        //使用对象
        userController.sayHi();
    }
}

在这里插入图片描述

上述代码是根据类型来查找对象, 如果Spring容器中, 同⼀个类型存在多个bean的话, 怎么来获取呢?
ApplicationContext 也提供了其他获取bean的⽅式, ApplicationContext 获取bean对象的功能, 是⽗类BeanFactory提供的功能
在这里插入图片描述
常用的是第一种 第二种 第五种

第一种是根据bean名获取bean
第二种是根据bean名和类型获取bean
第五种是按照bean类型和构造函数参数动态创建bean 只适用于具有原型作用域的bean

但是其中涉及到的bean 的名称 那么bean的名称是什么呢?

Bean的命名约定
程序开发人员不需要为bean指定名称,如果没有显式的提供名称,Spring容器将为该bean生成唯一的名称

  1. 命名约定使用Java标准约定作为实例字段名,也就是说,bean的名称以小写字母开头,然后使用驼峰式大小写
    比如类名UserController Bean的 名称为userController
  2. 当有多个字符并且第一个和第二个字符都是大写时,将保留原始的大小写
    比如类名UController Bean 的名称为UController

ApplicationContext 和 BeanFactory的对比

  1. 从继承关系和功能方面来说 Spring容器有两个顶级的接口 BeanFactory和ApplicationContext 其中BeanFactory提供基础的访问容器的能力 而ApplicationContext属于BeanFactory的子类,他除了继承BeanFactory的所有功能之外,还具有独特的特性,还添加了对国际化支持,资源访问支持,以及事件传播等方面的支持
  2. 从性能方面来说: ApplicationContext是一次性加载并初始化所有的Bean对象,而BeanFactory是需要哪个才去加载哪个,因此更加轻量

@Service(服务存储)

@Service
public class UserService {

    public void sayHi(){
        System.out.println("hi UserService");
    }
}

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

@Repository(仓库存储)

@Repository
public class UserRepository {
    public void sayHi(){
        System.out.println("hi UserRepository");
    }
}

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

@Component(组件存储)

@Component
public class UserComponent {
    public void sayHi(){
        System.out.println("hi UserComponent");
    }
}

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

@Configuration(配置存储)

@Configuration
public class UserConfiguration {
    public void sayHi(){
        System.out.println("hi UserConfiguration");
    }
}

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

为什么需要这么多类注解

这里的类注解和应用分层是呼应的,程序员在看到类注解之后,就能够直接了解当前类的用途

• @Controller:控制层, 接收请求, 对请求进⾏处理, 并进⾏响应.
• @Servie:业务逻辑层, 处理具体的业务逻辑.
• @Repository:数据访问层,也称为持久层. 负责数据访问操作
• @Configuration:配置层. 处理项⽬中的⼀些配置信息

在这里插入图片描述

类注解之间的关系

查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:其实这些注解里面都有一个注解@Component 说明他们本身是基于@Component的子类

@Component 是⼀个元注解,也就是说可以注解其他类注解,如 @Controller , @Service ,@Repository 等. 这些注解被称为 @Component 的衍⽣注解.

@Controller , @Service 和 @Repository ⽤于更具体的⽤例(分别在控制层, 业务逻辑层, 持久化层), 在开发过程中, 如果你要在业务逻辑层使⽤ @Component 或@Service,显然@Service是更好的选择

方法注解@Bean

类注解是添加到某个类上的, 但是存在两个问题:

  1. 使⽤外部包⾥的类, 没办法添加类注解
  2. ⼀个类, 需要多个对象, ⽐如多个数据源
    这种场景, 我们就需要使⽤⽅法注解 @Bean
@Component
public class BeanConfig {
    @Bean
    public User user(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
}

在这里插入图片描述
在这里插入图片描述
方法注解要配合类注解使用

定义多个对象

对于同一个类,如何定义多个对象呢?

比如多数据源的场景,类是同一个,但是配置不同,指向不同的数据源

@Component
public class BeanConfig {
    @Bean
    public User user1(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
    
    @Bean
    public User user2(){
        User user = new User();
        user.setName("lisi");
        user.setAge(20);
        return user;
    }
}

当我们定义了多个对象时,我们根据类型获取对象,获取到的是哪个对象呢?
在这里插入图片描述

Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.demo.Model.User' available: expected single matching bean but found 2: user1,user2
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1273)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:494)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1178)
	at com.example.demo.DemoApplication.main(DemoApplication.java:35)

我们发现此时代码报错了,根据报错信息,期望只有一个匹配,结果发现了两个对象 user1和user2

从报错信息中可以看出来,@Bean注解的Bean,Bean的名称就是他的方法名
我们可以通过名称来获取Bean对象

User user1 = (User) context.getBean("user1");
User user2 = (User) context.getBean("user2");
System.out.println(user1);
System.out.println(user2);

在这里插入图片描述

重命名Bean

可以通过设置name属性给Bean对象进行重命名操作
在这里插入图片描述
此时我们既可以通过user1这个名称获取User对象 也可以通过u1这个名称获取到User对象了

name=可以省略
在这里插入图片描述
只有一个名称时 括号也可以省略
在这里插入图片描述

扫描路径

使用四个注解声明的bean一定会生效吗? 答案是不一定 因为bean要想生效 还需要被Spring扫描

使用五大注解声明的bean,要想生效,还需要配置扫描路径 让Spring扫描到这些注解

也就是使用@ComponentScan来配置扫描路径

为什么我们在之前没有配置扫描路径也可以扫描到bean呢?
我们虽然没有显示的配置@ComponentScan,但是在启动类的注解上已经包含了这个注解了
在这里插入图片描述
默认的扫描范围是SpringBoot启动类所在包及其子包

DI详解

上面我们详解了控制反转IoC的细节,下面我们介绍DI的细节

依赖注⼊是⼀个过程,是指IoC容器在创建Bean时, 去提供运⾏时所依赖的资源,⽽资源指的就是对象.在上⾯程序案例中,我们使⽤了@Autowired这个注解,完成了依赖注⼊的操作.简单来说, 就是把对象取出来放到某个类的属性中.

在⼀些⽂章中, 依赖注⼊也被称之为 “对象注⼊”, “属性装配”, 具体含义需要结合⽂章的上下⽂来理解

关于依赖注入,Spring也给我们提供了三种方式

  1. 属性注入
  2. 构造方法注入
  3. Setter注入

属性注入

属性注⼊是使⽤ @Autowired 实现的,将 Service 类注⼊到 Controller 类中。
Service 类的实现代码如下:

@Service
public class UserService {

    public void sayHi(){
        System.out.println("hi UserService");
    }
}

Controller类实现

@Controller
public class UserController {

    @Autowired
    //将UserService注入到Usercontroller中
    private UserService userService;
    public void sayHi(){
        System.out.println("hi UserController");
        userService.sayHi();
    }
}

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

构造方法注入

@Controller
public class UserController {
    //方式二:构造方法注入
    //将UserService注入到Usercontroller中
    private UserService userService;
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }
    
    public void sayHi(){
        System.out.println("hi UserController");
        userService.sayHi();
    }
}

注意事项:如果类只有⼀个构造⽅法,那么 @Autowired 注解可以省略;如果类中有多个构造⽅法,那么需要添加上 @Autowired 来明确指定到底使⽤哪个构造⽅法

Setter注入

注意事项:如果类只有⼀个构造⽅法,那么 @Autowired 注解可以省略;如果类中有多个构造⽅法,那么需要添加上 @Autowired 来明确指定到底使⽤哪个构造⽅法

@Controller
public class UserController {
    //方式三:Setter注入
    //将UserService注入到Usercontroller中
    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    
    public void sayHi() {
        System.out.println("hi UserController");
        userService.sayHi();
    }
}

在这里插入图片描述

三种注入优缺点分析

构造方法注入:

优点:构造方法注入可以保证对象的完整性,因为它要求在创建对象时必须提供所需的属性值。这样可以避免对象处于不完整或不一致的状态。同时,构造方法注入也使得对象在创建后就可以是不可变的。
缺点:构造方法注入在参数较多的情况下会显得冗长,特别是当属性较多、属性之间有依赖关系时。此外,对于每个依赖项,都需要提供一个相应的构造方法,这可能会导致类的构造方法过于臃肿。

Setter方法注入:

优点:Setter方法注入相对于构造方法注入,使用起来更加灵活,不需要在创建对象时传递所有依赖项。可以通过调用各个Setter方法来逐个注入属性。同时,Setter方法注入也便于后续修改或替换属性的值。
缺点:Setter方法注入破坏了对象的完整性,因为依赖项可以在对象创建后的任何时候进行注入。这可能导致对象在某些操作中处于不一致的状态。此外,它也增加了类的可变性,可能导致对象的不可变性和线程安全性问题。

字段注入:

优点:字段注入简单直观,没有构造方法或Setter方法的冗长代码。对于小型的应用或快速原型开发,字段注入可能更加方便。
缺点:字段注入破坏了封装性,将依赖项直接暴露为公共字段。这违反了面向对象编程的原则,可能导致代码可维护性和测试性的问题。此外,字段注入也不利于单元测试和模拟依赖项。

@Autowired存在问题

当同一个类型存在多个bean时,使用@Autowired会存在问题

@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private User user;

    public void sayHi() {
        System.out.println("hi UserController");
        userService.sayHi();
        System.out.println(user);
    }
}

在这里插入图片描述

报错的原因是,非唯一的Bean对象
那么如何解决上述问题呢? Spring提供了以下几种解决方案

@Primary

使用@Primary注解 ,当存在多个相同类型的bean注入时,加上@Primary注解 来确定默认的实现

@Component
public class BeanConfig {
    @Primary
    @Bean("user1")
    public User user1(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }

    @Bean
    public User user2(){
        User user = new User();
        user.setName("lisi");
        user.setAge(20);
        return user;
    }
}

@Qualifier

使⽤@Qualifier注解:指定当前要注⼊的bean对象。 在@Qualifier的value属性中,指定注⼊的bean的名称。

@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    @Qualifier("user2")
    private User user;

    public void sayHi() {
        System.out.println("hi UserController");
        userService.sayHi();
        System.out.println(user);
    }
}

@Qualifier注解不能单独使⽤,必须配合@Autowired使⽤

@Resource

使⽤@Resource注解:是按照bean的名称进⾏注⼊。通过name属性指定要注⼊的bean的名称。

@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @Resource(name = "user2")
    private User user;

    public void sayHi() {
        System.out.println("hi UserController");
        userService.sayHi();
        System.out.println(user);
    }
}

@Autowird 与 @Resource的区别
@Autowired 是spring框架提供的注解,⽽@Resource是JDK提供的注解
@Autowired 默认是按照类型注⼊,⽽@Resource是按照名称注⼊

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

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

相关文章

LeetCode 26. 删除有序数组中的重复项 简单

题目 - 点击直达 1. 26. 删除有序数组中的重复项 简单1. 题目详情1. 原题链接2. 题目要求3. 基础框架 2. 解题思路1. 思路分析2. 时间复杂度3. 代码实现 1. 26. 删除有序数组中的重复项 简单 1. 题目详情 给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复…

Redis发布订阅

文章目录 前言一、什么是Redis订阅和发布?二、命令三、原理四、使用场景总结 前言 消息队列 Redis 发布订阅(publsub)是一种消息通信模式︰发送者(pub)发送消息,订阅者(sub)接收消息。微信、微博、关注系统! Redis客户端可以订阅任意数量的频道。 一、…

springboot定时服务

上一篇文章【修改定时时间,定时任务及时生效】 是定时任务与功能项目共用一个; 我目前所在公司的定时服务是专门有一个项目处理,然后定时查询库里面的定时信息配置。 话不多说,上程序 数据库设置 create table SCHEDULER_JOB…

基于springboot 手工艺品在线展示系统-计算机毕设 附源码 42553

springboot 手工艺品在线展示系统 目 录 摘要 1 绪论 1.1本课题研究意义 1.2系统开发目的 2 1.3系统开发技术的特色 3 1.4 springboot框架介绍 3 1.5论文结构与章节安排 4 2 手工艺品在线展示系统系统分析 5 2.1 可行性分析 5 2.2 系统流程分析 5 2.2.1数据增加流程 5 2.2.…

Swift 抛砖引玉:从数组访问越界想到的“可抛出错误”属性

0. 概览 了解 Swift 语言的小伙伴们都知道,我们可以很方便的写一个可能抛出错误的方法。不过大家可能不知道的是在 Swift 中对于结构或类的实例属性我们也可以让它抛出错误。 这称之为实效只读属性(Effectful Read-only Properties)。 那么…

速锐得柴油发动机车辆数据的实时获取定位和运行状态监测设计思路

随着港口、油田、车队运输、物流及冷链等多种交通运输领域的兴起,保障性集团运输业务在这些领域凸显出重要的作用,数字化转型及平台系统性管理要求越来越高,针对柴油发动机车辆数据的实时获取定位和运行状态的检测方案配套平台系统&#xff0…

DSP开发例程(4): logbuf_print_to_uart

目录 DSP开发例程: logbuf_print_to_uart新建工程源码编辑app.cfgos.cmain.c 调试说明 DSP开发例程: logbuf_print_to_uart SYS/BIOS 提供了 xdc.runtime.Log, xdc.runtime.LoggerBuf 和 xdc.runtime.LoggerSys 这几个模块用于日志记录. 日志信息在 应用程序调试和状态监控中非…

用友NC Cloud accept.jsp接口任意文件上传漏洞复现 [附POC]

文章目录 用友NC Cloud accept.jsp接口任意文件上传漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 用友NC Cloud accept.jsp接口任意文件上传漏洞复现 [附POC] 0x01 前言 免责声明&#xff1a…

万宾科技内涝积水监测仪使用效果一览

当一个城市突降暴雨,对城市管理部门来讲首当其中的是防止积水成患。随着城市人口快速增长,基础设施建设也日益受到更多的关注,城市内涝问题频繁增加,会给城市带来严重的经济损失和人员的安全问题。城市生命线工程建设过程中&#…

【EI会议征稿】第八届先进能源科学与自动化国际研讨会(AESA 2024)

第八届先进能源科学与自动化国际研讨会(AESA 2024) 2024 8th International Workshop on Advances in Energy Science and Automation 继AESA 2017-2023相继成功举办之后,来自国内外多所高校、科研院所及企业代表在先进能源科学与自动化的科研合作和交流…

(附源码)基于spring boot 房屋租赁系统小程序-计算机毕设 88306

spring boot 房屋租赁系统小程序 目 录 摘要 1 绪论 1.1选题意义 1.2开发现状 1.3springboot框架介绍 1.4论文结构与章节安排 2 房屋租赁系统小程序系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 法律可行性分析 2.2 系统功能分析 2.…

VINS-Mono-后端优化 (三:视觉雅可比推导)

用逆深度是因为这样可以在优化中从优化3个变量降低到1个,降低优化的维度加快求解速度 用逆深度是因为当距离很远的时候, 1 x \frac{1}{x} x1​ x x x 就会无穷大,而3D点很近的情况也一般不会有,这也是为了数值稳定性 用逆深度的…

SAP 20策略测试简介

20策略相信也有很多小伙伴使用过,与50最大的不同之处就在于20策略是不能做计划独立需求的。 我看一下系统中20 策略的配置图,可以看到独立需求这里的配置都是空的。 1、我们开始测试准备物料 成品物料AB4 原材料:100197 2、创建BOM—CS01 3、创建主配方—c201 ,离散制造…

创建第一个Go的程序Hello Kitty

上一篇,我们已经搭建好了开发要用的基础环境:Go开发基础环境搭建, 今天我们要开始用GoLand实操关于Go的代码开发。 创建工程 File > New > Project 其中 game为项目名称 在项目目录下会自动生成一个文件:go.mod ,模块是相关Go包的集合。modules是源代码交换…

R | R包安装报错-github连接速度慢或无法访问 | metaboanalystR | Retip | rJava安装

R | R包安装报错-github连接速度慢或无法访问 | metaboanalystR | Retip | rJava安装 一、metaboanalystR 安装1.1 Bioconductor报错,无网络连接1.2 github520-修改hosts文件 二、retip安装2.1 rJava包加载报错及安装2.2 安装Retip包 三、从Bioconductor安装Rdisop报…

web3 前端dapp从redux过滤出 (我创建与别人创建)正在执行的订单 并展示在Table上

上文 web3 从redux中拿出所有已完成订单 并渲染到对应的Table列表中 我们从redux中 取出并渲染了 已完成的订单 那么 我们继续 万里长征 就快看到尽头了呀 我们先起一下环境 ganache 终端输入 ganache -d然后 登一下 MetaMask 然后 打开我们的项目 发布一下合约 truffle mig…

GZ038 物联网应用开发赛题第4套

2023年全国职业院校技能大赛 高职组 物联网应用开发 任 务 书 (第4套卷) 工位号:______________ 第一部分 竞赛须知 一、竞赛要求 1、正确使用工具,操作安全规范; 2、竞赛过程中如有异议,可向现场考评…

SAP 50策略测试简介

上篇博文写了40策略的测试,40策略就是典型的按库存生产,考虑库存,考虑销售订单。 本文将测试50策略,按单生产用的最多的策略。相信很多公司按单生产应该都会用到50的策略 1、首先还是先创建物料AB3 同时将BOM中的原材料的独立集中的字段设置为1 2、创建BOM—CS01 3、同杨…

动态通讯录及程序保存在文件中

目录 一、结构体改造及增容函数 1.结构体部分 2.初始化函数及增容函数 二、信息添加及销毁和排序 1.信息添加函数(Add) 2.销毁函数(Destroy) 3.排序部分(qsort) 三、通讯录信息保存 1.保存在文件中…

【华为数通HCIP | 网络工程师】821-BGP 组播高频题与解析(1)

个人名片: 🐼作者简介:一名大三在校生,喜欢AI编程🎋 🐻‍❄️个人主页🥇:落798. 🐼个人WeChat:hmmwx53 🕊️系列专栏:🖼️…