【Java面试题】《尚硅谷经典Java面试题第一季(java面试精讲)》学习笔记

2023-12-12 15:30

本文主要是介绍【Java面试题】《尚硅谷经典Java面试题第一季(java面试精讲)》学习笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 尚硅谷经典Java面试题第一季(java面试精讲)
      • 01_尚硅谷_JavaSE面试题:自增变量
        • 题目
        • 解释:
        • 总结:
      • 02_尚硅谷_JavaSE面试题:单例设计模式
        • 概述
        • 饿汉式
        • 懒汉式
      • 03_尚硅谷_JavaSE面试题:类初始化和实例初始化等
        • 题目
        • 类初始过程与实例初始化过程
        • 方法的重写 Override
        • Overload与Override
      • 04_尚硅谷_JavaSE面试题:方法的参数传递机制
        • 题目:
        • 解释:
        • 方法的参数传递机制
      • 05_尚硅谷_JavaSE面试题:递归与迭代
        • 题目
        • 分析:
        • 代码实现:
        • 小结
      • 06_尚硅谷_JavaSE面试题:成员变量与局部变量
        • 问题:
        • 局部变量与成员变量的区别
        • 堆、栈、方法区
      • 07_尚硅谷_SSM面试题_Spring Bean的作用域之间有什么区别
        • singleton与prototype
        • 总结
      • 08_尚硅谷_SSM面试题_Spring支持的常用数据库事务传播属性和...
        • 事务传播行为
        • 数据库事务并发问题
        • 隔离级别
      • 09_尚硅谷_SSM面试题_SpringMVC中如何解决POST请求中文乱码问...
        • 解决post中文乱码:
        • 解决get中文乱码
      • 10_尚硅谷_SSM面试题_简单的谈一下SpringMVC的工作流程
        • 流程图
        • doDispatch方法源码
        • 流程描述
      • 11_尚硅谷_SSM面试题_MyBatis中当实体类中的属性名和表中的字段不一致
        • 方式1:改sql
        • 方式2:启动驼峰名法
        • 方式3:resultMap
      • 12_尚硅谷_Java高级_Linux常用服务类相关命令
        • centos 6
        • centos 7
      • 13_尚硅谷_Java高级_git分支相关命令
        • 基本命令
        • Git工作流
      • 14_尚硅谷_Java高级_redis持久化
        • RDB优缺点
        • AOF优缺点
      • 15_尚硅谷_Java高级_Mysql什么时候建索引
      • 16_尚硅谷_Java高级_JVM垃圾回收机制
        • 发生时期
        • GC算法
          • 1. 引用计数算法:(不能处理循环引用,基本被淘汰了)
          • 2. 复制算法:年轻代使用的是Minor GC,这种gc算法采用的是复制算法
          • 3. 标记清除:老年代一般是由标记清除或者是标记清除与标记整理混合实现
          • 4. 标记压缩:老年代一般是由标记清除或者是标记清除与标记整理混合实现
          • 5. 标记清除压缩
      • 17_尚硅谷_项目面试题_redis 在项目中的使用场景
        • redis 数据类型元使用场景
      • 18_尚硅谷_项目面试题_es与solr的区别
        • es与solr的区别
      • 19_尚硅谷_项目面试题_单点登录
        • 流程图:
      • 20_尚硅谷_项目面试题_购物车
        • 购物车
      • 21_尚硅谷_项目面试题_消息队列
        • 处理高并发
        • 电商项目使用场景

尚硅谷经典Java面试题第一季(java面试精讲)

视频地址:https://www.bilibili.com/video/BV1Eb411P7bP

01_尚硅谷_JavaSE面试题:自增变量

题目

代码:问输出的 i、j、k 的值

        int i = 1;i = i++;int j = i++;int k = i + ++i * i++;System.out.println("i = " + i);System.out.println("j = " + j);System.out.println("k = " + k);

运行结果:
在这里插入图片描述

解释:

在这里插入图片描述
关于int k = i + ++i * i++;我认为是:int k =(i++) + i * i++;,例如,不妨把中间的i换成j,再看一下字节码文件:
在这里插入图片描述
是给第一个变量i++了,而不是++j


总结:

在这里插入图片描述

02_尚硅谷_JavaSE面试题:单例设计模式

概述

singleton 单例:一个系统中只有一个实例对象可以被获取和使用,例如,jvm运行环境的Runtime类:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

饿汉式

饿,急于创建,在类初始化就创建了

public class SingletonHungry {public static void main(String[] args) {System.out.println(SH01.INSTANCE);System.out.println(SH02.INSTANCE);System.out.println(SH03.INSTANCE);}
}/*** 方式1:直接实例化*/
class SH01{/*** 使用final强调这是一个单例*/public static final SH01 INSTANCE = new SH01();private SH01(){ }
}/*** 方式2:使用枚举类*/
enum SH02{/*** 只有一个可用的变量,达到单例的效果*/INSTANCE;
}/*** 方式3:静态代码块*/
class SH03{public static final SH03 INSTANCE;String name;static {// 例如,要从配置文件获取值String config = null;try {Properties properties = new Properties();properties.load(SH03.class.getClassLoader().getResourceAsStream("application.properties"));config = properties.getProperty("spring.application.name");} catch (IOException e) {e.printStackTrace();}//创建对象INSTANCE = new SH03(config);}private SH03(String name){this.name = name;}
}
懒汉式
public class SingletonLazy {public static void main(String[] args)  {//方式1在多线程的情况下是不安全的:Runnable runnable = () -> System.out.println(SL01.getInstance());new Thread(runnable).start();new Thread(runnable).start();//方式2在多线程的情况下是安全的:runnable = () -> System.out.println(SL02.getInstance());new Thread(runnable).start();new Thread(runnable).start();//方式3System.out.println(SL03.getInstance());System.out.println(SL03.getInstance());}
}/*** 方式1:线程不安全版*/
class SL01{/*** 静态变量私有化,防止直接用类名获取到null*/private static SL01 instance;private SL01(){}public static SL01 getInstance(){if (instance == null){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}instance = new SL01();}return instance;}
}/*** 方式2:线程安全版* * 为什么用volatile ?* 		instance = new Singleton(); 这段代码其实是分为三步执行* 		1. 为 instance 分配内存空间* 		2. 初始化 instance* 		3. 将 instance 指向分配的内存地址* 		但是由于 JVM 具有指令重排的特性,会使执行顺序有可能变成 1 3 2,指令重排在单线程环境下不会出现问题,但是在多线程环境下会导致一个线程获得一个还没有初始化的实例。比如线程 T1 执行了 1、3,此时线程 T2 获取 instance 发现不为空,但是 instance 还未被初始化。* 		使用 volatile 可以禁止 JVM 指令重排,保证在多线程环境下也能正常运行。*/
class SL02{/*** 静态变量私有化,防止直接用类名获取到null*/private volatile static SL02 instance;private SL02(){}public static SL02 getInstance(){// 判断是否为null,为null才加锁创建,提升性能if (instance == null){synchronized (SL02.class){// 即使进来了,可能前一个刚好创建好了if (instance == null){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}instance = new SL02();}}}return instance;}
}/*** 方式3:内部类*/
class SL03{/*** 静态变量私有化,防止直接用类名获取到null*/private static SL03 instance;private SL03(){}private static class Inner{// 静态内部类不会自动随着外部类的加载和初始化而初始化,而是要单独的加载和初始化,而且只会被加载一次private static final SL03 INSTANCE = new SL03();}public static SL03 getInstance()  {return Inner.INSTANCE;}
}

部分结果:结果显示,第一种方式在多线程情况下是不安全的,获取到两个实例:
在这里插入图片描述

03_尚硅谷_JavaSE面试题:类初始化和实例初始化等

题目

题目:输出结果是?

class Father {private int i = method();private static int j = staticMethod();static {System.out.print(1 + " ");}Father() {System.out.print(2 + " ");}{System.out.print(3 + " ");}public int method() {System.out.print(4 + " ");return 1;}public static int staticMethod() {System.out.print(5 + " ");return 1;}
}public class Son extends Father {private int i = method();private static int j = staticMethod();static {System.out.print(6 + " ");}Son() {System.out.print(7 + " ");}{System.out.print(8 + " ");}@Overridepublic int method() {System.out.print(9 + " ");return 1;}public static int staticMethod() {System.out.print(10 + " ");return 1;}public static void main(String[] args) {new Son();System.out.println();new Son();}
}

在这里插入图片描述
运行结果:

5 1 10 6 9 3 2 9 8 7 
9 3 2 9 8 7 

分析:

  • 先进行类初始化,也即执行<clinit>()方法,(只会被初始化一次)

    • 如果有父类先对父类进行类初始化
    • 静态代码块、静态变量初始化(谁在前,谁先进行)
  • 再进行实例初始化,也即执行<init>()方法,(每一次创建实例对象都会被执行)

    • 如果有父类,先对父类进行类初始化;如果父类的方法在当前类被重写,则使用被重写后的方法
    • 非静态代码块、非静态变量的初始化(谁在前,谁先进行)
    • 对应构造器方法

类初始过程与实例初始化过程

在这里插入图片描述
在这里插入图片描述


方法的重写 Override

在这里插入图片描述


Overload与Override
  • overload是方法重载

    • 同一个类
    • 方法名相同
    • 方法参数个数、顺序不同
    • 与修饰符、返回值无关
  • override是方法重写,要求以下内容相同:

    • 方法名
    • 形参列表
    • 返回值类型
    • 抛出的异常
    • 修饰符

04_尚硅谷_JavaSE面试题:方法的参数传递机制

题目:

运行结果?

在这里插入图片描述

运行结果:

在这里插入图片描述

解释:
  • int 是基本类型,只传值,因此 i 的值不会变。基本类型包括:byte、char、short、boolean、int、float、long、double八种
  • String传地址,但是String是不可变的,拼接字符串实际指向常量池中新的地址,并且只是change中的局部变量指向新的地址,并不影响main方法中字符串的值
  • Array数组类型传地址,并且把这个地址中的数字改了,因此mian方法中arr的值会变
  • 对象也传地址,把地址中的变量改了

方法的参数传递机制

在这里插入图片描述


05_尚硅谷_JavaSE面试题:递归与迭代

题目

题目:
在这里插入图片描述

分析:

想要跳到第n步台阶,只能是从第n-1或者n-2跳上来的,要求跳到第n机有多少种走法,只需知道跳到第n-1步和n-2步有多少种走法,求和即可。即:

  • f(n) = f(n-1) + f(n-2)
代码实现:
public class P05 {public static void main(String[] args) {int n = 20;//秒表统计运行时间StopWatch watch = new StopWatch();watch.start();int res = method1(n);System.out.println("res1 = " + res);watch.stop();watch.start();res = method2(n);System.out.println("res2 = " + res);watch.stop();//查看运行时间StopWatch.TaskInfo[] taskInfo = watch.getTaskInfo();for (StopWatch.TaskInfo info : taskInfo) {System.out.println(info.getTimeNanos());}}/*** 迭代实现* @param n* @return*/private static int method2(int n) {if (n == 1 || n == 2){return n;}// i1表示跳到n-2的走法,i2表示跳到n-1的走法int i1 = 1, i2 = 2;int tmp;for (int i = 3; i <= n; i++) {//新的i2tmp = i1 + i2;//新的i1i1 = i2;i2 = tmp;}return i2;}/*** 递归实现* @param n* @return*/private static int method1(int n) {if (n == 1 || n == 2){return n;}return method1(n - 1) + method1(n -2);}
}

运行结果:可见递归慢很多,但是它代码简单
在这里插入图片描述

小结

在这里插入图片描述


06_尚硅谷_JavaSE面试题:成员变量与局部变量

问题:
public class P06 {static int s;int i;int j;{int i = 1;i++;j++;s++;}private void test(int j) {i++;j++;s++;}public static void main(String[] args) {P06 problem1 = new P06();P06 problem2 = new P06();problem1.test(100);problem1.test(200);problem2.test(300);System.out.println("i = " + problem1.i + ", j = " + problem1.j + ", s = " + problem1.s);System.out.println("i = " + problem2.i + ", j = " + problem2.j + ", s = " + problem2.s);}
}

结果:
在这里插入图片描述
分析:

  • 去除干扰;下图框选的都是局部变量,影响不到外面的数据,直接忽略
    在这里插入图片描述
  • 对象对静态变量的引用转换为类对对象的引用,提醒我们这是类公有的:
    在这里插入图片描述
  • 实例初始化,每次创建对象都会执行
局部变量与成员变量的区别

在这里插入图片描述

堆、栈、方法区

在这里插入图片描述
在这里插入图片描述


07_尚硅谷_SSM面试题_Spring Bean的作用域之间有什么区别

singleton与prototype

代码:

//简单的创建两类A、B
class A{ }
class B{ }//将A、B两个类加入容器,分别设置为单例和多例
@Configuration
class Config{@Bean@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)public A a(){return new A();}@Bean@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)public B b(){return new B();}
}//多次获取A、B
@SpringBootApplication
public class JavaInterviewQuestionsApplication {public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(JavaInterviewQuestionsApplication.class, args);System.out.println(run.getBean(A.class));System.out.println(run.getBean(A.class));System.out.println(run.getBean(B.class));System.out.println(run.getBean(B.class));}
}

部分结果:观察到A获取两次是一个对象,B获取两次是两个对象
在这里插入图片描述

总结

在这里插入图片描述


08_尚硅谷_SSM面试题_Spring支持的常用数据库事务传播属性和…

事务传播行为

在这里插入图片描述
常用的是前两种

  • REQUIRED:A和B都定义事务,A调用B,则B的事务不生效
  • REQUIRED_NEW:A和B都定义事务,A调用B,B的事务生效

设置示例: @Transactional(propagation = Propagation.REQUIRED)

数据库事务并发问题

在这里插入图片描述

隔离级别

在这里插入图片描述

例如:可设置事务的隔离级别为可重复读,则在它管辖范围内的代码,多次读取相同数据获得的结果是一致的:@Transactional(isolation = Isolation.REPEATABLE_READ)

在这里插入图片描述


09_尚硅谷_SSM面试题_SpringMVC中如何解决POST请求中文乱码问…

解决post中文乱码:

在这里插入图片描述

在这里插入图片描述

解决get中文乱码

在这里插入图片描述

10_尚硅谷_SSM面试题_简单的谈一下SpringMVC的工作流程

流程图

在这里插入图片描述

doDispatch方法源码
  • 从doDispatch方法的角度看执行流程
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {// 1、找controller// 2、找interceptorHandlerExecutionChain mappedHandler = getHandler(processedRequest);// 找HandlerAdapter(哪个HandlerAdapter能处理当前handle?遍历所有HandlerAdapter的supports方法)HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// 执行拦截器preHandle方法if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// 执行HandlerAdapter的handle方法;解析参数、执行controller、解析返回值、返回ModelAndViewModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// 倒序执行拦截器postHandle方法mappedHandler.applyPostHandle(processedRequest, response, mv);// 1、视图解析器解析出view// 2、渲染// 3、倒序执行拦截器的afterCompletion方法processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}

其中,doDispatch完整源码:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;boolean multipartRequestParsed = false;WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);try {ModelAndView mv = null;Exception dispatchException = null;try {processedRequest = checkMultipart(request);multipartRequestParsed = (processedRequest != request);// Determine handler for the current request.mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {noHandlerFound(processedRequest, response);return;}// Determine handler adapter for the current request.HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// Process last-modified header, if supported by the handler.String method = request.getMethod();boolean isGet = "GET".equals(method);if (isGet || "HEAD".equals(method)) {long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {return;}}if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// Actually invoke the handler.mv = ha.handle(processedRequest, response, mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}applyDefaultViewName(processedRequest, mv);mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException = ex;}catch (Throwable err) {// As of 4.3, we're processing Errors thrown from handler methods as well,// making them available for @ExceptionHandler methods and other scenarios.dispatchException = new NestedServletException("Handler dispatch failed", err);}processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}catch (Exception ex) {triggerAfterCompletion(processedRequest, response, mappedHandler, ex);}catch (Throwable err) {triggerAfterCompletion(processedRequest, response, mappedHandler,new NestedServletException("Handler processing failed", err));}finally {if (asyncManager.isConcurrentHandlingStarted()) {// Instead of postHandle and afterCompletionif (mappedHandler != null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}}else {// Clean up any resources used by a multipart request.if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}}
流程描述
  1. 用户发送请求至前端控制器DispatcherServlet
  2. DispatcherServlet收到请求调用处理器映射器HandlerMapping。
  3. 处理器映射器根据请求url找到具体的处理器,生成处理器执行链HandlerExecutionChain(包括处理器对象和处理器拦截器)一并返回给DispatcherServlet。
  4. DispatcherServlet根据处理器Handler获取处理器适配器HandlerAdapter执行HandlerAdapter处理一系列的操作,如:参数封装,数据格式转换,数据验证等操作
  5. 执行处理器Handler(Controller,也叫页面控制器)。
  6. Handler执行完成返回ModelAndView
  7. HandlerAdapter将Handler执行结果ModelAndView返回到DispatcherServlet
  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器
  9. ViewReslover解析后返回具体View
  10. DispatcherServlet对View进行渲染视图(即将模型数据model填充至视图中)。
  11. DispatcherServlet响应用户。

11_尚硅谷_SSM面试题_MyBatis中当实体类中的属性名和表中的字段不一致

方式1:改sql
  • 例如:给user_id起别名为userId:
    select user_id userId, money from account;
    
方式2:启动驼峰名法

mapUnderscoreToCamelCase = true

方式3:resultMap
  • 例如:
    <resultMap id="BaseResultMap" type="com.ljy.domain.Account"><id property="id" column="id" jdbcType="INTEGER"/><result property="userId" column="user_id" jdbcType="INTEGER"/><result property="money" column="money" jdbcType="DOUBLE"/>
    </resultMap>
    

12_尚硅谷_Java高级_Linux常用服务类相关命令

centos 6

在这里插入图片描述


执行chkconfig --list,运行级别有七种:
在这里插入图片描述
解释:
在这里插入图片描述


centos 7

在这里插入图片描述

13_尚硅谷_Java高级_git分支相关命令

基本命令

在这里插入图片描述


Git工作流

在这里插入图片描述


14_尚硅谷_Java高级_redis持久化

两种持久化方式:RDB (Redis DataBase) 、AOF (Append Only File);

RDB优缺点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


AOF优缺点

在这里插入图片描述
在这里插入图片描述


15_尚硅谷_Java高级_Mysql什么时候建索引

mysql官方对索引的定义为:索引是帮助mysql高效获取数据的数据结构。可也得出索引的本质是数据结构。

优势:

  • 提高检索效率,降低数据库的io成本
  • 通过索引列对数据进行排序,降低数据排序成本,减低cpu消耗

劣势:

  • 降低更新表的速度,因为不仅要保存数据,还要维护索引
  • 索引也是一张表,占用空间

适合创建索引的情况:

  • 主键自动建立唯一索引
  • 频繁作为查询条件的字段
  • 外键
  • 单键、组合索引的选择问题,组合索引性价比更高
  • 排序字段
  • 查询统计或者分组字段

不适合建索引:

  • 表记录太少
  • 经常增删改的表或字段
  • where条件用不到的字段
  • 过滤性不好的(例如:性别;过滤性好的如:身份证号)

16_尚硅谷_Java高级_JVM垃圾回收机制

发生时期

在这里插入图片描述

GC算法

在这里插入图片描述

1. 引用计数算法:(不能处理循环引用,基本被淘汰了)

在这里插入图片描述

2. 复制算法:年轻代使用的是Minor GC,这种gc算法采用的是复制算法

在这里插入图片描述

3. 标记清除:老年代一般是由标记清除或者是标记清除与标记整理混合实现

在这里插入图片描述

4. 标记压缩:老年代一般是由标记清除或者是标记清除与标记整理混合实现

在这里插入图片描述

5. 标记清除压缩

在这里插入图片描述


17_尚硅谷_项目面试题_redis 在项目中的使用场景

redis 数据类型元使用场景

在这里插入图片描述
数据类型:

  • String:用户登录之后
  • Hash:
    • 上述表中的存用户(经常修改,可能新注册的?);
    • 购物车;用户id作为K,商品id作为HK,商品信息作为HV
  • List:秒杀
  • Set:自动排重,上架商品,可用来避免重复上架同一商品
  • ZSet:做销量、好评等排序

18_尚硅谷_项目面试题_es与solr的区别

es与solr的区别

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


19_尚硅谷_项目面试题_单点登录

  • 单点登录:一处登录多处使用
  • 前提:单点登录多使用在分布式系统中
流程图:
  • 原文:https://blog.csdn.net/LBWNB_Java/article/details/120003954
    在这里插入图片描述

20_尚硅谷_项目面试题_购物车

购物车

在这里插入图片描述

21_尚硅谷_项目面试题_消息队列

处理高并发

在这里插入图片描述

  • 异步
    在这里插入图片描述

  • 并行
    在这里插入图片描述

  • 排队
    在这里插入图片描述


电商项目使用场景

支付宝支付成功后,会有回调通知(如果支付宝未收到success,会继续发送回调通知),支付模块收到支付宝的回调通知,一边通过 消息队列 给订单模块通知支付完成,一边响应success
在这里插入图片描述


弊端:

  • 消息的不确定性:使用延迟队列或者轮询技术解决
  • 例如:上图中,既可以支付模块成功后通知订单模块,也可订单模块设置延迟队列主动去查询支付宝的支付状态

这篇关于【Java面试题】《尚硅谷经典Java面试题第一季(java面试精讲)》学习笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/485083

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06