【Spring】(三)Spring 使用注解存储和读取 Bean对象

news2024/9/22 23:39:25

文章目录

  • 前言
  • 一、使用注解储存 Bean 对象
    • 1.1 配置扫描路径
    • 1.2 类注解储存 Bean 对象
      • 1.2.1 @Controller(控制器存储)
      • 1.2.2 @Service(服务储存)
      • 1.2.3 @Repository(仓库存储)
      • 1.2.4 @Component(组件储存)
      • 1.2.5 @Configuration(配置储存)
      • 1.2.6 Bean 命名规则
    • 1.3 五大类注解的作用
      • 1.3.1 为什么有这么多的注解
      • 1.3.2 类注解之间的关系
    • 1.4 方法注解储存 Bean 对象
      • 1.4.1 @Bean 注解的使用
      • 1.4.2 Bean 对象重命名
  • 二、使用注解获取 Bean 对象
    • 2.1 Bean 对象通过注解获取的方法
    • 2.2 三种注入方法的使用
      • 2.2.1 属性注入
      • 2.2.2 Setter 注入
      • 2.2.3 构造方法注入
    • 2.3 三种注入方法的优缺点
    • 2.4 @Resource 注入
    • 2.5 @Autowired 和 @ Resource的区别
    • 2.6 注入同一类型的多个 @Bean 报错问题
      • 2.6.1 报错问题
      • 2.6.2 使用 @Resource(name="XXX") 解决
      • 2.6.3 @Autowired 配合使用 @Qualifier 解决


前言

前面的文章详细的介绍了 Spring 对象的创建,以及对 Bean 对象的存取操作,但是通过配置文件注册 Bean 对象以及使用 ApplicationContextBeanFactory 的方式获取 Bean 对象的操作就显得格外的复杂。因此,本文主要就是详细介绍了一种更加简单的方式来实现对 Bean 对象更加简单的储存和读取操作。

在 Spring 中,要想更加简单的实现对 Bean 对象的储存和使用,其核心就是使用注解,本文主要就是演示如何使用注解实现对 Bean 对象的存取操作。

一、使用注解储存 Bean 对象

在之前储存 Bean 对象的时候,还需在 spring-congig 文件中添加一行 <bean> 内容才行,而且,每需要新增一个 Bean 对象到 Spring 容器中就需要新增一行,这样的操作就显得非常麻烦了。

而现在只需要使用一个注解就能代替这一行 <bean> 内容,此时就变得非常方便。想要通过注解的方式将对象储存到 Spring 容器中,主要有两种注解类型可以实现:

  1. 使用类注解(五大类注解):

    • @Controller(控制储存):验证用户请求的数据合法性,相当于安保系统;
    • @Service(服务储存):用于编排和调度具体的执行方法;
    • @Repository(仓库储存):持久层,与数据库进行交换;
    • @Component(组件储存):相当于工具类;
    • @Configuration(配置储存):项目中的一些配置。
  2. 使用方法注解:

    • @Bean:作用在方法上,需要配合上述的类注解使用。

但在此之前还需要配置一下扫描路径

1.1 配置扫描路径

spring-config.xml文件中添加如下一行记录:

其含义是,指定一个 base package,即所有需要添加到 Spring 容器中的 Bean 对象都在 base package 所指定包或者其子包下。这里我知道的包是com.spring.demo,那么就意味着,如果不是此包下的 Bean 对象,即使加上了注解,也不会被添加到 Spring 容器中。

1.2 类注解储存 Bean 对象

1.2.1 @Controller(控制器存储)

使用 @Controller 注解储存 Bean 对象:

@Controller
public class StudentController1 {
    public void sayHi(){
        System.out.println("do studentController1 sayHi().");
    }
}

使用 ApplicationContext的方式获取 Bean 对象:

public static void main(String[] args) {
    ApplicationContext context =
            new ClassPathXmlApplicationContext("spring-config.xml");

    StudentController1 studentController1 =
            context.getBean("studentController1", StudentController1.class);

    studentController1.sayHi();
}

关于 Bean 对象的命名规则可见后文。

1.2.2 @Service(服务储存)

使用 @Service 注解储存 Bean 对象:

@Service
public class StudentController2 {
    public void sayHi(){
        System.out.println("do studentController2 sayHi().");
    }
}

获取 Bean 对象:

StudentController2 studentController2 =
        context.getBean("studentController2", StudentController2.class);

1.2.3 @Repository(仓库存储)

使用 @Repository 注解储存 Bean 对象:

@Repository
public class StudentController3 {
    public void sayHi(){
        System.out.println("do studentController3 sayHi().");
    }
}

获取 Bean 对象:

StudentController3 studentController3 =
        context.getBean("studentController3", StudentController3.class);

1.2.4 @Component(组件储存)

使用 @Component 注解储存 Bean 对象:

@Component
public class StudentController4 {
    public void sayHi(){
        System.out.println("do studentController4 sayHi().");
    }
}

获取 Bean 对象:

StudentController4 studentController4 =
        context.getBean("studentController4", StudentController4.class);

1.2.5 @Configuration(配置储存)

使用 @Configuration 注解储存 Bean 对象:

@Configuration
public class StudentController5 {
    public void sayHi(){
        System.out.println("do studentController5 sayHi().");
    }
}

获取 Bean 对象:

StudentController5 studentController5 =
        context.getBean("studentController5", StudentController5.class);

1.2.6 Bean 命名规则

通过上述代码可以发现,在创建 Bean 对象的时候,都是使用的标准 “大驼峰” 的命名方式,而读取的时候 Bean 的名称则是其类名称的首字母小写,即小驼峰。


但是,此时创建一个 SController 类,并使用注解将其添加到 Spring 容器中,那么此时它的 Bean 对象的名称是什么呢?根据上面代码的规律,难道还是SController 吗?

SController sController = context.getBean("sController", SController.class);

当运行程序的时候,发现报错了:

其意思是不存在名称为 sController 这样 Bean 对象。此时如果将其改成 SController,会是正确的吗?


此时发现便能正常运行了。

关于 Bean 的名称生成的源码:

  1. 查找 beanname,选择AnnotationBeanNameGenerator
  2. 继续查找

  1. 继续查找


4. 找到了源码,即Introspector类下的decapitalize 方法

该方法通过检查字符串的首字母是否为大写,并且第二个字符也是大写的情况下,直接返回原字符串,不做小写化处理。这样做是为了避免一些特殊情况下,例如缩写或首字母缩写词,不被误处理。

1.3 五大类注解的作用

在Spring框架中,五大类常用的注解,分别是:@Component、@Controller、@Service、@Repository和@Configuration。

  • @Component: 通用的组件注解,表示类是一个Spring管理的组件(Bean)。

  • @Controller: 用于标识控制器类,通常用于Spring MVC中,处理HTTP请求和视图渲染。

  • @Service: 用于标识服务类,表示该类提供一些业务逻辑处理。

  • @Repository: 用于标识仓库类,表示该类用于数据访问,通常与数据库交互。

  • @Configuration: 用于标识配置类,表示该类包含Spring配置信息,通常与@Bean一起使用,用于定义 Bean。

1.3.1 为什么有这么多的注解

通过上面代码的演示,发现这些注解的功能都是一样的,既然都是一样的为什么还需要有这么多不同的注解呢?

Spring 之所以提供这么多的注解,是为了更好的组织和管理应用程序的组件和依赖关系因为每个注解都有自己特定的用途,让开发人员在应用程序中能够更方便地标识和区分不同类型的类。同时也提现了程序的工程分层:

  1. 其中 @Controller 表示的是控制层,负责与用户进行交互,以及验证用户提交数据的合法性;
  2. @Service表示的是服务层,用于编排和调度具体的执行方法,相当于车站中的服务台;
  3. @Repository表示的是持久层,负责将数据持久化储存,通常需要与数据库进行交互。

以上三个层次实现了程序的工程分层,同时也是 Java EE 标准分层的最核心分层。

1.3.2 类注解之间的关系

  • 查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:
    它们都是 @Component 子类注解,这意味着,被标注为 @Controller / @Service / @Repository / @Configuration 的类也被视为@Component

  • 另外,@Configuration注解是一个特殊的注解,它表明该类是 Spring 的配置类,用于定义 Bean 和配置应用程序的其他元素。配置类中的@Bean注解用于定义 Bean。

1.4 方法注解储存 Bean 对象

首先创建一个 User 实体类:

package com.spring.demo.entity;

/**
 * 普通的用户实体类
 */
public class User {
    private Integer uid;
    private String username;
    private String password;
    private Integer age;

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }
}


1.4.1 @Bean 注解的使用

创建一个组件类 UserBeans,并使用方法注解 @Bean 将 User 类添加到 Spring 容器中:

@Controller
public class UserBeans {
    @Bean
    public User getUser(){
        User user = new User();
        user.setUid(1);
        user.setUsername("王五");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }
}

注意,使用方法注解 @Bean 的时候需要搭配五大类注解才能生效。

获取 Bean 对象:

public static void main(String[] args) {
    ApplicationContext context =
            new ClassPathXmlApplicationContext("spring-config.xml");

    User user = context.getBean("getUser", User.class);
    System.out.println(user);
}

注意,当使用方法注解@Bean 的时候,Bean 对象的默认名称就是其 添加到 Spring 容器中的方法名。

1.4.2 Bean 对象重命名

如果直接使用方法名作为 Bean 对象的名称,例如getUser就显得非常的不合理,因此往往需要对 Bean 进行改名操作。但查看@Bean源码的时候可以发现,其中的namevalue属性是一个数组,那么就意味着可以一个 Bean 对象取多个名称。

例如:

此时,可通过这两个名称,获取该 Bean 对象,发现它们是同一个 Bean:

另外需要注意的是,如果对 Bean 进行了重命名,则原来默认的方法名就失效了。

二、使用注解获取 Bean 对象

2.1 Bean 对象通过注解获取的方法

获取 Bean 对象也叫做对象装配,即把对象取出来放到某个类当中,同时也叫做对象注入

对象注入的实现方式有以下三种:

  1. 属性注入:属性注入是通过在属性上使用注解实现的。常见的注解有@Autowired@Resource。属性注入是在 Bean 对象的属性上直接进行注入,不需要提供setter方法。

  2. Setter 注入Setter 注入是通过在 Bean 对象的 setter 方法上使用注解实现的。这种注入方式是在调用 Bean 的 setter 方法时,将依赖对象作为参数传入。

  3. 构造方法注入:构造方法注入是通过在 Bean 对象的构造方法上使用注解实现的。这种注入方式是在创建 Bean 对象的时候,通过构造方法参数传入依赖对象。

2.2 三种注入方法的使用

下⾯按照实际开发中的模式,将 Service 类注入到 Controller 类中,然后通过 main 方法获取 Controller 中的 Bean 对象。
首先创建一个 UserService 类和 UserController 类:


@Service
public class UserService {
    public void sayHi(){
        System.out.println("hi, userService.");
    }
}

2.2.1 属性注入

@Controller
public class UserController {
    // 1. 属性注入
    @Autowired
    private UserService userService;

    public void sayHi(){
        System.out.println("do userController sayHi().");

        userService.sayHi();
    }
}

2.2.2 Setter 注入

@Controller
public class UserController {
    // 2. setter 注入
    private UserService userService;

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

        userService.sayHi();
    }
}

2.2.3 构造方法注入

@Controller
public class UserController {
    // 3. 构造方法注入
    private UserService userService;

    // @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    public void sayHi(){
        System.out.println("do userController sayHi().");

        userService.sayHi();
    }
}

注意,如果此时只有一个构造方法,则@Autowired 可以省略。

2.3 三种注入方法的优缺点

属性注入

  1. 优点:简洁,代码量少,适合对属性直接注入的情况;
  2. 缺点:
    • 对于必须注入的属性,如果没有找到匹配的Bean,会导致运行时错误;
    • 兼容不好,只能用于 IoC 容器;
    • 没办法实现 finally 修饰的变量实现注入;
    • 过于简单,容易违背单一设计原则。

Setter注入:

  1. 优点:符合单一设计原则,每个方法只能传递一个对象。

  2. 缺点:

    • 没办法实现 finally 修饰的变量实现注入;
    • 使用 Setter 注入的对象可能会被修改。

构造方法注入:

  1. 优点:

    • 可以实现 finally 修饰的变量实现注入;
    • 注入的对象不会被改变,即构造方法只能执行一次;
    • 构造方法注入可以保证注入对象完全被初始化。
  2. 缺点:构造方法参数较多时,代码显得冗长。

2.4 @Resource 注入

在进行类注入时,除了可以使用 @Autowired 关键字之外,我们还可以使用 @Resource 进行注入,如下代码所示:

属性注入:

public class UserController {
    // 1. 属性注入
    @Resource
    private UserService userService;

    public void sayHi(){
        System.out.println("do userController sayHi().");

        userService.sayHi();
    }
}

Setter注入:


@Controller
public class UserController {

    // 2. setter 注入
    private UserService userService;
    
    @Resource
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void sayHi(){
        System.out.println("do userController sayHi().");

        userService.sayHi();
    }
}

遗憾的是,@Resource 不支持构造方法注入:

2.5 @Autowired 和 @ Resource的区别

  1. @Autowired是 Spring 框架提供的注解,而 @Resource 是JSR-250规范提供的注解,但是 Spring 也对其进行了支持。
  2. @Autowired 默认按照类型装配 Bean,如果多个类型匹配,可以配合 @Qualifier 注解指定具体的 Bean 名称。而 @Resource 默认按照属性名进行装配,可以通过 name 属性指定具体的 Bean 名称。
  3. @Autowired 是 Spring 的专有注解,更加灵活,功能更强大。@Resource 是标准的 Java 注解,适用于更通用的情况
  4. @Autowired 可用于 Setter 注入、构造函数注入和属性注入,而 @Resource 只能用于 Setter 注入和属性注入,不能用于构造函数注入。

2.6 注入同一类型的多个 @Bean 报错问题

当存在多个类型相同的 Bean 对象,并且需要通过注解将其注入到其他 Bean 对象中时,如果没有明确指定注入哪个 Bean,就会导致报错。

2.6.1 报错问题

例如,通过 Component 中的 UserBeans 将 User 注入到 Controller 中的 UserController 中。

首先,在UserBeans 使用@Bean 添加两个 User 对象到 Spring 容器中:

@Controller
public class UserBeans {
    @Bean(name = {"user1", "u1"})
    public User getUser1(){
        User user = new User();
        user.setUid(1);
        user.setUsername("张三");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }

    @Bean(name = "user2")
    public User getUser2(){
        User user = new User();
        user.setUid(1);
        user.setUsername("李四");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }
}

UserController 中分别使用 @Autowired@Resource注入获取 Bean 对象:

@Autowired

此时,由于存在两个相同类型的 Bean 对象,但是其名称不同,所以使用@Autowired注解不知道获取哪个对象。

@Resource

使用@Resource注解同样无法判断获取哪一个对象。

关于@Autowired@Resource 查找 Bean 对象的顺序:

  • @Autowired首先按照类型查找,然后再按照名称查找;
  • @Resource首先按照名称查找,然后再按照类型查找。

2.6.2 使用 @Resource(name=“XXX”) 解决

@Controller
public class UserController {

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

    public void sayHi(){
        System.out.println("do userController sayHi().");
    }
}

2.6.3 @Autowired 配合使用 @Qualifier 解决

@Controller
public class UserController {

    @Autowired
    @Qualifier(value = "user1")
    private User user;

    public void sayHi() {
        System.out.println("do userController sayHi().");
    }
}

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

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

相关文章

java+vue+springboot基于Web的研究生信息管理系统_u0974

随着社会的不断进步与发展&#xff0c;人们对生活质量要求逐步提升。如果开发一款基于web的研究生管理系统&#xff0c;可以让管理员、研究生和导师在最短的时间里享受到最好的服务&#xff1b;而开发本系统&#xff0c;又能够提高系统整体工作水平&#xff0c;简化工作程序&am…

TiDB Serverless 正式商用,全托管的云服务带来数据管理和应用程序开发的全新体验

八 年 前 &#xff0c;我们构建了 TiDB&#xff0c;一个开源分布式关系型数据库。 我们的目标是重新定义开发者和企业处理数据的方式&#xff0c;满足不断增长的可扩展性、灵活性和性能需求。 从那时起&#xff0c;PingCAP 便致力于为开发者和企业提供快速、灵活和规模化的数据…

flutter-GridView使用

先看效果 代码实现 import package:app/common/util/k_log_util.dart; import package:app/gen/assets.gen.dart; import package:app/pages/widget/top_appbar.dart; import package:flutter/cupertino.dart; import package:flutter/material.dart; import package:flutter_…

机器学习深度学习——卷积的多输入多输出通道

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——从全连接层到卷积 &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你们有所帮…

GPT神器级插件Code Interpreter开放,这里有一份保姆级教程

# 关注并星标腾讯云开发者# 每周4 | 鹅厂一线程序员&#xff0c;为你“试毒”新技术# 第2期 | 腾讯李洛勤&#xff1a;测评 GPT4 Code Interpreter 体验 自 3 月份以来&#xff0c;人们对 GPT-4 API 的兴趣激增&#xff0c;“有数百万开发人员请求访问”。OpenAI 在一篇博客文章…

MySQL日志——慢查询日志

1.慢查询日志 默认情况下&#xff0c;不会记录管理语句&#xff0c;也不会记录不使用索引进行查找的查询。可以 使用log_slow_admin_statements和更改此行为log_queries_not_using_indexes&#xff0c;如下所述。 #慢查询日志 slow_query_log1 #执行时间参数 long_query_time…

Redis面试题-3

Redis面试题-3 14、什么是缓存击穿&#xff1f;该如何解决 缓存击穿是指一个Key非常热点&#xff0c;在不停的扛着大并发&#xff0c;大并发集中对这一个点进行访问&#xff0c;当这个Key在失效的瞬间&#xff0c;持续的大并发就穿破缓存&#xff0c;直接请求数据库&#xff…

SpringBoot整合Nacos实现配置中心

目录 1.Nacos定位 2.Nacos的安装配置 3.整合Nacos 3.1.Nacos安装 3.2.Nacos登录 3.3.配置Nacos 4.Nacos使用 4.1.引入 Maven 依赖 4.2.配置bootstrap.yml 4.3.Nacos配置类 4.4.启用Nacos服务 4.5.测试获取配置 5.加载多个配置文件 datasource-dev.yaml myba…

Antd Table带有分页的全选功能

这种带有分页的全选 如果我们翻页也需要记录跨页的勾选数据 antd自带的onChange事件只能记录选中RowKey值 但是勾选的数据只会是当前页的条数 此时就需要我们结合onSelect和onSelectAll来完成数据的交互 <Tableloading{tableDataloading}rowKey"id"rowSelection{r…

Unity进阶--使用PhotonServer实现服务端和客户端通信--PhotonServer(一)

文章目录 Unity进阶--使用PhotonServer实现服务端和客户端通信服务器的安装和配置添加日志客户端的配置客户端和服务器的通信Dlc 出现vscode引用不好使的时候 Unity进阶–使用PhotonServer实现服务端和客户端通信 服务器的安装和配置 Photon的地址&#xff1a;https://www.ph…

智能物流千人俱乐部---行业必备神器

千人俱乐部前两天正式推出了。 智能物流千人俱乐部详情 很多行业内的甲方和乙方的朋友过来问&#xff0c;这个千人俱乐部到底怎么玩&#xff1f;今天再来解释一下。 1、为什么搞这个千人俱乐部&#xff1f; 一个原因是&#xff1a;研习社天天都有甲方粉丝让推荐设备厂家&#x…

Wavefront .OBJ文件格式解读【3D】

OBJ&#xff08;或 .OBJ&#xff09;是一种几何定义文件格式&#xff0c;最初由 Wavefront Technologies 为其高级可视化器动画包开发。 该文件格式是开放的&#xff0c;已被其他 3D 图形应用程序供应商采用。 OBJ 文件格式是一种简单的数据格式&#xff0c;仅表示 3D 几何体&…

【力扣每日一题】2023.8.4 不同路径3

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 在二维网格之上&#xff0c;让我们模拟从开头走到末尾&#xff0c;并且要经过所有能经过的点&#xff0c;问我们有多少种走法。 看到这道…

【雕爷学编程】MicroPython动手做(31)——物联网之Easy IoT 3

1、物联网的诞生 美国计算机巨头微软(Microsoft)创办人、世界首富比尔盖茨&#xff0c;在1995年出版的《未来之路》一书中&#xff0c;提及“物物互联”。1998年麻省理工学院提出&#xff0c;当时被称作EPC系统的物联网构想。2005年11月&#xff0c;国际电信联盟发布《ITU互联网…

PCIE扩频时钟及参考时钟要求

Spread Spectrum Clocking 1. 概述 Spread Spectrum Clocking(扩频时钟)是采用一种可控的方式使系统时钟抖动以减少峰值能量的过程。主要是为了尽量减少电磁干扰(EMI),主要应用在PCle和USB应用中。与非调制时钟相比,扩频时钟具有相对较高的抖动,应确保下游元件能够承受扩频…

Python:Spider爬虫工程化入门到进阶(1)Scrapy

本文通过简单的小例子&#xff0c;亲自动手创建一个Spider爬虫工程化的Scrapy项目 本文默认读着已经掌握基本的Python编程知识 目录 1、环境准备1.1、创建虚拟环境1.2、安装Scrapy1.3、创建爬虫项目 2、爬虫示例-爬取壁纸2.1、分析目标网站2.2、生成爬虫文件2.3、编写爬虫代码…

用python做一个小项目,python做简单小项目

大家好&#xff0c;本文将围绕用python做一个小项目展开说明&#xff0c;python做简单小项目是一个很多人都想弄明白的事情&#xff0c;想搞清楚python入门小项目需要先了解以下几个事情。 来源丨网络 经常听到有朋友说&#xff0c;学习编程是一件非常枯燥无味的事情。其实&…

实现实时互动:用Spring Boot原生WebSocket打造你的专属聊天室

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; 实现实时互动&#xff1a;用Spring Boot原生WebSocket打造你的专属聊天…

详解Nodejs中的Process对象

在Nodejs中&#xff0c;process是一个全局对象&#xff0c;它提供了与当前进程和运行时环境交互的方法和属性。通过process对象&#xff0c;我们可以访问进程的信息、控制流程和进行进程间通信&#xff0c;这些都是服务端语言应该具备的能力。本文将全面介绍process对象的使用场…

【雕爷学编程】 MicroPython动手做(35)——体验小游戏2

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…