【金三银四系列】Spring面试题-下(2023版)

news2025/7/27 4:33:22

Spring面试专题

1.介绍下Spring的初始化过程

  Spring的初始化过程中会走refresh方法,这是个模板模式的实现,包含有如下的14个方法

image.png

每个方法的相关作用

image.png

把每个方法的作用按照这个图介绍下就可以了

2.配置文件的加载解析

  Spring初始化的时候在obtainFreshBeanFactory方法中完成了配置文件的加载解析,并把解析的bean标签信息封装到了BeanDefinition对象中,所有的解析的BeanDefinition对象都存储在了DefaultListableBeanFactory对象的beanDefinitionMap的Map集合中。

3.介绍下Spring中常用的注解

  @Controller,@Service,@Repository 这些日常开发中常用的注解没啥挑战,@Import注解会让面试官眼前一亮。

@Import注解本身的由来是在Spring3.0的时候由xml文件的方式向注解编程的发展,替换以前在配置文件中的/<import>标签 ,也就是可以导入其他的配置类,然后@Import注解还扩展了对应的功能

静态注入:可以直接把对应的类型注入到容器中:@Import(User.class)

动态注入:可以实现ImportSelector接口和ImportBeanDefinitionRegistrar接口,然后通过重写对应的方法来实现动态的注入

当然在ImportSelector接口的实现还可以触发延迟加载的逻辑。DeferredImportSelector,这块在SpringBoot的自动装配中就应用到了

4.SpringBoot 的自动装配原理

  

image.png

5.介绍下SpringBoot的启动流程

SpringBoot.png

6.SpringBoot中有了属性文件为什么还要加一个bootstrap.yml文件?

  在单体的SpringBoot项目中其实我们是用不到bootstrap.yml文件的,bootsrap.yml文件的使用需要SpringCloud的支持,因为在微服务环境下我们都是有配置中心的,来统一的管理系统的相关配置属性,那么怎么去加载配置中心的内容呢?一个SpringBoot项目启动的时候默认只会加载对应的application.yml中的相关信息,这时bootstrap.yml的作用就体现出来了,会在SpringBoot正常启动前创建一个父容器来通过bootstrap.yml中的配置来加载配置中心的内容。

7.如果要对属性文件中的账号密码加密如何实现?

  其实这是一个比较篇实战的一个问题,我们在application.yml中保存的MySQL数据库的账号密码或者其他服务的账号密码,都可以保存加密后的内容,那么我们在处理的时候要怎么解密呢?这个其实比较简单只需要对SpringBoot的执行流程清楚就可以了,第一个我们可以通过自定义监听器可以在加载解析了配置文件之后对加密的文件中做解密处理同时覆盖之前加密的内容,或者通过对应的后置处理器来处理,具体的实现如下:

在这里插入图片描述

然后我们通过案例代码来演示下,加深大家的理解
首先我们在属性文件中配置加密后的信息

spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mb?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
# 对通过3DES对密码加密
spring.datasource.password=t5Jd2CzFWEw=

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

mybatis.mapper-locations=classpath:mapper/*.xml

  在SpringBoot项目启动的时候在在刷新Spring容器之前执行的,所以我们要做的就是在加载完环境配置信息后,获取到配置的 spring.datasource.password=t5Jd2CzFWEw= 这个信息,然后解密并修改覆盖就可以了。
在这里插入图片描述  然后在属性文件的逻辑其实是通过发布事件触发对应的监听器来实现的
在这里插入图片描述
  所以第一个解决方案就是你自定义一个监听器,这个监听器在加载属性文件(ConfigFileApplicationListener)的监听器之后处理,这种方式稍微麻烦点,
  还有一种方式就是通过加载属性文件的一个后置处理器来处理,这就以个为例来实现

3DES的工具类

/**
 * 3DES加密算法,主要用于加密用户id,身份证号等敏感信息,防止破解
 */
public class DESedeUtil {

    //秘钥
    public static final String  KEY = "~@#$y1a2n.&@+n@$%*(1)";
    //秘钥长度
    private static final int secretKeyLength = 24;
    //加密算法
    private static final String  ALGORITHM = "DESede";
    //编码
    private static final String CHARSET = "UTF-8";

    /**
     * 转换成十六进制字符串
     * @param key
     * @return
     */
    public static byte[] getHex(String key){
        byte[] secretKeyByte = new byte[24];
        try {
            byte[] hexByte;
            hexByte = new String(DigestUtils.md5Hex(key)).getBytes(CHARSET);
            //秘钥长度固定为24位
            System.arraycopy(hexByte,0,secretKeyByte,0,secretKeyLength);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return secretKeyByte;
    }

    /**
     * 生成密钥,返回加密串
     * @param key 密钥
     * @param encodeStr 将加密的字符串
     * @return
     */
    public static String  encode3DES(String key,String encodeStr){
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(getHex(key), ALGORITHM));
            return Base64.encodeBase64String(cipher.doFinal(encodeStr.getBytes(CHARSET)));
        }catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 生成密钥,解密,并返回字符串
     * @param key 密钥
     * @param decodeStr 需要解密的字符串
     * @return
     */
    public static String decode3DES(String key, String decodeStr){
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(getHex(key),ALGORITHM));
            return new String(cipher.doFinal(new Base64().decode(decodeStr)),CHARSET);
        } catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }


    public static void main(String[] args) {
        String userId = "123456";
        String encode = DESedeUtil.encode3DES(KEY, userId);
        String decode = DESedeUtil.decode3DES(KEY, encode);
        System.out.println("用户id>>>"+userId);
        System.out.println("用户id加密>>>"+encode);
        System.out.println("用户id解密>>>"+decode);
    }

}

声明后置处理器

public class SafetyEncryptProcessor implements EnvironmentPostProcessor {
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        for (PropertySource<?> propertySource : environment.getPropertySources()) {
            System.out.println("propertySource = " + propertySource);
            if(propertySource instanceof OriginTrackedMapPropertySource){
                OriginTrackedMapPropertySource source = (OriginTrackedMapPropertySource) propertySource;
                for (String propertyName : source.getPropertyNames()) {
                    //System.out.println(propertyName + "=" + source.getProperty(propertyName));
                    if("spring.datasource.password".equals(propertyName)){
                        Map<String,Object> map = new HashMap<>();
                        // 做解密处理
                        String property = (String) source.getProperty(propertyName);
                        String s = DESedeUtil.decode3DES(DESedeUtil.KEY, property);
                        System.out.println("密文:" + property);
                        System.out.println("解密后的:" + s);
                        map.put(propertyName,s);

                        // 注意要添加到前面,覆盖
                        environment.getPropertySources().addFirst(new MapPropertySource(propertyName,map));
                    }
                }
            }
        }
    }
}

然后在META-INF/spring.factories文件中注册

org.springframework.boot.env.EnvironmentPostProcessor=com.bobo.util.SafetyEncryptProcessor

然后启动项目就可以了
在这里插入图片描述

  搞定

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

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

相关文章

内存管理框架---页(一)

文章目录物理内存的模型非一致内存访问--NUMA一致内存访问模型--UMA内存管理架构页页框管理页描述符页描述符字段flags字段详解gfp_mask 标志获得页alloc_pages__get_free_pages获得填充为0的页释放页kmallocvmalloc参考资料你用心写的每一篇文章&#xff0c;可能会带别人和自己…

【华为OD机试模拟题】用 C++ 实现 - 选座位(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 分积木(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 吃火锅(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - RSA 加密算法(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 构成的正方形数量(2023.Q1) 【华为OD机试模拟…

特征向量中心度(eigenvector centrality)算法原理与源码解析

前言 随着图谱应用的普及&#xff0c;图深度学习技术也逐渐被越来越多的数据挖掘团队所青睐。传统机器学习主要是对独立同分布个体的统计学习&#xff0c;而图深度学习则是在此基础上扩展到了非欧式空间的图数据之上&#xff0c;通过借鉴NLP和CV方向的模型思想&#xff0c;衍生…

供应商关系有哪些类型?如何优化管理?

供应商关系有两种主要类型。识别你与供应商的关系类型将有助于你有效地管理期望和调整目标。 1、垂直供应商关系 在垂直供应商关系中&#xff0c;供应链以卖方和买方之间的传统方式联系起来。各方都把重点放在确保个人和供应链目标的实现上。垂直供应商关系的例子包括分销商…

JVM面试总结

文章目录栈帧中存放的信息&#xff1a;对象的创建过程对象的内存布局&#xff1f;对象的访问定位方式&#xff1f;如何判断对象已死&#xff1f;可以作为GC Root的点&#xff1a;谈一下引用对象再被回收时如何逃脱&#xff1f;回收方法区如何判断常量是否废弃&#xff1f;垃圾回…

IMX Yocto SDK 拉取报错误fatal: Could not read from remote repository

IMX 平台Yocto SDK拉取步骤拉取步骤可以在NXP官方yocto指导文档里查看&#xff0c;这里再贴一次&#xff0c;然后针对的讲可能遇到的问题。1&#xff0c;首先下载repo。repo是谷歌开发的一款python小程序。是基于GIT工作的&#xff0c;可以批量拉取&#xff0c;合并多个代码仓库…

Springboot 使用thymeleaf 服务器无法加载resources中的静态资源异常处理

目录一、异常错误二、原因三、解决方法方法1. 将无法编译的静态资源放入可编译目录下方法2. 重新编译项目加载资源方法3. 修改pom.xml资源配置文件方法4. 不连接远程数据库启动&#xff0c;使用本地数据库一、异常错误 Springboot使用thymeleaf&#xff0c;并连接远程数据库启…

Vue3电商项目实战-商品详情模块5【14-商品详情-数量选择组件、15-商品详情-按钮组件、16-商品详情-同类推荐组件】

文章目录14-商品详情-数量选择组件15-商品详情-按钮组件16-商品详情-同类推荐组件14-商品详情-数量选择组件 目的&#xff1a;封装一个通用的数量选中组件。 大致功能分析&#xff1a; 默认值为1可限制最大最小值点击-就是减1 点击就是加1需要完成v-model得实现存在无label情况…

如何构建以应用为核心的运维体系

在微服务的架构模式下&#xff0c;我们的运维视角一定转到应用这个核心概念上来&#xff0c;一切要从应用的角度来分析和看待问题。 微服务架构一般都是从单体架构或分层架构演进过来的。软件架构服务化的过程&#xff0c;就是我们根据业务模型进行细化的过程&#xff0c;在这…

并发编程学习篇并发线程池底层原理详解与源码分析

一、线程池与线程对比 package bat.ke.qq.com.threadpool;import java.util.ArrayList; import java.util.List; import java.util.Random;/**** 使用线程的方式去执行程序*/ public class ThreadTest {public static void main(String[] args) throws InterruptedException {…

为Webpack5项目引入Buffer Polyfill

前言 最近在公司的一个项目中使用到了Webpack5&#xff0c; 然而在使用某个npm包的时候&#xff0c;出现了Buffer is not defined 这个问题&#xff0c;原因很明显了&#xff0c;因为浏览器运行时没有Buffer这个API&#xff0c;所以需要为浏览器引入Buffer Polyfill. Webpack5…

如何制定达人营销策略

如今&#xff0c;达人营销不再是一个新兴趋势&#xff0c;而是公司整个数字营销战略的一部分。虽然十年前&#xff0c;达人还不存在&#xff0c;但随着公司对数字化营销依赖度地提升&#xff0c;各个领域的大V群体逐渐壮大&#xff0c;越来越多的公司已经采用了达人营销策略。如…

JavaScript 库

文章目录JavaScript 库JavaScript 框架&#xff08;库&#xff09;jQueryPrototypeMooTools其他框架CDN -内容分发网络引用 jQuery使用框架JavaScript 库 JavaScript 库 - jQuery、Prototype、MooTools。 JavaScript 框架&#xff08;库&#xff09; JavaScript 高级程序设计…

界面控件DevExtreme的Data Grid组件——让业务信息管理更轻松!

DevExtreme拥有高性能的HTML5 / JavaScript小部件集合&#xff0c;使您可以利用现代Web开发堆栈&#xff08;包括React&#xff0c;Angular&#xff0c;ASP.NET Core&#xff0c;jQuery&#xff0c;Knockout等&#xff09;构建交互式的Web应用程序&#xff0c;该套件附带功能齐…

【阿旭机器学习实战】【35】员工离职率预测---决策树与随机森林预测

【阿旭机器学习实战】系列文章主要介绍机器学习的各种算法模型及其实战案例&#xff0c;欢迎点赞&#xff0c;关注共同学习交流。 本文的主要任务是通过决策树与随机森林模型预测一个员工离职的可能性并帮助人事部门理解员工为何离职。 目录1.获取数据2.数据预处理3.分析数据3.…

Python之正则表达式细讲

文章目录前言一、行定位符二、元字符三、限定符四、字符类五、排除字符六、选择字符七、转义字符八、分组九、正则表达式语法总结前言 在处理字符串时&#xff0c;经常会有查找符合某些复杂规则的字符串的需求。比如用爬虫批量抓取某网站图片&#xff0c;要从抓下来的网页信息中…

【AI写作】 机器人流程自动化 介绍 - Robotic Process Automation (RPA) Introduction

写一篇文章介绍RPA技术,未来的发展。使用markdown格式,有3级索引,超过3000字。 某位大师说过的: 任何行业、任何部门都有大量的场景,涉及重复、有规则逻辑的工作,都可以用 RPA 开发一个软件机器人帮助完成。 文章目录 机器人过程自动化(RPA)简介RPA的定义RPA的好处Robo…

国内“谁”能实现chatgpt,短期穷出的类ChatGPT简评(算法侧角度为主),以及对MOSS、ChatYuan给出简评,一文带你深入了解宏观技术路线。

1.ChatGPT简介【核心技术、技术局限】 ChatGPT&#xff08;全名&#xff1a;Chat Generative Pre-trained Transformer&#xff09;&#xff0c;美国OpenAI 研发的聊天机器人程序 &#xff0c;于2022年11月30日发布 。ChatGPT是人工智能技术驱动的自然语言处理工具&#xff0c…

这周末,StarRocks 邀请开发者们一起来上海 GAIDC 开源集市,各种任务等你来挑战!

2 月 25 日-26 日 &#xff08;本周末&#xff09;2023 全球人工智能开发者先锋大会&#xff08;GAIDC&#xff09;将于上海临港中心举行&#xff01;StarRocks 社区受邀参与开源集市&#xff0c;展示开源魅力、分享社区成果。欢迎上海的同学们到“摊位”上与工作人员互动&…

经典设计模式MVC理解

MVC是模型(Model)、视图(View)、控制器(Controller)的简写&#xff0c;将业务逻辑、数据、显示分离的方法来组织代码。今天简单回顾一下。 mvc释义理解 M代表模型(Model)&#xff0c;表示业务规则封装。在MVC的三个部件中&#xff0c;模型拥有最多的处理任务。被模型返回的数据…