Java注解之@Autowired,一文掌握@Autowired注解知识(3)

在这里插入图片描述

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。
🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。
🎉欢迎 👍点赞✍评论⭐收藏

Java注解知识专栏学习

Java注解知识云集访问地址备注
Java注解知识点(1)https://blog.csdn.net/m0_50308467/article/details/135240536Java注解专栏
Java注解知识点(2)https://blog.csdn.net/m0_50308467/article/details/135263693Java注解专栏
Java注解知识点(3)https://blog.csdn.net/m0_50308467/article/details/135278911Java注解专栏

文章目录

  • 🏆 学习Java注解之@Autowired
    • 🔎 Java 注解@Autowired学习(3)
      • 🍁🍁 01、如何解决在使用 @Autowired 注解时可能出现的循环依赖问题?
      • 🍁🍁 02、是否可以在静态字段上使用 @Autowired 注解?
      • 🍁🍁 03、如何处理在使用 @Autowired 注解时出现多个匹配候选对象的情况?
      • 🍁🍁 04、如何使用 @Autowired 注解注入集合类型的依赖?
      • 🍁🍁 05、是否可以在构造函数上同时使用 @Autowired 和 @Value 注解?
      • 🍁🍁 06、如何通过 @Autowired 注解注入通用的 ApplicationContext 对象?
      • 🍁🍁 07、@Autowired 注解的 required 属性的作用是什么?
      • 🍁🍁 08、如何自定义一个注解来替代 @Autowired 注解的功能?

🏆 学习Java注解之@Autowired

🔎 Java 注解@Autowired学习(3)

🍁🍁 01、如何解决在使用 @Autowired 注解时可能出现的循环依赖问题?

在使用 @Autowired 注解时,可能会出现循环依赖的问题。循环依赖指的是两个或多个 Bean 之间相互引用,无法完成依赖注入的情况。

为了解决循环依赖问题,Spring 提供了三种解决方案:

1. 构造器注入:使用构造器注入可以避免循环依赖问题。在每个类的构造器参数中,注入所需的依赖项。这样,在实例化每个类时,所有依赖关系都已解决,不会发生循环依赖的情况。

@Component
public class A {
    private B b;
    
    @Autowired
    public A(B b) {
        this.b = b;
    }
}

@Component
public class B {
    private A a;
    
    @Autowired
    public B(A a) {
        this.a = a;
    }
}

2. @Lazy 注解@Lazy 注解可以延迟解决循环依赖问题。通过将 @Lazy 注解应用到需要延迟注入的 bean 上,可以确保在需要使用时才进行依赖注入。

@Component
@Lazy
public class A {
    @Autowired
    private B b;
}

@Component
@Lazy
public class B {
    @Autowired
    private A a;
}

3. @DependsOn 注解@DependsOn 注解可以指定 bean 之间的依赖顺序,从而解决循环依赖问题。通过在需要指定顺序的 bean 上使用 @DependsOn 注解,可以确保被注解的 bean 在指定的 bean 之后实例化。

@Component
@DependsOn("b")
public class A {
    @Autowired
    private B b;
}

@Component
public class B {
    @Autowired
    private A a;
}

需要注意的是,循环依赖是一种不良的设计模式,尽量要避免出现循环依赖的情况。如果你在设计中出现了循环依赖,可以考虑重构代码,优化依赖关系,以减少循环依赖发生的可能性。

🍁🍁 02、是否可以在静态字段上使用 @Autowired 注解?

不可以在静态字段上使用 @Autowired 注解。@Autowired 注解是用来实现依赖注入的,它将自动将对应类型的 bean 注入到被注解的字段、构造器或方法参数上。但是,静态字段(static fields)属于类级别,而不是对象级别,无法通过依赖注入的方式进行注入。

@Autowired 注解通常用于实例化的对象,它将在对象创建时注入依赖的 bean。而静态字段不依赖于对象的创建和生命周期,它是类加载时就分配的静态资源。这意味着无法使用 @Autowired 注解将 bean 自动注入到静态字段上。

如果你需要在静态字段上引用依赖的 bean,可以考虑通过静态方法或其他方式手动获取该 bean,或者将依赖的 bean 作为参数传递给静态方法,以实现所需的功能。

🍁🍁 03、如何处理在使用 @Autowired 注解时出现多个匹配候选对象的情况?

在使用 @Autowired 注解时,如果存在多个匹配候选对象(multiple matching candidates),将会导致注入失败,Spring 框架会抛出 NoUniqueBeanDefinitionException 异常。

为了解决多个匹配候选对象的问题,Spring 框架提供了多种解决方案,具体如下:

1. 使用 @Qualifier 注解@Qualifier 注解可以和 @Autowired 注解一起使用,消除多个匹配候选项的歧义。@Qualifier 注解指定了要注入的 bean 的名称或 ID。

示例如下:

@Component("myComponentA")
public class MyComponentA implements MyComponentInterface {
    // ...
}

@Component("myComponentB")
public class MyComponentB implements MyComponentInterface {
    // ...
}

@Component
public class MyComponentConsumer {
    @Autowired
    @Qualifier("myComponentA")
    private MyComponentInterface myComponentA;

    @Autowired
    @Qualifier("myComponentB")
    private MyComponentInterface myComponentB;
}

2. 使用 @Primary 注解@Primary 注解用于标识 bean 的首选项,当一个类型的 bean 有多个候选对象时,Spring 框架将优先选择带有 @Primary 注解的 bean。

示例如下:

@Component
@Primary
public class MyPrimaryComponent implements MyComponentInterface {
    // ...
}

@Component
public class MyComponentConsumer {
    @Autowired
    private MyComponentInterface myComponent;
}

3. 使用 ListMap 类型:如果存在多个匹配候选项,可以使用 ListMap 类型来注入所有匹配的 bean。如果存在多个匹配项,Spring 框架会自动将它们注入一个 ListMap 实例中。可以使用 @Autowired 注解将 ListMap 注入到目标 bean 中。

示例如下:

@Component
public class MyComponentA implements MyComponentInterface {
    // ...
}

@Component
public class MyComponentB implements MyComponentInterface {
    // ...
}

@Component
public class MyComponentConsumer {
    @Autowired
    private List<MyComponentInterface> myComponentList;

    @Autowired
    private Map<String, MyComponentInterface> myComponentMap;
}

在使用上述解决方案时,需要根据实际情况选择最适合的方法,以确保正确地注入 bean。需要注意的是,选择不同的解决方案可能会影响代码的可读性和复杂度,因此需要在考虑各种因素的情况下选择最适合的方案。

🍁🍁 04、如何使用 @Autowired 注解注入集合类型的依赖?

要使用 @Autowired 注解注入集合类型的依赖,可以依赖注入一个集合(如 ListSetMap)来容纳匹配的 bean。

以下是几种常见的方式:

1. 使用 List 注入:

@Component
public class MyComponentConsumer {
    @Autowired
    private List<MyComponentInterface> myComponentList;
}

在上面的示例中,所有实现了 MyComponentInterface 接口的 bean 都会被自动注入到 myComponentList 中。

2. 使用 Set 注入:

@Component
public class MyComponentConsumer {
    @Autowired
    private Set<MyComponentInterface> myComponentSet;
}

List 类似,所有实现了 MyComponentInterface 接口的 bean 都会被自动注入到 myComponentSet 中,但是 Set 不允许重复的元素。

3. 使用 Map 注入:

@Component
public class MyComponentConsumer {
    @Autowired
    private Map<String, MyComponentInterface> myComponentMap;
}

在上面的示例中,myComponentMap 将以 bean 的名称作为键,MyComponentInterface 实例作为值。可以通过键来访问和调用相应的 bean。

需要注意的是,确保集合的泛型参数正确,并且匹配的 bean 类型与集合的泛型参数相符。另外,如果没有匹配的 bean,集合将是空的而不是 null。

这三种方式都可以用于注入集合类型的依赖。它们之间的主要区别在于它们所使用的容器类型以及容器的特性。

  1. List 类型:使用 List 类型可以容纳多个元素,并且元素的顺序是按照它们被添加到集合中的顺序。如果需要按照固定的顺序处理多个实例,就可以使用 List 类型。

  2. Set 类型:使用 Set 类型可以容纳多个元素,但是集合中的元素是无序的并且不能重复。如果需要在一个集合中保证唯一性,可以使用 Set 类型。

  3. Map 类型:使用 Map 类型可以容纳多个键值对,并且键值对是唯一的。使用 Map 可以根据键值对应的键(例如 bean 的名称)来访问相应的实例,这种方式比较灵活。

在实际开发中,应根据具体的需求选择最适合的类型,以便更好地处理依赖注入的集合类型。

下面是一个表格,说明了使用 ListSetMap 类型注入集合类型依赖的主要区别:

区别ListSetMap
容器类型ListSetMap
元素顺序有序无序无序
元素唯一性元素可以重复元素不重复键值对的键不重复
访问方式按照索引访问无法用索引访问通过键访问
注入示例List<MyComponent>Set<MyComponent>Map<String, MyComponent>
示例代码`````````
@Autowiredprivate List<MyComponent> myComponentList;private Set<MyComponent> myComponentSet;private Map<String, MyComponent> myComponentMap;
````````````

希望以上的表格能够清晰地展示 ListSetMap 在注入集合类型依赖方面的区别。根据具体的需求,选择最合适的容器类型进行注入。

🍁🍁 05、是否可以在构造函数上同时使用 @Autowired 和 @Value 注解?

可以同时在构造函数上使用 @Autowired@Value 注解,但是需要注意一些细节。

首先,@Autowired 用于注入类的实例,而 @Value 用于注入配置属性值。因此,@Autowired@Value 同时使用时,需要保证它们分别注入不同类型的依赖。

另外需要注意的是,@Value 注解需要指定一个属性名称来获取对应的配置值,例如:

public class MyComponent {
    private String name;

    public MyComponent(@Value("${my.component.name}") String name) {
        this.name = name;
    }
    // ...
}

在这个例子中,@Value 注解通过 ${my.component.name} 从配置文件中获取 name 属性值并注入到构造函数中。

如果需要在构造函数中同时使用 @Autowired@Value 注解,可以在构造函数参数列表中按顺序声明 @Autowired@Value 注解,例如:

public class MyComponent {
    private AnotherComponent anotherComponent;
    private String name;

    public MyComponent(@Autowired AnotherComponent anotherComponent, @Value("${my.component.name}") String name) {
        this.anotherComponent = anotherComponent;
        this.name = name;
    }
    // ...
}

在这个例子中,@Autowired 注解注入了 AnotherComponent 的实例,@Value 注解注入了 name 属性值。

需要注意的是,使用 @Autowired@Value 同时注入多个属性时,建议按照属性类型或者名称进行排序,提高代码的可读性。使用 @Autowired@Value 注解时,最好注入不同类型的依赖,以确保注入顺序正确性。

🍁🍁 06、如何通过 @Autowired 注解注入通用的 ApplicationContext 对象?

要通过 @Autowired 注解注入通用的 ApplicationContext 对象,可以按照以下步骤进行操作:

1. 在类中添加 @Autowired 注解,并将 ApplicationContext 类型的属性声明为需要注入的字段。

@Autowired
private ApplicationContext applicationContext;

2. 确保你的项目中已经正确地配置了 Spring 上下文,并且已经将 ApplicationContext 注册为一个 Bean。

@Configuration
public class AppConfig {

    @Bean
    public ApplicationContext applicationContext() {
        // 返回适当的 ApplicationContext 实例
        // ...
    }
    
    // 其他配置
    // ...
}

3. 在目标类中使用注入的 ApplicationContext 对象进行需要的操作。

public class MyComponent {

    @Autowired
    private ApplicationContext applicationContext;

    public void doSomething() {
        // 使用 applicationContext 进行操作
        // ...
    }

    // ...
}

现在,当 MyComponent 类的实例被创建时,Spring 容器会自动注入 ApplicationContext 对象,并使其可用。

请确保你的 Spring 配置正确,并且 ApplicationContext 已经正确注册为一个 Bean。同时,也要确保目标类已被 Spring 所管理(例如通过 @Component 注解或 XML 配置等方式进行管理)。

记住,虽然可以通过 ApplicationContext 进行各种操作,但应首先仔细考虑依赖注入的最佳实践,并尽量避免直接访问 Spring 上下文对象。依赖注入是一种更好的设计模式,可以提高代码的可测试性和可维护性。

🍁🍁 07、@Autowired 注解的 required 属性的作用是什么?

@Autowired 注解的 required 属性用于指定所注入的依赖是否为必需的。默认情况下,@Autowired 注解的 required 属性为 true,即所注入的依赖是必需的。当这个依赖不能被注入时,Spring 将会抛出一个异常。

例如,如果没有正确配置所依赖的对象或者没有匹配的候选对象,则会抛出 org.springframework.beans.factory.NoSuchBeanDefinitionException 异常。

@Autowired(required = true)
private MyDependency myDependency;

在上面的示例中,MyDependency 对象是必需的。如果没有找到匹配的对象,则会抛出异常。

如果将 required 属性设置为 false,则所注入的对象不是必需的。当没有找到匹配的对象时,Spring 只会不进行依赖注入,而不会抛出异常。

@Autowired(required = false)
private MyDependency myDependency;

这在编写可选依赖关系的代码时非常有用,例如,可以使用 @Autowired(required = false) 将 ORM 框架或存储库作为可选依赖注入到 Spring 组件中,而不必强制要求具有相关的依赖项。

需要注意的是,在使用 required 属性时,应当牢记依赖的正确性,确保不能发生未明确处理的空指针异常等问题。

总之,通过控制 required 属性,可以实现对所注入依赖的精细处理,避免在依赖项未正确配置时出现不愉快的运行时异常。

🍁🍁 08、如何自定义一个注解来替代 @Autowired 注解的功能?

要自定义一个注解来替代 @Autowired 注解的功能,可以按照以下步骤进行操作:

1. 创建一个自定义注解, 使用 @Retention(RetentionPolicy.RUNTIME) 保留策略和 @Target(ElementType.FIELD) 目标元素类型。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyCustomAutowired {
}

2. 在需要进行依赖注入的字段上使用自定义注解。

public class MyClass {
    @MyCustomAutowired
    private MyDependency myDependency;

    // ...
}

3. 创建一个后置处理器类, 实现 BeanPostProcessor 接口,用于处理标记有自定义注解的字段。

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;

public class MyCustomAutowiredProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        Field[] fields = bean.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(MyCustomAutowired.class)) {
                Object dependency = // 根据自定义注解的逻辑获取依赖对象

                // 设置字段可访问性以允许注入
                ReflectionUtils.makeAccessible(field);
                // 为字段注入依赖对象
                ReflectionUtils.setField(field, bean, dependency);
            }
        }
        return bean;
    }

    // 可选择实现 postProcessAfterInitialization() 方法进行其他处理

}

4. 将后置处理器类注册到 Spring 上下文中。

可以通过 XML 配置或者在配置类中使用 @Bean 注解进行注册。

@Configuration
public class AppConfig {

    @Bean
    public MyCustomAutowiredProcessor myCustomAutowiredProcessor() {
        return new MyCustomAutowiredProcessor();
    }

    // ...

}

完成以上步骤后,当 Spring 容器初始化时,后置处理器将会检查标记有 @MyCustomAutowired 注解的字段,并根据自定义的逻辑进行依赖注入操作。

请注意,这只是一个简化的示例,实际情况下你可能需要根据自己的需求对后置处理器进行修改和扩展。

同时,还需确保在 Spring 配置中正确设置了 MyClassMyDependency 的相关定义,让它们被 Spring 所管理。

自定义注解能够帮助我们更好地扩展和控制依赖注入的行为,但在使用自定义注解时,同样要考虑代码的可读性和可维护性,以及与团队的共识和约定一致。

在这里插入图片描述

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

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

相关文章

k8s搭建(四、k8s集群创建)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

05-C++ 类和对象-继承

类与对象-03 继承与派生 1. 继承的概念 c最重要的特征是代码重用&#xff0c;通过继承机制可以利用已有的数据类型&#xff0c;来定义新的数据类型&#xff0c;新的类不仅拥有旧类的成员&#xff0c;还拥有新定义的成员。 一个 B 类继承于 A 类&#xff0c;或称从类 A 派生…

QCheckBoxQRadioBoxQComboBoxQSlider

QCheckBox QCheckBox 是 Qt 框架中一个常用的控件&#xff0c;用于创建一个可以勾选或取消勾选的复选框。它通常用于表示选项的开/关状态 autoExclusive 是一个与单选按钮&#xff08;QRadioButton&#xff09;相关的属性。这个属性决定了同一个父窗口下的单选按钮是否自动形成…

【C++干货铺】STL中set和map的介绍和使用

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 序列式容器 关联式容器 键值对 树形结构的关联式容器 set set的介绍 set的使用 set的模板参数列表 set的构造 ​编辑 set的容量 set的删除和查找 mult…

125 验证回文串

如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字母和数字都属于字母数字字符。 给你一个字符串 s&#xff0c;如果它是 回文串 &#xff0c;返回 true &#xff1b;否则&#…

软件测试/测试开发丨Python常用数据结构-列表list

列表的定义 列表是有序的可变元素的集合&#xff0c;使用中括号[ ]包围&#xff0c;元素之间用逗号分隔&#xff1b;列表是动态的&#xff0c;可以随时扩展和收缩&#xff1b;列表是异构的&#xff0c;可以同时存放不同类型的对象&#xff1b;列表允许出现重复的元素。 列表的…

电子企业实施MES管理系统需要多少预算

在当今高度自动化的工业环境中&#xff0c;MES管理系统已成为提升生产效率、优化资源配置、确保产品质量的关键工具。对于电子企业而言&#xff0c;实施MES管理系统不仅可以提升生产过程的透明度&#xff0c;还能有效降低成本&#xff0c;增强市场竞争力。然而&#xff0c;企业…

SV接口的驱动和采样_2023.12.27】

cb 使用cloking block进行信号的同步 在cloking block&#xff0c;所有信号的采样和驱动&#xff0c;都是和时钟同步的 clocking cb &#xff08;posedge clk&#xff09;; input grant; output request; endclocking接口同步 用和wait来同步测试平台中的信号 bus.cb; 接口…

uboot安装操作系统

FT1500A 刀片机uboot安装系统 外接sata盘的方式&#xff1a; 准备一个带系统的sata盘&#xff08;系统必须支持这个硬件不然启不来&#xff0c;uboot不需要改什么默认进这个系统&#xff09;&#xff0c;把iso与脚本harddisk_copy-noarch_20160711.sh拷进去 通过mobaxterm或…

《Python》:深拷贝、浅拷贝、赋值之间的关系(附可变与不可变)【用图文讲清楚!】

背景 想必大家面试或者平时学习经常遇到问python的深拷贝、浅拷贝和赋值之间的区别了吧&#xff1f;看网上的文章很多写的比较抽象&#xff0c;小白接收的难度有点大&#xff0c;于是乎也想自己整个文章出来供参考 可变与不可变 讲深拷贝和浅拷贝之前想讲讲什么是可变数据类型…

Kubernetes 学习总结(43)—— Kubernetes 从提交 deployment 到 pod 运行的全过程

当用户向 Kubernetes 提交了一个创建 deployment 的请求后&#xff0c;Kubernetes 从接收请求直至创建对应的 pod 运行这整个过程中都发生了什么呢&#xff1f; kubernetes 架构简述 在搞清楚从 deployment 提交到 pod 运行整个过程之前&#xff0c;我们有先来看看 Kubernete…

【unity学习笔记】配置模型,实现眨眼和口型效果

一、vriod捏人 1.在vroidstudio软件中捏人 2.导出模型&#xff08;.vrm) 二、vrid导入unity的插件 1.在Git上搜索、打开univrm。 2.找到release页面找到合适的插件版本。&#xff08;VRM-0.116.0_0f6c&#xff09; 3.将univrm导入到工程中&#xff08;assets&#xff09;。 三…

Vue - 实现文件导出文件保存下载

1 文件导出&#xff1a;使用XLSX插件 需求背景&#xff1a;纯前端导出&#xff0c;如 在前端页面勾选部分表格数据&#xff0c;点击"导出"按钮导出Excel文件。 实现思路&#xff1a; 1.通过XLSX插件的 XLSX.utils.book_new()方法&#xff0c;创建excel工作蒲对象wb…

基于YOLOv7算法的高精度实时行人打电话检测系统(PyTorch+Pyside6+YOLOv7)

摘要&#xff1a;基于YOLOv7算法的高精度实时行人打电话检测系统可用于日常生活中检测与定位手机&#xff0c;此系统可完成对输入图片、视频、文件夹以及摄像头方式的目标检测与识别&#xff0c;同时本系统还支持检测结果可视化与导出。本系统采用YOLOv7目标检测算法来训练数据…

2023年度总结:技术旅程的杨帆远航⛵

文章目录 职业规划与心灵成长 ❤️‍&#x1f525;我的最大收获与成长 &#x1f4aa;新年Flag &#x1f6a9;我的技术发展规划 ⌛对技术行业的深度思考 &#x1f914;祝愿 &#x1f307; 2023 年对我来说是一个充实而令人难以忘怀的一年。这一年&#xff0c;我在CSDN上发表了 1…

3D视觉-激光三角测量法的分类

按照入射激光光束和被测物体表面法线的角度关系&#xff0c;一般分为直射式和斜射式两种方式。 1&#xff09;直射式测量 如图所示&#xff0c;激光器发出的光线&#xff0c;经会聚透镜聚焦后垂直入射到被测物体表面上&#xff0c;物体移动或者其表面变化&#xff0c;导致入射…

网络安全专家常用的12个操作系统

文章目录 前言一、什么是网络安全专家常用的OS和工具二、漏洞赏金猎人常用操作系统Kali LinuxParrot OSBlackArch Linux 三、恶意软件分析和逆向工程操作系统REMnux OSFlare-VM &#xff08;工具&#xff09; 四、OSINT和信息采集操作系统CSI LinuxTsurugi Linux 五、事件响应和…

PulseGAN

研究背景 远程光电容积描记术 (rPPG) 是一种非接触式技术&#xff0c;用于测量面部视频中的心脏信号。健康监测和情绪识别等许多领域都迫切需要高质量的 rPPG 脉冲信号。然而&#xff0c;由于脉搏信号不准确的限制&#xff0c;现有的大多数rPPG方法只能用于获取平均心率&#…

云上攻防--云服务对象存储(域名接管)弹性计算(元数据泄露)

云上攻防–云服务&&对象存储(域名接管)&&弹性计算(元数据泄露) 目录标题 云上攻防--云服务&&对象存储(域名接管)&&弹性计算(元数据泄露)对象存储权限配置错误域名接管AK/SK泄漏&#xff1a; 弹性计算元数据泄露加固措施 对象存储 各个厂商对于…

第6章 网页布局

学习目标 熟悉网页布局&#xff0c;能够说明DIVCSS布局的含义。 掌握元素的浮动属性&#xff0c;能够为元素添加和清除浮动。 熟悉overflow属性的用法&#xff0c;能够设置不同的内容溢出状态。 掌握元素的定位属性&#xff0c;能够设置不同的定位模式。 了解元素的类型&am…
最新文章