当前位置: 首页 > news >正文

【Spring】使用注解的方式获取Bean对象(对象装配)

目录

一、了解对象装配

1、属性注入

1.1、属性注入的优缺点分析

2、setter注入

 2.1、setter注入的优缺点分析

3、构造方法注入

 3.1、构造方法注入的优缺点

二、@Resource注解

三、综合练习


上一个博客中,我们了解了使用注解快速的将对象存储到Spring中,当然存储有简单方法,读取对象也可以使用注解的简单方法来实现,下面我们来了解一下,简单的获取对象的方法。

一、了解对象装配

获取Bean对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注入。

对象装配(对象注入)的实现方法有下面的三种方式

  1. 属性注入:会根据属性的类型,在容器种查找并获取对象,然后赋值给类的成员变量。
  2. 构造方法注入:通过构造方法将对象注入到对象中。
  3. Setter注入:通过setXXX 方法将对象注入到类中。

1、属性注入

属性注入只需要在需要注入对象的属性上加上@Autowired或者@Resource注解即可,这两个注解存在什么样的区别,我们在后面分析,这里我们以@Autowired注解来举例说明。

1️⃣容器中同类型的对象只有一个:直接将获取到的对象注入到当前属性上。

这里我们想让UserService类种获取到UserRepository类的对象,我们就需要在UserService类种设置一个类型是UserRepository的属性,给这个属性添加上@Autowired。表示的意思为从容器种获取这个属性类型的对象注入给这个属性。

首先给UserRepository类上添加类注解,将Bean存放在容器中。

package com.java.demo.dao;import org.springframework.stereotype.Repository;@Repository
public class UserRepository {public int add(){System.out.println("hello UserRepository");return 1;}
}

属性注入:将UserRepository在容器中的对象注入到UserService类中。

package com.java.demo.service;import com.java.demo.dao.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {//1.属性注入(DI:依赖注入)@Autowiredprivate UserRepository userRepository;public int add(){System.out.println("do UserService add method");return userRepository.add();}}

上面两步完成之后,我们就可以在测试类中,通过获取上下文对象(容器对象)来获取到userService对象(也就是依赖查找的方式获取到userService对象),然后调用userService对象的add方法,就可以观察到执行了UserRepository类的add方法,此时说明属性注入获取对象成功,我们并没有手动的new 这个userRepository对象。这里设置这个类只是用来检测属性注入(依赖注入)获取对象是否成功。

package com.java.demo.test;import com.java.demo.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");UserService userService = context.getBean("userService",UserService.class);userService.add();}
}

容器中同类型的对象只有一个的情况,属性注入的时候根据类型在Spring中查找,找到对象之后,直接复制给这个类型的属性,但是如果容器中同类型的对象存在多个的情况,就需要给属性指定注入那个对象。如果不指定这程序就会报错。

2️⃣容器中同类型的对象存在多个:如果获取到多个同类型对象,会根据属性的名字来进行匹配。

我们通过下面的例子来了解容器中存在多个同类型对象,在获取对象是没有指定给属性指定注入那个对象,程序出现的错误。

创建一个普通实体类User,然后再Users类中使用@Bean的方式向Spring中添加多个对象,然后再UserService类中使用属性注入的方式获取User类的对象注入到属性中。

package com.java.demo.model;public class User {private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}
}package com.java.demo.model;import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;@Component
public class Users {@Bean("user1")public User user1(){User user = new User();user.setId(1);user.setName("张三");return user;}@Bean("user2")public User user2(){User user = new User();user.setId(2);user.setName("李四");return user;}
}package com.java.demo.service;import com.java.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService2 {@Autowiredprivate User user;public void sayHi(){System.out.println(user.toString());}
}package com.java.demo.test;import com.java.demo.service.UserService2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");UserService2 userService2 = context.getBean("userService2",UserService2.class);userService2.sayHi();}
}

 上述的代码中由于获取到多个同类型的对象,不能直接根据类型将对象直接注入到当前类的属性中,需要根据属性的名称,将获取到的对象注入到属性中,但是属性的名称和对象名不相同的情况下,属性注入就会失败。想要解决这个问题,就需要设置对象名与属性名匹配,下面是三种解决这个问题的方法。

✨解决方案

1️⃣将属性的名字和Bean的名字对应上即可。

2️⃣ 也可以通过@Autowired注解和@Qualifier注解搭配使用,设置@Qualifier的参数为获取到的对象中的任意一个对象名即可,@Qualifier表示的意思就是根据参数筛选对象。

3️⃣属性上直接添加@Resource注解,这个注解的参数中存在name属性,我们可以将name的值设置获取到的对象中的某一个对象的名字。

 

1.1、属性注入的优缺点分析

1️⃣优点

 属性注入的优点就是使用简单,直选哟添加一个@Autowired注解,就可以在不new对象的情况下,直接获取注入的对象了。

2️⃣缺点

🍂功能性问题:无法注入一个不可变的对象(被final修饰的对象),因为被final修饰的变量只能有两种初始化的方式,一种是直接复制,一种是通过构造方法赋值。就不能通过属性注入的方式获取到对象了。

 🍂通用性问题:属性注入只能在IoC容器的前提下使用,脱离了IoC容器就不能使用了。

🍂设计原则问题:更容易违背单一设计原则,通俗来说就是属性注入的方式简单,滥用的概率就会很大。举个例子比如一个页面中不仅有用户的信息,也有用户请求的资源信息,那么后端写代码的时候在数据持久层的用户类中,本来就是针对用户注入相关的依赖,但是由于为了让程序的效率更高,有可能会在这个类中注入一些其他的信息相关的依赖。


2、setter注入

使用setter注入,在setXXX方法上添加一个@Autowired或者@Resource注解即可,当然setter注入也存在和属性注入一样的容器中相同类型的对象个数问题。这个问题的解决方法也和上述的属性注入时说的方法一样。

package com.java.demo.dao;import org.springframework.stereotype.Repository;@Repository
public class UserRepository {public int add(){System.out.println("hello UserRepository");return 1;}
}package com.java.demo.service;import com.java.demo.dao.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService3 {private UserRepository userRepository;@Autowiredpublic void setUserRepository(UserRepository userRepository) {this.userRepository = userRepository;}public void sayHi(){System.out.println("hello UserService3 .");userRepository.add();}
}package com.java.demo.test;import com.java.demo.service.UserService3;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");UserService3 userService3 = context.getBean("userService3",UserService3.class);userService3.sayHi();}
}

 2.1、setter注入的优缺点分析

1️⃣优点

setter更符合单一设计原则,因为那个setter方法,只是针对一个属性进程赋值。

2️⃣缺点

🍂无法注入一个final修饰的变量,因为final修饰的变量初始化的时候只有两种方式要么直接初始化,要么通过构造方法初始化。

🍂注入的对象可被修改。因为setXXX是一个方法,所以他就可能别调用,这个时候就会导致注入的Bean对象被修改了。


3、构造方法注入

使用构造方法注入,标准的写法在构造方法上添加一个@Autowired注解或者在构造方法上不加注解也可以实现注入效果。当然构造注入也存在和属性注入一样的容器中相同类型的对象个数问题。这个问题的解决方法也和上述的属性注入时说的方法一样。这里构造方法不支持使用@Resource注解。

1️⃣标准的写法构造方法上添加@Autowired注解

package com.java.demo.dao;import org.springframework.stereotype.Repository;@Repository
public class UserRepository {public int add(){System.out.println("hello UserRepository");return 1;}
}package com.java.demo.service;import com.java.demo.dao.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService4 {private UserRepository userRepository;@Autowiredpublic UserService4(UserRepository userRepository) {this.userRepository = userRepository;}public void sayHi(){System.out.println("hello userService4 .");userRepository.add();}
}package com.java.demo.test;import com.java.demo.service.UserService2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");UserService4 userService4 = context.getBean("userService4",UserService4.class);userService4.sayHi();}
}

 2️⃣不太标准的写法,构造方法上不加注解,这种写法是当前类中只有一个构造方法的时候可以使用的如果有多个构造方法的时候,构造方法上的@Autowired注解是不可以省略的。

 3.1、构造方法注入的优缺点

1️⃣优点

🍂可以注入不可变对象(被final修改的变量)

 🍂注入的对象不会被修改,因为构造方法会随着JVM的启动而被加载,只会被加载一次。就像上面的例子userRepositoryd对象注入到UserService4这个类中,这个类实例化被存入容器的时候,构造方法只会执行一次。

🍂构造方法注入,可以保证注入对象完全初始化,因为构造方法是在对象创建之前执行的。

🍂构造方法注入的通用性最好的,因为一个类中使用了构造方法注入,当你要使用这个类的对象的时候你就不得不给构造方法中的参数(当前类的属性)注入一个对象。

2️⃣缺点

🍂构造方法注入的写法比属性注入复杂

🍂构造方法注入的写法无法解决循环依赖的问题


二、@Resource注解

@Resource注解和@Autowired注解的用法是相同的,都可以注入对象。

 ✨@Resource和@Autowired的区别

1️⃣出生不同:@Autowired来自于Spring,而@Resource来自于JDK的注解;

2️⃣支持参数不同:@Autowired的参数只有一个,而@Ressource支持更多的参数设置。

 3️⃣使用上的区别@Autowired可用于Setter注入、构造方法注入和属性注入,但是@Resource只能用于Setter注入和属性注入,不支持使用构造方法注入

4️⃣idea兼容性支持不同:使用@Autowired在idea专业版下可能出现误报,@Resource不存在误报的问题。


三、综合练习

在 Spring 项⽬中,通过 main ⽅法获取到 Controller 类,调⽤ Controller ⾥⾯通过注⼊的⽅式调⽤ Service 类,Service 再通过注⼊的⽅式获取到 Repository 类,Repository 类⾥⾯有⼀个⽅法构建⼀ 个 User 对象,返回给 main ⽅法。Repository ⽆需连接数据库,使用伪代码即可。

这里需要注意的是,通过main方法获取Controller类,在main方法中不能使用依赖注入的方式获取对象,因为main方法为静态方法,静态方法的执行是在Spring框架之前的,所以我们需要使用依赖查找的方式获取容器对象,然后获取对象。

类的设置路径

 

package com.java.demo.model;public class User {private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}}
package com.java.demo.dao;import com.java.demo.model.User;
import org.springframework.stereotype.Repository;@Repository
public class UserRepository {//伪代码public User getUser(){User user = new User();user.setId(1);user.setName("王五");return user;}}
package com.java.demo.service;import com.java.demo.dao.UserRepository;
import com.java.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {@Autowiredprivate UserRepository userRepository;public User getUser(){return userRepository.getUser();}
}
package com.java.demo.controller;import com.java.demo.model.User;
import com.java.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class UserController {@Autowiredprivate UserService userService;public User getUser(){return userService.getUser();}
}
package com.java.demo;import com.java.demo.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");UserController userController = context.getBean("userController",UserController.class);System.out.println(userController.getUser());}
}

 

相关文章:

【Spring】使用注解的方式获取Bean对象(对象装配)

目录 一、了解对象装配 1、属性注入 1.1、属性注入的优缺点分析 2、setter注入 2.1、setter注入的优缺点分析 3、构造方法注入 3.1、构造方法注入的优缺点 二、Resource注解 三、综合练习 上一个博客中,我们了解了使用注解快速的将对象存储到Spring中&#x…...

[webpack] 基本配置 (一)

文章目录 1.基本介绍2.功能介绍3.简单使用3.1 文件目录和内容3.2 下载依赖3.3 启动webpack 4.基本配置4.1 五大核心概念4.2 基本使用 1.基本介绍 Webpack 是一个静态资源打包工具。它会以一个或多个文件作为打包的入口, 将我们整个项目所有文件编译组合成一个或多个文件输出出去…...

模板学堂|SQL数据集动态参数使用场景及功能详解

DataEase开源数据可视化分析平台于2022年6月正式发布模板市场(https://dataease.io/templates/)。模板市场旨在为DataEase用户提供专业、美观、拿来即用的仪表板模板,方便用户根据自身的业务需求和使用场景选择对应的仪表板模板&a…...

Wlan——射频和天线基础知识

目录 射频的介绍 射频和Wifi 射频的相关基础概念 射频的传输 信号功率的单位 射频信号传输行为 天线的介绍 天线的分类 天线的基本原理 天线的参数 射频的介绍 射频和Wifi 什么是射频 从射频发射器产生一个变化的电流(交流电),通过…...

前端实习周记第三周周记

第二周总结 第二周主要是做了一些PC端细节内容。大的地方改的不多,但是小的细节蛮多。 值得一提的是,第二周做的微信小程序,改了很多逻辑。改逻辑需要与后端进行联调,收获很大,思路也愈发清楚。 记录做了什么是好习…...

Android 13 Launcher界面——移除Launcher的删除和卸载功能

目录 一.背景 二.将卸载功能进行屏蔽 三.将移除功能屏蔽 四.将Remove按钮与Uninstall按钮屏蔽...

深度学习:使用卷积神经网络CNN实现MNIST手写数字识别

引言 本项目基于pytorch构建了一个深度学习神经网络,网络包含卷积层、池化层、全连接层,通过此网络实现对MINST数据集手写数字的识别,通过本项目代码,从原理上理解手写数字识别的全过程,包括反向传播,梯度…...

docker search 镜像报错: connect: no route to host (桥接模式配置静态IP)

如下 原因 可能有多种: ① 没有开放防火墙端口 ② ip地址配置有误 解决 我是因为虚拟机采用了桥接模式,配置静态ip地址有问题。 先确认虚拟机采用的是 桥接模式,然后启动虚拟机。 1、打开命令行,输入下面指令,打开…...

【VUE】[Violation] Added non-passive event listener to a scroll-blocking...

环境 chrome: 115.0.5790.170vue: ^3.3.4element-plus: ^2.3.4vite: ^4.4.7 问题 [Violation] Added non-passive event listener to a scroll-blocking <某些> 事件. Consider marking event handler as passive to make the page more responsive. See <URL> …...

runit-docker中管理多个服务

runit-docker中管理多个服务 介绍Runit, systemctl和supervisor是三种不同的服务管理工具区别runit优点程序构成快速开始runit实现服务退出执行指定操作runit监管服务打印日志到syslogrunit监管服务后台运行runit监管服务一些错误总结 介绍 runit 是一个轻量级的、稳定的、跨平…...

Intune 应用程序管理

由于云服务提供了增强的安全性、稳定性和灵活性&#xff0c;越来越多的组织正在采用基于云的解决方案来满足他们的需求。这正是提出Microsoft Endpoint Manager等解决方案的原因&#xff0c;它结合了SCCM和Microsoft Intune&#xff0c;以满足本地和基于云的端点管理。 与 Int…...

Oracle DB 安全性 : TDE HSM TCPS Wallet Imperva

• 配置口令文件以使用区分大小写的口令 • 对表空间进行加密 • 配置对网络服务的细粒度访问 TCPS 安全口令支持 Oracle Database 11g中的口令&#xff1a; • 区分大小写 • 包含更多的字符 • 使用更安全的散列算法 • 在散列算法中使用salt 用户名仍是Oracle 标识…...

leetcode27—移除元素

思路&#xff1a; 参考26题目双指针的思想&#xff0c;只不过这道题不是快慢指针。 看到示例里面数组是无序的&#xff0c;也就是说后面的元素也是可能跟给定 val值相等的&#xff0c;那么怎么处理呢。就想到了从前往后遍历&#xff0c;如果left对应的元素 val时&#xff0c…...

flask---》更多查询方式/连表查询/原生sql(django-orm如何执行原生sql)/flask-sqlalchemy

更多查询方式 #1 查询&#xff1a; filer:写条件 filter_by&#xff1a;等于的值 # 查询所有 是list对象 res session.query(User).all() # 是个普通列表 print(type(res)) print(len(res))# 2 只查询某几个字段 # select name as xx,email from user; res session.…...

Chromium内核浏览器编译记(三)116版本内核UI定制

转载请注明出处&#xff1a;https://blog.csdn.net/kong_gu_you_lan/article/details/132180843?spm1001.2014.3001.5501 本文出自 容华谢后的博客 往期回顾&#xff1a; Chromium内核浏览器编译记&#xff08;一&#xff09;踩坑实录 Chromium内核浏览器编译记&#xff08;…...

LoRaWan网关设计架构介绍

LoRa 数据包转发器是在基于 LoRa 的网关(带或不带 GPS)主机上运行的程序。它将集中器(上行链路)接收到的 RF 数据包通过安全的 IP 链路转发到LoRaWAN 网络服务器( LNS )。它还通过相同的安全 IP 将 LNS(下行链路)发送的 RF 数据包传输到一台或多台设备。此外,它还可以传…...

vue 全局状态管理(简单的store模式、使用Pinia)

目录 为什么使用状态管理简单的store模式服务器渲染&#xff08;SSR&#xff09; pinia简介示例1. 定义一个index.ts文件2. 在main.ts中引入3. 定义4. 使用 为什么使用状态管理 多个组件可能会依赖同一个状态时&#xff0c;我们有必要抽取出组件内的共同状态集中统一管理&…...

ORACLE和MYSQL区别

1&#xff0c;Oracle没有offet,limit&#xff0c;在mysql中我们用它们来控制显示的行数&#xff0c;最多的是分页了。oracle要分页的话&#xff0c;要换成rownum。 2&#xff0c;oracle建表时&#xff0c;没有auto_increment&#xff0c;所有要想让表的一个字段自增&#xff0c…...

tensorflow 1.14 的 demo 02 —— tensorboard 远程访问

tensorflow 1.14.0&#xff0c; 提供远程访问 tensorboard 服务的方法 第一步生成 events 文件&#xff1a; 在上一篇demo的基础上加了一句&#xff0c;如下&#xff0c; tf.summary.FileWriter("./tmp/summary", graphsess1.graph) hello_tensorboard_remote.py …...

Spring中Bean的循环依赖问题

1.什么是Bean的循环依赖&#xff1f; 简单来说就是在A类中&#xff0c;初始化A时需要用到B对象&#xff0c;而在B类中&#xff0c;初始化B时需要用到A对象&#xff0c;这种状况下在Spring中&#xff0c;如果A和B同时初始化&#xff0c;A&#xff0c;B同时都需要对方的资源&…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...