OUZHANBO

对于我这种菜鸡来说,毕业等于失业

0%

SpringSecurity 中的 SecurityContextHolder 分析

分析

一般我们在 SpringSecurity 中可以通过 SecurityContextHolder.getContext().getAuthentication()获取到认证信息,这个认证信息就是存放在 SecurityContext 中,这个 SecurityContext 就是通过 SecurityContextHolder.getContext()获取到的,SecurityContextHolder.getContext()的代码如下

1
2
3
public static SecurityContext getContext() {
return strategy.getContext();
}
阅读全文 »

SpringSecurity 源码(一)——SpringSecurity 如何被加载进来的?

前言

这篇文章还是参考了这个大佬的这篇文章,文笔不好,如果觉得难理解可以看大佬的文章

xml 的方式配置 SpringSecurity

在 web.xml 中添加 filter 的相关配置

1
2
3
4
5
6
7
8
9
10
<filter>
//这里的filter-name必须是springSecurityFilterChain,这里先记住后面源码分析的时候可以知道为什么一定要叫这个名字
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
阅读全文 »

Javaweb 从 web.xml 到 springboot

前言

这篇文章依然是参考了这位大佬的文章,讲得已经非常细了,真的非常建议去看下大佬的文章。

几乎所有人都是从 servlet,jsp,filter 开始编写自己的第一个 hello world 工程。那时,还离不开 web.xml 的配置,在 xml 文件中编写繁琐的 servlet 和 filter 的配置。随着 spring 的普及,配置逐渐演变成了两种方式—java configuration 和 xml 配置共存。现如今,springboot 的普及,java configuration 成了主流,xml 配置似乎已经“灭绝”了。不知道你有没有好奇过,这中间都发生了哪些改变,web.xml 中的配置项又是被什么替代项取代了?

servlet3.0 以前的时代(使用 web.xml 配置)

项目的结构和部分代码

图片丢失

阅读全文 »

参考文章

这篇文章大部分都是参考的下面这位大佬的文章,真的很推荐去看下,写得真的很不错。

前言

JDK 提供的 SPI(Service Provider Interface)机制,可能很多人不太熟悉,因为这个机制是针对厂商或者插件的,也可以在一些框架的扩展中看到。其核心类 java.util.ServiceLoader 可以在 jdk1.8 的文档中看到详细的介绍。虽然不太常见,但并不代表它不常用,恰恰相反,你无时无刻不在用它。玄乎了,莫急,思考一下你的项目中是否有用到第三方日志包,是否有用到数据库驱动?其实这些都和 SPI 有关。再来思考一下,现代的框架是如何加载日志依赖,加载数据库驱动的,你可能会对class.forName("com.mysql.jdbc.Driver")这段代码不陌生,这是每个 java 初学者必定遇到过的,但如今的数据库驱动仍然是这样加载的吗?你还能找到这段代码吗?这一切的疑问,将在本篇文章结束后得到解答。

实现一个自定义的 SPI

1 项目结构

图片丢失

  1. invoker 是我们的用来测试的主项目。
  2. interface 是针对厂商和插件商定义的接口项目,只提供接口,不提供实现。
  3. good-printer,bad-printer 分别是两个厂商对 interface 的不同实现,所以他们会依赖于 interface 项目。
阅读全文 »

Redis 字典 dict 要定义两个哈希表的原因

Redis 字典 dict 定义两个哈希表是为了给哈希表进行扩展或者收缩准备的

为什么 Redis 字典 dict 中的哈希表要扩展或者收缩

因为随着操作的不断执行,哈希表保存的键值对的逐渐增加或者减少,为了让哈希表负载因子(load factor)维持在一个合理的范围之内,当哈希表保存的键值对过多或者过少时,程序需要对哈希表的大小执行相应的扩展或者收缩

Redis 字典 dict 如何实现哈希表的扩展和收缩

扩张和收缩哈希表的工作是通过执行 rehash (重新散列)操作来完成,Redis 对字典 dict 的哈希表执行 rehash 的步骤如下:

  1. 为字典的 ht[1] 哈希表分配空间,这个哈希表的空间大小取决于要执行的操作是扩展还是收缩决,以及 ht[0] 包含键值对的数量 (ht[0].used 的值):
    • 如果执行的是扩展操作,那么 ht[1] 的大小为第一个大于等于 ht[0].used * 2 的 2 ^ n (2 的 n 次方幂)
    • 如果执行的是收缩操作,那么 ht[1] 的大小为第一个大于等于 ht[0].used 的 2 ^ n
  2. 将保存在 ht[0] 中的所有键值对 rehash 到 ht[1] 上面:rehash 指的是重新计算键的哈希值和索引值,然后将键值对放置到 ht[1] 哈希表中索引值对应位置上
  3. 当 ht[0] 包含的所有键值对都迁移到了 ht[1] 之后(ht[0] 变为空表),释放 ht[0] ,将 ht[1] 设置为 ht[0] ,并在 ht[1] 新创建一个空白哈希表,为下一次 rehash 做准备
阅读全文 »

Redis 为什么要自己实现一个 SDS?

原因一:SDS 获取字符串长度的时间复杂度比用 C 语言的字符数组实现的字符串要快

用 C 的字符数组实现的字符串在获取字符串长度时需要遍历整个字符数组,然后把每个字符进行计数,直到遇到空字符('\0' ) 才停止计数得出字符串的长度,这样的时间复杂度为 O(N)

图片丢失

而 SDS 在 len 属性中记录了字符串的长度,所以获取字符串的长度就相当于获取 len 的值,时间复杂度为 O(1)

阅读全文 »

static 关键字声明的变量的加载机制

前段时间在学习单例模式的时候遇到一种写法事用静态内部类来实现的,发现自己不是很懂静态内部类的加载时序,后来衍生到了 static 关键字修饰的变量方法都不是很懂,在网上找了一些文章看了下,大概明白他们的加载的机制和时序,下面来说下。之前我知道类的静态变量会在类被加载的时候初始化,但是类什么时候会被加载呢,这个我之前都没有考虑过。以下是我觉得我平时用得比较多的类加载方式:

​ 1.调用类的静态变量或者静态方法

​ 2.new 一个类的对象

​ 3.Class.forName 动态加载类

下面用代码测试一下第一种情况,在 Main 这个运行类型中的 main 入口方法中调用 Example 类的静态方法 staticField4,这样就会加载 Example 类并且先初始化这个类中的静态变量,静态代码块和静态代码的运行顺序取决于代码的编写顺序,然后再执行 main 方法,测试代码如下:

StaticField:

1
2
3
4
5
6
7
public class StaticField {

public StaticField(String string)
{
System.out.println(string);
}
}
阅读全文 »