springboot系列--web相关知识探索四

news2024/10/6 0:50:57

一、前言 

web相关知识探索三中研究了请求中所带的参数是如何映射到接口参数中的,也即请求参数如何与接口参数绑定。主要有四种、分别是注解方式、Servlet API方式、复杂参数、以及自定义对象参数。web相关知识探索三中主要研究了注解方式以及Servlet API方式。本次研究主要是复杂参数底层绑定原理。

二、 复杂参数底层绑定原理

一、测试用例

请求的接口当中,还可以放入这些类型作为参数,MapModel(map、model里面的数据会被默认放在request的请求域 request.setAttribute)、Errors/BindingResult、RedirectAttributes( 重定向携带数据)ServletResponse(response)、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder。

    /**
     * 请求进来这个接口,然后往map设置数据,同时也往model和request设置数据,
     * 处理完之后再转发到下一个接口,下一个接口再从请求域中拿出map和model中设置的数据
     * 这里主要是验证,接口参数map和moddel,请求进来时,携带到的值是放在请求域中的
     * Map<String,Object> map,  Model model, HttpServletRequest request 都是可以给request域中放数据,
     * @param map
     * @param model
     * @param request
     * @return
     */
    @GetMapping("/test")
    public String testParam(Map<String,Object> map, Model model, HttpServletRequest request, HttpServletResponse response){
        map.put("test1","mapTest");
        model.addAttribute("test2","modelTest");
        request.setAttribute("test3","requestTest");
        Cookie cookie = new Cookie("test4","cookieTest");
        response.addCookie(cookie);
        return "forward:/success";
    }

    @GetMapping("/success")
    @ResponseBody
    public Map testSuccess(HttpServletRequest request){
        Object test1 = request.getAttribute("test1");
        Object test2 = request.getAttribute("test2");
        Object test3 = request.getAttribute("test3");

        Map mp = new HashMap();
        mp.put("test1",test1);
        mp.put("test2",test2);
        mp.put("test3",test3);
        return mp;
    }

二、底层原理

一、Map参数解析

请求进来以后,直接到匹配合适的参数解析器这一步,第一个参数是Map类型的,所以需要的是能够解析Map类型参数的解析器。

 

上面是判断那种解析器支持解析Map类型参数,下面开始解析Map类型参数 

 

    // 解析map类型参数
    @Nullable
    public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
        Assert.state(mavContainer != null, "ModelAndViewContainer is required for model exposure");
        // 直接从一个ModelAndViewContainer(模型和视图容器)对象中获取一个model
        return mavContainer.getModel();
    }





    // 获取模型对象
    public ModelMap getModel() {
        默认会进入这条路径
        if (this.useDefaultModel()) {
            return this.defaultModel;
        } else {
            if (this.redirectModel == null) {
                this.redirectModel = new ModelMap();
            }

            return this.redirectModel;
        }
    }

 获取到的model对象是一个

private final ModelMap defaultModel = new BindingAwareModelMap();

也就是说,获取到的是一个BindingAwareModelMap对象,可以查看他的继承和实现发现,BindingAwareModelMap 是Model 也是Map。

二、Model参数解析 

从HandlerMethodArgumentResolverComposite类中的方法resolveArgument里面的代码

resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);

这里是开始解析参数的地方,从这里进入会发现,和map的解析是一模一样的。也是获取到一个BindingAwareModelMap对象。而且和前一个map用的还是同一个对象。

 

 三、map参数和model参数会被放到请求域当中

一、处理返回值

刚开始BindingAwareModelMap对象是空的,等到执行完接口后,接口里面会进行赋值,这个对象就有数据了。目标方法执行完,会将所有的数据都放在 ModelAndViewContainer;包含要去的页面地址View。还包含Model数据

	
	// 处理请求接口以及处理接口返回数据
  public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
        // 处理接口
		Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs);
        this.setResponseStatus(webRequest);
        if (returnValue == null) {
            if (this.isRequestNotModified(webRequest) || this.getResponseStatus() != null || mavContainer.isRequestHandled()) {
                this.disableContentCachingIfNecessary(webRequest);
                mavContainer.setRequestHandled(true);
                return;
            }
        } else if (StringUtils.hasText(this.getResponseStatusReason())) {
            mavContainer.setRequestHandled(true);
            return;
        }

        mavContainer.setRequestHandled(false);
        Assert.state(this.returnValueHandlers != null, "No return value handlers");

        try {
		// 处理返回结果,mavContainer也被作为参数传入进去了
            this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest);
        } catch (Exception var6) {
            if (logger.isTraceEnabled()) {
                logger.trace(this.formatErrorForReturnValue(returnValue), var6);
            }

            throw var6;
        }
    }
	
	
	
	
	
	// 处理返回值
    public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
        //找到返回值处理器,这里之后在返回值部分细细研究 
		HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);
        if (handler == null) {
            throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
        } else {
			//这里是处理返回值的具体逻辑
            handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
        }
    }
	
	
	
		// 具体处理返回值逻辑
	    public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
       // 如果返回值是字符串会进入到这里
		if (returnValue instanceof CharSequence) {
            String viewName = returnValue.toString();
			// 将返回值保存到ModelAndViewContainer对象中,view属性一般就是地址,model也就是数据,ModelAndView就是携带数据到达指定的地址当中
            mavContainer.setViewName(viewName);
            if (this.isRedirectViewName(viewName)) {
                mavContainer.setRedirectModelScenario(true);
            }
        } else if (returnValue != null) {
            throw new UnsupportedOperationException("Unexpected return type: " + returnType.getParameterType().getName() + " in method: " + returnType.getMethod());
        }

    }

二、将map、model数据设置到请求域中

 下面是上图中invokeHandlerMethod方法中

invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);

这段代码涉及到的源码

	
	// 处理请求接口以及处理接口返回数据
  public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
        // 处理接口
		Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs);
        this.setResponseStatus(webRequest);
        if (returnValue == null) {
            if (this.isRequestNotModified(webRequest) || this.getResponseStatus() != null || mavContainer.isRequestHandled()) {
                this.disableContentCachingIfNecessary(webRequest);
                mavContainer.setRequestHandled(true);
                return;
            }
        } else if (StringUtils.hasText(this.getResponseStatusReason())) {
            mavContainer.setRequestHandled(true);
            return;
        }

        mavContainer.setRequestHandled(false);
        Assert.state(this.returnValueHandlers != null, "No return value handlers");

        try {
		// 处理返回结果,mavContainer也被作为参数传入进去了
            this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest);
        } catch (Exception var6) {
            if (logger.isTraceEnabled()) {
                logger.trace(this.formatErrorForReturnValue(returnValue), var6);
            }

            throw var6;
        }
    }
	
	
	
	
	
	// 处理返回值
    public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
        //找到返回值处理器,这里之后在返回值部分细细研究 
		HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);
        if (handler == null) {
            throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
        } else {
			//这里是处理返回值的具体逻辑
            handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
        }
    }
	
	
	
		// 具体处理返回值逻辑
	    public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
       // 如果返回值是字符串会进入到这里
		if (returnValue instanceof CharSequence) {
            String viewName = returnValue.toString();
			// 将返回值保存到ModelAndViewContainer对象中,view属性一般就是地址,model也就是数据,ModelAndView就是携带数据到达指定的地址当中
            mavContainer.setViewName(viewName);
            if (this.isRedirectViewName(viewName)) {
                mavContainer.setRedirectModelScenario(true);
            }
        } else if (returnValue != null) {
            throw new UnsupportedOperationException("Unexpected return type: " + returnType.getParameterType().getName() + " in method: " + returnType.getMethod());
        }

    }

下面是上图中invokeHandlerMethod方法中

var15 = this.getModelAndView(mavContainer, modelFactory, webRequest);

涉及到的源码

 
	获取ModelAndView对象
 @Nullable
    private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
		// 这里会更新model主要逻辑在自定义参数对象这块再研究
	   modelFactory.updateModel(webRequest, mavContainer);
        if (mavContainer.isRequestHandled()) {
            return null;
        } else {
		
            ModelMap model = mavContainer.getModel();
			// 获取modelMap中的对象,并保存到ModelAndView中
            ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
            if (!mavContainer.isViewReference()) {
                mav.setView((View)mavContainer.getView());
            }

			// 处理重定向数据
            if (model instanceof RedirectAttributes) {
                Map<String, ?> flashAttributes = ((RedirectAttributes)model).getFlashAttributes();
                HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest(HttpServletRequest.class);
                if (request != null) {
				// 将请求数据放到请求上下文当中
                    RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
                }
            }

            return mav;
        }
    }

 以上使用处理器适配器调用具体handler就处理完了,让然后会返回一个ModelAndView对象。之后回到DispatcherServlet类中的doDispatch方法当中。这个时候需要关注这个方法里面

this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);

这块代码片段,主要是处理派发结果,这里就会往请求域中设置数据。

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {
		// 这部分是处理异常的
		boolean errorView = false;
        if (exception != null) {
            if (exception instanceof ModelAndViewDefiningException) {
                this.logger.debug("ModelAndViewDefiningException encountered", exception);
                mv = ((ModelAndViewDefiningException)exception).getModelAndView();
            } else {
                Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;
                mv = this.processHandlerException(request, response, handler, exception);
                errorView = mv != null;
            }
        }
		
		// ModelAndView不为空时,且没有被清理
        if (mv != null && !mv.wasCleared()) {
			// 这里是去渲染页面的
            this.render(mv, request, response);
            if (errorView) {
                WebUtils.clearErrorRequestAttributes(request);
            }
        } else if (this.logger.isTraceEnabled()) {
            this.logger.trace("No view rendering, null ModelAndView returned.");
        }

        if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
            }

        }
    }
	
	
	
	
	
	// 开始去渲染页面
	protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Locale locale = this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale();
        response.setLocale(locale);
		// 获取视图名
        String viewName = mv.getViewName();
        View view;
		// 开始解析视图
        if (viewName != null) {
            view = this.resolveViewName(viewName, mv.getModelInternal(), locale, request);
            if (view == null) {
                throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + this.getServletName() + "'");
            }
        } else {
            view = mv.getView();
            if (view == null) {
                throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a View object in servlet with name '" + this.getServletName() + "'");
            }
        }

        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Rendering view [" + view + "] ");
        }

        try {
            if (mv.getStatus() != null) {
                response.setStatus(mv.getStatus().value());
            }
			// 上面代码拿到了视图,这里就开始去渲染了
            view.render(mv.getModelInternal(), request, response);
        } catch (Exception var8) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Error rendering view [" + view + "]", var8);
            }

            throw var8;
        }
    }







	// 开始进行视图解析
    @Nullable
    protected View resolveViewName(String viewName, @Nullable Map<String, Object> model, Locale locale, HttpServletRequest request) throws Exception {
        if (this.viewResolvers != null) {
            Iterator var5 = this.viewResolvers.iterator();

            while(var5.hasNext()) {
                ViewResolver viewResolver = (ViewResolver)var5.next();
                View view = viewResolver.resolveViewName(viewName, locale);
                if (view != null) {
                    return view;
                }
            }
        }

        return null;
    }
	
	
	
	
	
	    @Nullable
    public View resolveViewName(String viewName, Locale locale) throws Exception {
		// 拿到请求域中的所有数据,和ModelAndView中的model数据(也就是接口中设置的数据)无关
        RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
        Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes");
        List<MediaType> requestedMediaTypes = this.getMediaTypes(((ServletRequestAttributes)attrs).getRequest());
        if (requestedMediaTypes != null) {
            List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes);
			// 拿到视图名,然后返回
			View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs);
            if (bestView != null) {
                return bestView;
            }
        }

        String mediaTypeInfo = this.logger.isDebugEnabled() && requestedMediaTypes != null ? " given " + requestedMediaTypes.toString() : "";
        if (this.useNotAcceptableStatusCode) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Using 406 NOT_ACCEPTABLE" + mediaTypeInfo);
            }

            return NOT_ACCEPTABLE_VIEW;
        } else {
            this.logger.debug("View remains unresolved" + mediaTypeInfo);
            return null;
        }
    }
	
	
	
	
	
	
	// 这里是开始渲染数据的部分
	    public void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("View " + this.formatViewName() + ", model " + (model != null ? model : Collections.emptyMap()) + (this.staticAttributes.isEmpty() ? "" : ", static attributes " + this.staticAttributes));
        }

       // 这里是创建合并数据HashMap对象,其实就是将model中个数据放到这个map当中
        Map<String, Object> mergedModel = this.createMergedOutputModel(model, request, response);
		// 准备响应
        this.prepareResponse(request, response);
		// 渲染合并输出的数据,就是在这里放到了请求域中
	   this.renderMergedOutputModel(mergedModel, this.getRequestToExpose(request), response);
    }
	
	
	
	
	
		// 渲染合并输出的数据,就是在这里放到了请求域中
	protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 就是在这行代码里将值设置到请求域当中
		this.exposeModelAsRequestAttributes(model, request);
        this.exposeHelpers(request);
        String dispatcherPath = this.prepareForRendering(request, response);
        RequestDispatcher rd = this.getRequestDispatcher(request, dispatcherPath);
        if (rd == null) {
            throw new ServletException("Could not get RequestDispatcher for [" + this.getUrl() + "]: Check that the corresponding file exists within your web application archive!");
        } else {
            if (this.useInclude(request, response)) {
                response.setContentType(this.getContentType());
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Including [" + this.getUrl() + "]");
                }

                rd.include(request, response);
            } else {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Forwarding to [" + this.getUrl() + "]");
                }

                rd.forward(request, response);
            }

        }
    }
	
	
	
	
		// 设置数据到请求域当中,其实就是循环遍历了合并数据后的Map集合,将里面的值设置到请求域中
	    protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception {
        model.forEach((name, value) -> {
            if (value != null) {
                request.setAttribute(name, value);
            } else {
                request.removeAttribute(name);
            }

        });
    }

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

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

相关文章

基于springboot vue 电影推荐系统

博主介绍&#xff1a;专注于Java&#xff08;springboot ssm 等开发框架&#xff09; vue .net php python(flask Django) 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找…

DatePicker 日期控件

效果&#xff1a; 要求&#xff1a;初始显示系统当前时间&#xff0c;点击日期控件后修改文本控件时间。 目录结构&#xff1a; activity_main.xml(布局文件)代码&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:and…

环境可靠性

一、基础知识 1.1 可靠性定义 可靠性是指产品在规定的条件下、在规定的时间内完成规定的功能的能力。 可靠性的三大要素&#xff1a;耐久性、可维修性、设计可靠性 耐久性&#xff1a;指的是产品能够持续使用而不会故障的特性&#xff0c;或者说是产品的使用寿命。 可维修性&a…

1.MySQL存储过程基础(1/10)

引言 数据库管理系统&#xff08;Database Management System, DBMS&#xff09;是现代信息技术中不可或缺的一部分。它提供了一种系统化的方法来创建、检索、更新和管理数据。DBMS的重要性体现在以下几个方面&#xff1a; 数据组织&#xff1a;DBMS 允许数据以结构化的方式存…

【C++ STL】手撕vector,深入理解vector的底层

vector的模拟实现 前言一.默认成员函数1.1常用的构造函数1.1.1默认构造函数1.1.2 n个 val值的构造函数1.1.3 迭代器区间构造1.1.4 initializer_list 的构造 1.2析构函数1.3拷贝构造函数1.4赋值运算符重载 二.元素的插入,删除,查找操作2.1 operator[]重载函数2.2 push_back函数:…

读论文、学习时 零碎知识点记录01

1.入侵检测技术 2.深度学习、机器学习相关的概念 ❶注意力机制 ❷池化 ❸全连接层 ❹Dropout层 ❺全局平均池化 3.神经网络中常见的层

51c视觉~CV~合集3

我自己的原文哦~ https://blog.51cto.com/whaosoft/11668984 一、 CV确定对象的方向 介绍如何使用OpenCV确定对象的方向(即旋转角度&#xff0c;以度为单位)。 先决条件 安装Python3.7或者更高版本。可以参考下文链接&#xff1a; https://automaticaddison.com/how-to-s…

【2024年最新】基于springboot+vue的毕业生信息招聘平台lw+ppt

作者&#xff1a;计算机搬砖家 开发技术&#xff1a;SpringBoot、php、Python、小程序、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;Java精选实战项…

基于keras的停车场车位识别

1. 项目简介 该项目旨在利用深度学习模型与计算机视觉技术&#xff0c;对停车场中的车位进行检测和状态分类&#xff0c;从而实现智能停车管理系统的功能。随着城市化的发展&#xff0c;停车场管理面临着车位检测效率低、停车资源分配不均等问题&#xff0c;而传统的人工检测方…

【Python】Dejavu:Python 音频指纹识别库详解

Dejavu 是一个基于 Python 实现的开源音频指纹识别库&#xff0c;主要用于音频文件的识别和匹配。它通过生成音频文件的唯一“指纹”并将其存储在数据库中&#xff0c;来实现音频的快速匹配。Dejavu 的主要应用场景包括识别音乐、歌曲匹配、版权管理等。 ⭕️宇宙起点 &#x1…

【AI知识点】泊松分布(Poisson Distribution)

泊松分布&#xff08;Poisson Distribution&#xff09; 是统计学和概率论中的一种离散概率分布&#xff0c;通常用于描述在固定时间或空间内&#xff0c;某个事件发生的次数。该分布适用于稀有事件的建模&#xff0c;特别是当事件发生是独立的、随机的&#xff0c;且发生的平均…

[Go语言快速上手]初识Go语言

目录 一、什么是Go语言 二、第一段Go程序 1、Go语言结构 注意 2、Go基础语法 关键字 运算符优先级 三、Go语言数据类型 示例 小结 一、什么是Go语言 Go语言&#xff0c;通常被称为Golang&#xff0c;是一种静态类型、编译型的计算机编程语言。它由Google的Robert Gr…

关闭IDM自动更新

关闭IDM自动更新 1 打开注册表2 找到IDM注册表路径 1 打开注册表 winR regedit 2 找到IDM注册表路径 计算机\HKEY_CURRENT_USER\Software\DownloadManager 双击LstCheck&#xff0c;把数值数据改为0 完成 感谢阅读

存储电话号码的数据类型,用 int 还是用 string?

在 Java 编程中&#xff0c;存储电话号码的选择可以通过两种常见方式进行&#xff1a;使用 int 类型或 String 类型。这种选择看似简单&#xff0c;但实际上涉及到 JVM 内部的字节码实现、内存优化、数据表示、以及潜在的可扩展性问题。 Java 基本数据类型与引用数据类型的差异…

Windows安全加固详解

一、补丁管理 使用适当的命令或工具&#xff0c;检查系统中是否有未安装的更新补丁。 Systeminfo 尝试手动安装一个系统更新补丁。 • 下载适当的补丁文件。 • 打开命令提示符或PowerShell&#xff0c;并运行 wusa.exe <patch_file_name>.msu。 二、账号管…

使用seata管理分布式事务

做应用开发时&#xff0c;要保证数据的一致性我们要对方法添加事务管理&#xff0c;最简单的处理方案是在方法上添加 Transactional 注解或者通过编程方式管理事务。但这种方案只适用于单数据源的关系型数据库&#xff0c;如果项目配置了多个数据源或者多个微服务的rpc调用&…

thinkphp 学习记录

1、PHP配置 &#xff08;点开链接后&#xff0c;往下拉&#xff0c;找到PHP8.2.2版本&#xff0c;下载的是ZIP格式&#xff0c;解压即用&#xff09; PHP For Windows: Binaries and sources Releases &#xff08;这里是下载地址&#xff09; 我解压的地址是&#xff1a;D:\…

Spring中Bean创建过程中各个阶段的作用

文章目录 Instantiate&#xff08;实例化&#xff09;Populate properties&#xff08;填充属性&#xff09;BeanNameAwares setBeanName()BeanFactoryAwares setBeanFactory()ApplicationContextAwares setApplicationContext()Pre-initialization BeanPostProcessorsInitiali…

【Python篇】从零到精通:全面分析Scikit-Learn在机器学习中的绝妙应用

文章目录 从零到精通&#xff1a;全面揭秘Scikit-Learn在机器学习中的绝妙应用前言第一部分&#xff1a;深入了解Scikit-Learn的基础知识1. 什么是Scikit-Learn&#xff1f;2. 安装Scikit-Learn3. Scikit-Learn中的基本构件4. 数据集的加载与探索5. 数据预处理标准化数据 6. 构…

【Kubernetes】常见面试题汇总(五十五)

目录 121. POD 创建失败&#xff1f; 122. POD 的 ready 状态未进入&#xff1f; 特别说明&#xff1a; 题目 1-68 属于【Kubernetes】的常规概念题&#xff0c;即 “ 汇总&#xff08;一&#xff09;~&#xff08;二十二&#xff09;” 。 题目 69-113 属于【Kube…