「Spring」AOP
OOP我们都知道,它把系统看作多个对象的交互。而AOP(Aspect Oriented Programming),面向切面编程,把系统分解为不同的关注点,或者称之为切面(Aspect)。
例如,对每个业务方法,除了业务逻辑,还需要安全检查、日志记录和事务处理。
安全检查、日志、事务等代码,它们会重复出现在每个业务方法中。
如果我们采用Proxy模式,给业务组件包一个代理类来实现这些,确实也可以,但比较麻烦:必须先抽取接口,然后,针对每个方法实现Proxy。
而AOP可以把权限检查、日志、事务等视作一种切面(Aspect),然后,以某种自动化的方式,把切面织入到核心逻辑中,实现Proxy模式。
在Java平台上,对于AOP的织入,有3种方式:
编译期:在编译时,由编译器把切面调用编译进字节码,这种方式需要定义新的关键字并扩展编译器,AspectJ就扩展了Java编译器,使用关键字aspect来实现织入;
类加载器:在目标类被装载到JVM时,通过一个特殊的类加载器,对目标类的字节码重新“增强”;
运行期:目标对象和切面都是普通Java类,通过JVM的动态代理功能或者第三方库实现运行期动态 ...
「Spring」IoC
Spring Framework主要包括几个模块:
支持IoC和AOP的容器;
支持JDBC和ORM的数据访问模块;
支持声明式事务的模块;
支持基于Servlet的MVC开发;
支持基于Reactive的Web开发;
以及集成JMS、JavaMail、JMX、缓存等其他模块。
IoC全称Inversion of Control,译为控制反转。
why如果一个系统有大量的组件,采用new创建实例的方式来持有,其生命周期和相互之间的依赖关系如果由组件自身来维护,不但大大增加了系统的复杂度,而且会导致组件之间极为紧密的耦合,继而给测试和维护带来了极大的困难。
而IoC就可以用于解决这一系列核心问题:
负责创建组件
负责根据依赖关系组装组件
销毁时,按依赖顺序正确销毁
传统的应用程序中,控制权在程序本身,程序的控制流程完全由开发者控制。这种模式的缺点是,一个组件如果要使用另一个组件,必须先知道如何正确地创建它。
在IoC模式下,控制权发生了反转,即从应用程序转移到了IoC容器,所有组件不再由应用程序自己创建和配置,而是由IoC容器负责,这样,应用程序只需要直接使用已经创建好并且配置好 ...
「Java」多线程
Java语言内置了多线程支持:一个Java程序实际上是一个JVM进程,JVM进程用一个主线程来执行main()方法,在main()方法内部,我们又可以启动多个线程。此外,JVM还有负责垃圾回收的其他工作线程等。
创建线程
从Thread派生一个自定义类,然后覆写run()方法
12345678910Thread t = new MyThread();t.start(); // 启动新线程class MyThread extends Thread { @Override public void run() { ... }}
创建Thread实例时,传入一个Runnable实例
123456789Thread t = new Thread(new MyRunnable());t.start(); // 启动新线程class MyRunnable implements Runnable { @Override public void run() { ... ...
「Java」泛型
泛型即编写模板代码来适应任意类型。使用时不必对类型进行强制转换,并通过编译器对类型进行检查;
例如,编一个Pair类:
1234567891011121314public class Pair<T, K> { private T first; private K last; public Pair(T first, K last) { this.first = first; this.last = last; } public T getFirst() { ... } public K getLast() { ... } public static <Q> Pair<Q> create(Q first, Q last) { return new Pair<Q>(first, last); }}
如上,需要注意,静态泛型方法不能引用泛型类型,应 ...
「Java」注解
注解是放在Java源码的类、方法、字段、参数前的一种特殊“注释”,是Java语言用于工具处理的标注,比如常用的@Override
Java的注解可以分为三类:
第一类是由编译器使用的注解,例如:
@Override:让编译器检查该方法是否正确地实现了覆写;
@SuppressWarnings:告诉编译器忽略此处代码产生的警告。
这类注解不会被编译进入.class文件,它们在编译后就被编译器扔掉了。
第二类是由工具处理.class文件使用的注解,比如有些工具会在加载class的时候,对class做动态修改,实现一些特殊的功能。这类注解会被编译进入.class文件,但加载结束后并不会存在于内存中。这类注解只被一些底层库使用,一般我们不必自己处理。
第三类是在程序运行期能够读取的注解,它们在加载后一直存在于JVM中,这也是最常用的注解。例如,一个配置了@PostConstruct的方法会在调用构造方法后自动被调用(这是Java代码读取该注解实现的功能,JVM并不会识别该注解)。
注解可以配置参数,没有指定配置的参数使用默认值;如果参数名称是value,且只有一个参数,那么可以省 ...
「Java」反射
通过Class实例获取class信息的方法称为反射。通过反射,即便我们对某个实例一无所知,但仍可以在程序运行期间获取该对象的所有信息。
Class类在java中,除了int等基本类型,其他类型均为class(包括interface)。而class是由JVM在执行过程中动态加载的。(动态加载:JVM在执行Java程序的时候,并不是一次性把所有用到的class全部加载到内存,而是第一次需要用到class时才加载)
JVM在第一次读取到一种class类型时,将其加载进内存。每加载一种class,JVM就为其创建一个Class类型的实例,这个实例就包含了该class的所有信息(name、package、super、field、method…)。当编译一个新类时,会产生一个同名的 .class 文件,该文件内容保存着 Class 对象。
注意Class类的构造方法是private,只有JVM能创建Class实例,我们自己的Java程序无法创建。
那么如何获取class实例?
通过一个class的静态变量class获取:
1Class cls = String.class;
通过实例变量提 ...
「selenium」基础
Selenium是一个用于Web应用程序测试的工具。
Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Firefox,Safari,Chrome,Opera等。
这个工具的主要功能包括:测试与浏览器的兼容性——测试你的应用程序看是否能够很好得工作在不同浏览器和操作系统之上。测试系统功能——创建回归测试检验软件功能和用户需求。
而用在爬虫上则是模拟正常用户访问网页并获取数据。
这里记录Selenium2的基础知识。
Pre安装chromedriver && selenium 库
一个简单的实例:
打开百度首页,在输入框中输入python,点击搜索
1234567891011121314151617181920212223from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditions as ECfrom ...
「OS」文件管理(磁盘组织与管理)
磁盘结构磁盘/磁道/扇区
盘面/柱面/物理地址
磁盘分类
磁盘调度算法读写时间
调度算法先来先服务(FCFS)
根据进程请求访问磁盘的先后顺序调度
公平;如果大量进程访问的磁道很分散,效率会很差
最短寻道时间优先(SSTF)
优先处理当前磁头最近的磁道,保证寻道时间最短(眼前最优,未必整体最优)
性能较好,但是可能产生饥饿现象(离磁头远的请求长时间得不到满足)
扫描算法(SCAN)
又叫电梯算法,在SSTF算法的基础上,规定磁头只有移动到磁道尽头(最外侧或者最内侧)才能往回移动
性能较好,不会饥饿;但是只能扫描到最边上的磁道才能改变磁头方向,越外侧的的磁道,响应频率越高
LOOK调度算法
改进SCAN算法,磁头边移动边观察(LOOK),如果移动方向没有请求了,就不必继续扫描,直接调头
循环扫描算法(C-SCAN)
只有磁头朝着某个方向移动(比如磁道号增大方向)时才处理访问请求,移动到最边上后直接返回到另一边(0号磁道),返回途中不处理请求
相比SACN算法,各个位置的磁道响应频率很平均
C-LOOK算法
改进C-SCAN算法,磁头移动方向上如果没有请求了,就直接返回到最靠近另 ...
「OS」文件管理(文件系统)
文件就是一组有意义的信息/数据的集合
文件的属性
文件名 主要是给用户看,同一个目录下不允许重名文件
标识符 一个系统内各文件标识符唯一,对用户毫无可读性,给操作系统看的
类型 文件扩展名
位置 文件存放路径,给用户看的;外存中的存放地址,操作系统可见
大小
创建时间
上次修改/访问时间
所有者信息
保护信息
文件的逻辑结构什么是逻辑结构逻辑结构:在用户看来,文件内部的数据是如何组织起来
物理结构:操作系统看来,文件的数据如何存放在外存中
无结构文件又叫流式文件,比如.txt,文件内部的数据由一些二进制或者字符流组成
有结构文件又叫记录式文件,比如数据库表,由一组相似的记录组成记录是一组相关数据项的集合,每条记录有一个数据项可作为关键字根据各条记录的长度是否相等,分为:定长记录,可变长记录
顺序文件文件中的记录顺序排列(逻辑上),记录可以定长或可变长。各记录在物理上可以顺序存储或链式存储
链式存储:
逻辑上相邻的记录,在物理上离散存储。无论是定长/可变长记录,都无法实现随机存取,只能从链头开始遍历
顺序存储:
逻辑上相邻的记录,在物理上也相邻。没有说明的情况下,顺序文件指 ...
「OOP」JML
规格什么是规格对一个方法/类/程序的外部可感知行为的抽象表示
意义
规格把设计与实现有效分离
准确理解一个方法的行为,是多人协同开发时的交互基础
可以以逻辑方式来验证代码实现的正确性
作为开展测试设计的依据。我们不能只在黑盒层次开展测试,也需要对类、方法和接口进行测试
如何表示规格由许多研究,比如形式化语言。要表示规格,需要实现:
方法规格抽象
执行前对输入的要求—-前置条件(precondition)
执行过程中对于环境(参数、所在this)的改变描述—-副作用(Side-Effects)
执行后返回结果应该满足的约束—-后置条件(postcondition)
数据规格抽象(类型抽象)
数据状态应该满足的要求—-不变式(invariant)
数据状态变化应该满足的要求—-约束(constraint)
类型层次下的规格关系子类重写方法可以减弱父类方法规定的Requires,或者加强父类方法规定的Ensures
子类可以对父类进行扩充,但需要保持父类的规格仍然成立
LSP替换原则:在任何父类型对象出现的地方使用子类对象都不会破坏user程序的行为
JMLJML (Java ...