- 博客(292)
- 资源 (2)
- 收藏
- 关注
原创 这就是AOP
举个例子,一个业务系统的很多模块都需要记录操作日志,这是一个能从业务逻辑中分离出来的横切关注点,完全不用交织在每个模块的代码中,可以作为一个单独的模块存在。AOP(Aspect Oriented Programming,面向切面编程)是一种编程范式,它的目的是通过分离横切关注点(cross-cutting concerns)来提升代码的模块化程度,AOP 的概念最早是由 Xerox PARC 提出的,它并非站在 OOP 的对立面,而是对 OOP 的一个很好的补充。,它定义了切面中能够采取的动作。
2024-12-04 21:09:19
383
原创 这就是IoC容器
IoC(Inversion of Control,控制反转),也叫依赖注入(Dependency Injection),是一种决定容器如何装配组件的模式。使用 Spring 来实现 IoC,意味着将设计好的对象交给 Spring 容器控制,而不是直接在对象内部控制。控制反转不能很好地描述这个模式,依赖注入却能更好地描述它的特点,所以才经常看到这两个词一同出现。只要遵循这种模式,按照一定规则,容器就能将组件组装起来。这里的容器就是用来创建组件并对它们进行管理的地方。
2024-12-04 21:03:38
746
原创 Spring 容器管理 Bean
Bean 是指 Java 中的可重用软件组件,容器会根据提供的元数据来创建和管理这些 Bean,也包括它们之间的依赖关系。Spring 容器对 Bean 并没有太多的要求,无须实现特定接口或依赖特定库,只要是最普通的 Java 对象即可,这类对象也被称为 POJO(Plain Old Java Object)。JavaBeans 是 Java 中一种特殊的类,可以将多个对象封装到一个对象(Bean)中。特点是可序列化,提供无参构造器,提供 Getter 方法和 Setter 方法访问对象的属性。
2024-12-04 20:46:26
1226
原创 Java注解原理
典型的就是 @Override 注解,一旦编译器检测到某个方法被 @Override 注解修饰了,编译器就会检查当前方法的方法签名是否真正重写了父类的某个方法,也就是比较父类中是否具有一个同样的方法签名。这种情况只适用于那些编译器已经熟知的注解类,比如 JDK 内置的几个注解,而自定义的注解,编译器是不知道注解作用的,当然也不知道该如何处理,往往只是会根据该注解的作用范围来选择是否编译进字节码文件。注解可以提供更大的便捷性,易于维护修改,但耦合度高,XML 相对于注解则是相反的。
2024-12-03 11:59:09
353
原创 Java 泛型
擦除时使用 Object 或者界定类型替代泛型,同时在要调用具体类型方法或者成员变量时插入强转代码,为了保证多态特性,Java 编译器还会为泛型类的子类生成桥接方法。Java泛型是一种类型参数化范式,有三种表现形式(分别是泛型方法,泛型类,泛型接口),允许开发者使用类型参数替代明确类型,实例化时再指明具体类型,达到了代码重用的目的,类似 C++ 模板的概念,但 Java 泛型是一种伪泛型。Java 编译器对泛型应用了强大的类型检测,如果代码违反了类型安全就会报错,可以在编译时暴露大多数泛型的编码错误。
2024-12-01 18:16:27
241
原创 反射和动态代理
否则被认为是不合法操作。从性能角度看,有 benchmark 表示 JDK Proxy 比 cglib 或者 Javassist 慢几十倍,暂且先不谈具体 benchmark 细节,在主流 JDK 版本中,JDK Proxy 在典型场景可以提供对等的性能水平,数量级的差距基本上不是广泛存在的。在选型中,性能未必是唯一考量,可靠性、可维护性、编程工作量等往往是更主要的考虑因素,毕竟标准类库和反射编程的门槛要低得多,代码量也是更加可控的,如果比较下不同开源项目在动态代理开发上的投入,也能看到这一点。
2024-12-01 17:35:49
850
原创 Java OOP
Default method 提供了一种二进制兼容扩展已有接口的办法,比如 java.util.Collection,它是 collection 体系的 root interface,在 Java 8 中添加了一系列 default method,主要是增加 Lambda、Stream 相关的功能。是对行为的抽象,它是抽象方法的集合(声明性的),方法定义和实现分离。特别说明的一点,方法名称和参数一致,但返回值不同,不是有效的重载,这点Java和C++一致,编译都会报错。实践中过度滥用继承可能会起到反效果。
2024-12-01 11:57:15
900
原创 ConcurrentHashMap
初始化在 initTable 实现,这是一个典型的 CAS 使用场景,volatile 的 sizeCtl 作为互斥手段,如果发现竞争性的初始化,就 spin 在那里,等待条件恢复;数据一致性是怎么保证的?HashEntry内部使用 volatile 的 value 字段来保证可见性,也利用了不可变对象的机制改进利用 Unsafe 提供的底层能力(比如 volatile access)去直接完成部分操作,以最优化性能,毕竟 Unsafe 中的很多操作都是 JVM intrinsic 优化过的。
2024-11-29 21:08:26
262
原创 Java Map
这种行为适用于一些特定场景,比如构建一个空间占用敏感的资源池,希望可以自动将最不常被访问的对象释放掉,就可以利用LinkedHashMap提供的机制来实现。TreeMap则是基于红黑树的一种提供顺序访问的Map,和HashMap不同,它的get、put、remove操作都是O(log(n))的时间复杂度,具体顺序可以由指定的Comparator来决定,或者根据键的自然顺序。大部分使用Map的场景,通常是放入、访问、删除,对顺序没有特别要求,HashMap在这种情况下基本是最好的选择。
2024-11-29 17:40:06
185
原创 Java Collection
它不需要考虑扩容,空间上更加紧凑等。Collection集合类都不是线程安全的,但并不代表这些集合完全不能支持并发编程的场景,在Collections工具类中提供了一系列的synchronized方法,但平常不推荐使用,同步控制粒度太大,不适合对性能要求较高的场景。Queue/Deque,Java提供的标准队列结构的实现,除了集合的基本功能,它还支持类似先入先出(FIFO, First-in-First-Out)或者后入先出(LIFO,Last-In-First-Out)等特定行为。
2024-11-29 16:46:40
963
原创 Java原始数据类型和包装类
对于应用移植,存在一些底层实现的差异,比如64位HotSpot JVM里的对象要比32位HotSpot JVM大(具体区别取决于不同JVM实现的选择),但总体来说并没有行为差异,应用移植还是可以做到“一次书写,到处执行”,开发者更多需要考虑的是容量、能力等方面的差异。Java对象是引用类型,内建了多态、线程安全等方面的支持,一个原始数据类型数组在内存里是一段连续的内存,而对象数组存储的是引用,对象分散地存储在堆的不同位置。各种转换方法(比如转换为不同进制的字符串,如8进制),或者反过来的解析方法等。
2024-11-29 15:36:13
622
原创 Java String设计思想
为了能修改字符序列,StringBuffer和StringBuilder底层都是利用可修改的(char,JDK 9以后是byte)数组,二者都继承了AbstractStringBuilder,里面包含了基本操作,区别仅在于最终的方法是否加了synchronized。在运行时,字符串的一些基础操作会直接利用JVM内部的Intrinsic机制,往往运行的就是特殊优化的本地代码,根本就不是Java代码生成的字节码。我们如果确定拼接会发生非常多次,而且大概是可预计的,就可以指定合适的大小,避免很多次扩容的开销。
2024-11-29 00:38:04
646
原创 搭建Java开发环境(MAC、IDEA)
不管三七二十一,先把需要的资源下载下来,然后挨个安装。IDEA:IntelliJ IDEA(ideaIU-2021.3.3-aarch64)JDK:Java Downloads | Oracle(jdk-8u333-macosx-x64)Maven:Maven – Download Apache Maven(apache-maven-3.8.6-bin)Git:Git - Downloads(git-2.33.0-intel-universal-mavericks)idea中application.prop
2022-06-29 15:56:59
1575
原创 C/C++的标准演进及对应的编译器
因为区别很小,因此,C89和C90通常指同一种语言,与传统C语言K&R标准对比, ANSI/ISO标准C语言的改进了很多。在1999年,C语言的标准化委员会将不断改进的C语言, 收纳为新的标准,官方名称为 ISO/IEC 9899: 1999,简称为 C99 标准,严格上讲是C语言的第二个官方版本,C99 标准引入了许多特性。在1995年,对C89标准作了一个修订与补充,产生了一个C95标准,官方名称为:ISO/IEC 9899:1990/AMD 1:1995,但并不是一个真正的标准,主要改动如下,
2022-06-01 23:35:43
3252
1
原创 服务熔断——断路器
就像电路中的保险丝熔断一样,微服务架构中,上游服务因为过载或者故障不可用时(这种不可用情况是指长时间不可用且持续性远程调用,非暂时故障),需要及时使用断路器在下游的服务调用方暂时熔断调用方和服务提供方之间的调用链,避免出现服务雪崩进而拖挂整个业务系统,从而保证部分服务与系统整体的稳定性和可用性。服务雪崩,是指调用链的某个环节不可用时,导致下游调用方环节不可用,最终这种影响像雪崩一样扩大到整个系统中,导致整个系统不可用。断路器模式断路器代理了服务调用方对提供方的请求,它监控了最近请求的失败和超
2022-05-31 01:02:30
760
原创 常见的线程模型
线程之间的调度永远是一个复杂的话题,但是并发编程必然会涉及到操作系统对线程的调度。根据资源访问权限的不同,操作系统会把内存分为内核空间和用户空间,内核空间的指令代码具备直接调度计算机底层资源的能力,比如说 I/O 资源等;用户空间的代码没有访问计算底层资源的能力,需要通过系统调用等方式切换为内核态来实现对计算机底层资源的申请和调度。线程作为操作系统能够调度的最小单位,也分为用户线程和内核线程:用户线程由用户空间的代码创建、管理和销毁,线程的调度由用户空间的线程库完成(可能是编程语言层次的线程库),无
2022-05-30 22:51:05
902
原创 Redis 及其数据类型、编码格式
Redis,全称为远程字典服务(Remote Dictionary Server)。Redis 印象Redis 为什么叫 Redis(远程字典服务)?从形式上,作为开源的 kv 存储系统,使用了字典 dict 结构来管理数据,内部定义了数据库对象 server.h/redisDb 负责存储数据。typedef struct redisDb { dict *dict; // 数据库字典,该redisDb所有的数据都存储在这里 dict *expires; //
2022-05-30 01:03:27
895
原创 Go context 上下文
Go Context,goroutine 并发的利器,可以取消正在执行的 goroutine,即通过 Context 控制并发使得 goroutine 退出。先来看一个例子eg.实现了一个监控 deamon,会让程序一直运行,每隔1秒就会打印一次package mainimport ( "fmt" "sync" "time")func watcher(strName string) { for { .
2022-05-28 22:42:34
264
原创 Go sync 同步原语
Go 中不仅有 channel 这种 CSP同步机制,还有 sync.Mutex、sync.WaitGroup 等比较原始的同步原语。使用它们,可以更灵活的控制数据同步和多协程并发。sync.Mutex sync.RWMutex sync.WaitGroup sync.Once sync.Cond sync.Map在一个 goroutine 中,如果分配的内存没有被其他 goroutine 访问,只在该 goroutine 中被使用,不存在资源竞争的问题。但如果同一块内存被多个 gorou.
2022-05-28 19:08:39
1881
原创 Go channel实现顺序无限输出123123123...
分析:顺序:需要同步,无 buffer channel 正好可以实现;无限:主协程阻塞,子协程为 deamon,或者说无限循环;需要开3个线程(协程),一个线程用来输出1,无限输出 一个线程用来输出2,无限输出 一个线程用来输出3,无限输出实现无限输出 123123123...package mainimport ( "fmt" "time")func print(curCh chan struct{}, nextCh chan stru
2022-05-28 11:11:44
1023
原创 Go channel 通道
go routine 可以使用 channel 来进行通信,使用通信的手段来共享内存。使用形式有下面几种,无缓冲 channel 有缓冲 channel 需要注意 channel 的关闭时机 单向 channel channel + select,实现多路复用基本语法make(chan Type) 等价于 make(chan Type,0)make(chan Type, capacity)ch<- value // 发送 value 到 ch<- ch...
2022-05-28 02:48:41
456
原创 搭建Go 开发环境(Ubuntu,Windows上类似)
Windows 、Linux 上搭建 Go 环境的流程和 Mac 类似,但要比 Mac上 简单,搭建Go开发环境,开发 RPC 服务(MAC、VSCode)_Schuyler_yuan的博客-优快云博客步骤如下,1. 下载并解压 Go Linux 安装包$ wget https://dl.google.com/go/go1.18.1.linux-amd64.tar.gz$ sudo tar -zxvf go1.18.1.linux-amd64.tar.gz -C /usr/local/
2022-05-27 16:22:40
305
原创 GMP 线程调度模型
GMP 是 Go 协程调度的 CSP 并发模型实现。Golang 内部有三个对象,goroutine,machine,processor。研究这块最好结合源码。GMP 调度模型G=Goroutine 协程,P=Processor 处理器, M=Thread 线程全局队列(Global Queue):存放等待运行的 G。 P 的本地队列:同全局队列类似,存放的也是等待运行的 G,存的数量有限,不超过 256 个。新建 G’时,G’优先加入到 P 的本地队列,如果队列满了,则会把.
2022-05-26 19:14:02
1001
原创 Go 并发模型
Go 语言中实现了两种并发模型,一种是依赖于共享内存实现的线程-锁并发模型,另一种则是CSP(Communicationing Sequential Processes,通信顺序进程)并发模型。大多数编程语言(比如 C++、Java、Python 等)的并发逻辑都是基于操作系统的线程。并发执行单元(线程)之间的通信利用的就是操作系统提供的线程或进程间通信的原语,如共享内存、信号、管道、消息队列、套接字等。在这些通信原语中,使用最广泛的就是共享内存。 而 Go 语言从设计之初,就将解决上面传统并发模型问题
2022-05-26 18:54:39
727
原创 并发和串行、并行的概念
先抛开语言不管,只聊概念,说起并发,就很容易想到它和串行、并行的区别。串行:一次只能取得一个任务并执行这个任务,这个任务执行完后面的任务才能继续;并行:一次可以取得多个任务,并且可以同时执行这几个任务,几个任务在同一时刻互不干扰地同时执行;并发:一次可以取得多个任务,但是只能同时执行一个任务。同时安排若干个任务,这些任务可以彼此穿插着进行;有些任务可能是并行的,比如买菜、发邮件和去幼儿园的某些路途是重叠的,这时你的确同时在做三件事;但进菜市场和发邮件和接娃三者是互斥的,每个时刻只能完成其中一件。
2022-05-26 11:39:08
6548
原创 VSCode(Ubuntu、C++)
Ubuntu安装VSCode去VSCode官网下载 deb 安装包,运行命令安装即可$ sudo dpkg -i code_1.67.2-1652812855_amd64.deb安装成功,去Ubuntu搜索vscode,打开即可。为了以后方便使用,也可以直接拖拽到菜单栏。可以根据自己的需要安装常用的插件了,C/C++插件是开发C++必须的。C/C++,肯定是必须的。C/C++ Snippets,即 C/C++重用代码块。C/C++ Advanced Li.
2022-05-25 18:45:11
1175
原创 Go routine、channel、sync、context和好用的并发模式
Go routine 协程协程和通道,是 Go 语言并发的基础。谈并发,就绕不开线程,操作系统会为 deamon 服务创建进程,进程可以看作一个服务的工作空间,它包含了服务运行所需的所有资源(PCB控制块),比如内存空间、文件句柄等。线程是进程的执行空间,一个进程可以有多个线程,线程被操作系统调度执行,也就是可以实现多线程的并发。Go 中的并发,是通过协程 goroutine 来实现的。相比线程来说,协程更加轻量,一个程序可以随意开启成千上万个 goroutine。协程是被 Go 运行时所调度的,这
2022-05-24 11:17:30
286
原创 Golang中的项目管理是对代码包的管理
引言如果想要在项目中使用第三方代码库,C/C++ 中一般会有两种方法,1. 将第三方源码合并到自己的工程文件中直接编译;2. 将第三方代码先编译生成静态链接库(.a、.lib)或动态链接库(.so 、.dll) 放到工程目录下,然后通过条件编译直接使用。目前大多数主流语言都有一套标准的包管理解决方案,比如 Java 有 maven,Python 有 pip,Ruby 有 RubyGems,Rust 有Cargo,Nodejs 有 npm,PHP 有 composer。包管理工具用于自动化构.
2022-05-12 23:29:23
837
原创 Golang一角:环境变量(Go开发必需的环境变量、普通环境变量)
“环境变量”这个词,有经验的开发同学对它一定很熟悉了,它提供给软件工程以高灵活性、高扩展性,大到操作系统,小到某个项目,都有它的影子,它的表现方式有很多。微服务应用提倡将配置存储在环境变量中,任何从开发环境切换到生产环境时需要修改的东西都从代码抽取到环境变量里。但是在实际开发中,如果同一台机器运行多个项目,在操作系统中设置环境变量容易冲突,不实用,就会有了从.env文件中读取配置, 然后存储到程序的环境变量中。一个项目对应一个 .env 文件,在代码中读取 .env 文件的方式也非常方便。很多大..
2022-05-07 00:23:00
4446
原创 一份方便的 Vim 配置
先贴图Vim 编辑器配置执行命令,$ vi ~/.vimrc复制下面的内容粘贴即可。"~/.vimrc"vim config file"date 2022-03-31"Created by shouyuan """"""""""""""""""""""""""""""""""""""=>全局配置<="""""""""""""""""""""""""""""""""""""""关闭vi兼容模式"set nocompatible"设置历史记录步数"s
2022-05-01 23:47:54
901
原创 MAC机后端开发必备
开篇:相信很多日常使用 MAC 进行软件开发的同学会有一种感受,在换 MAC 机的时候,拿到的都是一些裸系统,有一些常用必备的软件需要重新来安装一遍。我也遇到几次这样的问题,发现每次配置开发环境时都要安装那么几个方便好用的软件,在这总结一下备忘踩过的坑。brew(Homebrew),Mac上的包管理器,一般拿到 MAC 就要先安装这个工具,方便后面使用brew命令(类似Linux中的yum)安装开发环境。Mac上有Homebrew和Homebrew-cask,它俩之间的区别可以参考之前的记录:Ma
2022-05-01 23:44:24
2911
原创 搭建Go开发环境,开发 RPC 服务(MAC、VSCode)
一、配置 Go 1.18 开发环境1. install golang by brew$ brew install go2. set Path for Go# .zshrc# goexport GOROOT=/opt/homebrew/Cellar/go/1.18/libexecexport GOPATH=$HOME/workspace/project/goexport PATH=$PATH:$GOROOT/bin:$GOPATH/binexport GOPROXY=https:
2022-04-29 16:48:22
3502
2
Pima Indians Diabetes Data Set
2022-05-13
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人