admin管理员组

文章数量:1594242

静态语言的定义:变量定义的声明变量的类型
	(1)变量的类型在编译的时候确定
    (2)变量的类型在运行时不能修改
动态语言的定义:变量定义时无类型声明的语言
	(1).变量的类型在运行的的时候确定
	(2).变量的类型在运行时候可以修改
强类型语言的定义:强制数据类型定义的语言
	也就是说,一旦数据类型确定之后,如果不经过强制转换,他就永远是这个数据类型。
弱类型语言的定义:数据类型可以被忽略的语言。
	跟强类型语言相反,一个变量可以被赋予不同的数据类型,这样看来,强类型的语言的运行的时候,可能速度不急弱类型的语言,但是,强制数据类型的规范可以避免很多的错误。
java:
	强类型语言:大小写敏感
	解释性(需要jvm解释运行)+编译型(需要javac编译成.class文件才可以运行)的语言
	准静态语言+准动态语言

基本数据类型:
	整数:byte 占1字节  short  占2字节  int(默认) 占4字节  long 占8字节
	浮点数    float  占4字节  double(默认)  占 8字节
	字符: char  占2字节    
	布尔值:boolean  占 1位
	扩展:字符型的还有 Ascii(中文占1个字节,共128个),  unicode(中文占2个字节)  UTF-8(中文占3个字节,推荐使用的)
引用数据类类型:
	类,接口,数组
类型转换:
	向上转(低转高):自动转
	向下转(高转低):强制转
变量类别:
	1.类变量:就是类中的static修饰的变量,比如:public static name="小明"
	2.实例变量:就是类中的一般变量,比如:public name="小红";没有static修饰的变量
	3.局部变量:就是方法中的变量
	4.常量:就是有final修饰的变量:声明的时候必须初始化,而且一旦初始化,就是不能改变的,一般使用纯大写
作用域:
	类变量实在整项目中都有效
	实例变量,只在本类中有效
	局部变量:实在本方法中有效。
1.使用new关键字的时候,除了分配空间之外(名字存在栈中,分配的空间在堆中),还会直接默认初始化的值,以及对类中构造器的使用
2.构造器也叫构造方法,是在创建时期必须要创建的,并且特点是
	a).必须和类名相同
	b).不能使用String之类的返回值类型,也不能写void
3.构造器的类型:
	1.无参构造(没有参数的):new的时候不传参数
	2有参构造:有参数的构造器(注意:一旦写了有参构造,无参构造就没有了,但是这个时候new的时候会报错,所以无参构造必须存在) new的时候不传参数走无参构造(这个无参构造必须亲自写一个,不能用默认的看不到的那个),传参数的时候走有参构造
3.构造器作用:
	1.实例化对象,本质就是在调用构造器(使用new关键字,必须要有构造器)
	2.用来初始化值
static关键字:
1.是和类一起加载的,类存在,他就存在,因为,当有static修饰的类的时候,不能调用没有static修饰的类
执行顺序:静态代码快(多个按顺序执行)--main方法中出现new之前的可以被直接输出的语句--匿名代码--构造方法--main方法中的new以后的代码顺序执行
2.类中static修饰的静态方法能直接调用非静态的方法,但是非静态方法不能调用静态方法。

instanceof关键字:语法规则:小类/父类/祖宗类 (至少都是小类) instanceof 小类
	判断一个对象是否为一个类的实例
	判断一个 对象是否为一个实现指定接口的类的实例
	判断一个对象是否为一个子类的实例
一个类里只能有1个public修饰的类,所以,再有其他类的时候,直接 
class 类名{}就可以了
实体类是抽象的,所以,需要实例化才能使用下面的方法和属性等等
 
封装(三大特性之一):
实体类都是私有的,属性私有,提供公共的get/set方法供外部使用,这些公共的方法可以做一些基本的逻辑判断
封装的意义:
1.提高数据的安全性,保护数据
2.隐藏代码的实现细节
3.统一接口,形成一种规范
4.增加系统的可维护性
重载:(overload)(多态的一种,另一中是重写)
同一个类,同一个方法名
参数不同(类型/顺序/个数)
继承(三个特性之二):(extands):就是扩展,子类是父类的扩展a
特点:
1.是类跟类之间的关系,除此之外,类跟类之间的关系还有依赖,组合,聚合等等
2.继承是父类(基类)和子类(派生类)的两个类之间的关系,语法:字类 extands 父类
3.之间的关系是,字类 is a父类

知识点: 
(字类继承了父类,就拥有了父类的所有方法,父亲私有的变量或者方法除外)
理解:
	1.父类中的方法,及时子类没有,new 字类的时候,也能.出父类的方法
	,但是.父类私有的属性或者方法的时候,会报错,所以一般情况下,继承都是public的
	(在java 中所有的类,都默认直接或者间接继承Object类)
	(Java中,只有单继承,没有多继承,也就是说,一个类,只能继承一个父类)
	

拓展:
在java中,所有的类,都直接或者间接的继承Object这个类
权限的从大导小级别
public  :公共的
protected:受保护的
default:默认的
private:私有的
super关键字的使用:
1.super关键字的使用,是在继承之中发生的
2.new 子类的时候,执行的顺序:进入到子类的无参构造,先访问super()调用父类的构造方法,然后执行子类构造方法中的其他语句,子类构造函数走完之后,new才算走完,之后,在进行调用子类.出来的方法
特别注意:子类的构造器中,不显示的写super()的时候,默认存在,调用父类的构造函数,当显示的写的时候,必须放在第一行,否则会报错,在构造器中写this的之后,也不许放在第一行,所以,在子类中,不能调用本类的无参构造

注意点:
	1.super()在子类中默认调用父类的构造方法,必须放在子类构造方法的第一步
	2.super关键字必须之出现在子类的方法中
	3.super和this不能同时调用构造方法(因为是要保证都在第一行,无法实现)

this和super关键字的区别
	代表对象不同:this是指本类中属性(本身调用者),比如this.属性就是值本类的属性,this.方法就是指本类的方法,super:是用来在子类中调用父类的属性,或者方法.,
	前提不同:super必须有继承再能使用,this没有继承也能使用。
	构造方法的区别:this()调用本类的构造方法,super()调用父类的构造方法。
方法的重写:override
重写中的静态方法和非静态方法区别很大
	静态方法:只跟左边的类型有关,也就是,父类 =new 子类()的时候,走的时候是走父类的方法,子类 =new 子类()的时候,走子类的方法
	非静态方法(重写):跟右边的类型有关系 ,例如:父类 =new 子类(),如果发生重写,则走的是子类的方法;子类 =new 子类()的时候,走的是子类的方法
总结:重写
	前提:需要有继承关系,子类重写父类的方法,重写只是跟方法有关系的
	语法规则:方法名必须相同,参数列表也必须相同,修饰符范围可以扩大,但是不能缩小,private<default<protected<public,抛出的异常,范围只能缩小,不能扩大
为什么需要重写:
	父类的功能子类不一定需要,或者,不一定满足
多态:父类的引用指向子类
例子:
	父类 =new 子类():能调用的方法:是没有被重写的父类的方法,和被子类重写的子类的方法
	子类=new 子类();能调用的方法:是子类本身的方法,和父类的方法
注意事项:
	1.多态是方法的多态,属性没有多态。
	2.子类和父类的关系,没有联系的时候会报类型转换异常
	3.存在条件:继承,方法的重写,父类的应用指向子类  父类 =new 子类();
不能重写的方法:
	1.static:方法属于类,不属于实例
	2.final:常量:一旦声明就不能改变,不能重写,也就不能被继承。记住final之后断子绝孙了
	3.private:私有的属性不能重写
抽象类:abstract
特点:
	1.抽象类中可以有一些正常的方法
	2.一个类中只要有一个抽象类,这个类必须为抽象类。
	3.抽象类不能直接被实例化,只能有子类去继承,而且必须去重写父类的抽象方法,使用的时候,new 子类()然后去使用其中的被重写过的抽象方法。
	4.抽象类也是有构造方法的
为什么使用抽象类:
	1.写公共的抽象方法,节省开发效率
接口:interface:只有方法的定义
	Java的类只能单继承,但是接口可以多继承
特点:
	1.接口中的所有的方法都是抽象的,默认的是:public abstract
	2.接口中定义的属性,默认是的:public static final 
	3.接口都需要有实现类,实现接口的类必须重写接口中的每个方法
接口的作用:
	1.约束
	2.定义一些方法,让不同的人自己去实现自己的方法
	3.接口的默认修饰符是:public abstract
	4.常量都是静态常量:static final
	5.接口不能被实例化,只能实例化子类,本质是接口没有构造方法
	6.接口可以被多个实现,关键字:implements
	7.实现接口之后,必须重写其中的方法
5种常见的异常
ArrayIndexOutOfBoundsException  (数组下标越界)
NullPointerException(空指针异常)
ArithmeticException(算数异常)
MissResourceException(丢失资源)
ClassNotFoundsException(找不到类异常)
classCaseException:类型转换异常
除此之外还有一些常见的异常,比如:io异常,sql异常等等

Error和Exception的区别
Error:一般情况不是我们程序导致的,可能是Jvm里面的东西出错,比如,栈溢出等等,一旦报错,jvm会停止运行。
Exception:一般情况是我们程序导致的,我们是可以去解决的。

捕获异常的时候:
try{
//需要捕获的语句
}catch(异常的类型){
出现异常之后的输出语句
} fnally{
//无论如何都会去执行,主要是善后工作
}
注意:当出现多个catch的时候,一定是从上到下范围逐渐扩大  比如:sql异常->Exception->Throwable(最大)
StringBuffer和Stringbuild
StringBuffer:多线程,效率低,安全,语法:append();
StringBuild:单线程,效率高,不安全
集合框架:
collection:包括:list(有序,可重复)、set(无序不可重复)
		list:分为:AyyayList(数组),LinendList(链表)
		set:HashSet(),TreeSet
Map:包括:HashMap(JDK1.7:组成结构:数组+链表  JDK1.8组成结构:数组+链表+红黑树)
刷题  leetcode
排序算法:西部开源官方(哔哩哔哩)
注解和反射:
注解:Annotation,是从JDK5.0引入的
注解的作用:
	1.不是程序本身,可以对程序做出解释
	2.可以被其他程序读取
线程:Thread
线程简介:
进程(Process)和线程(Thread):
	进程是一个动态的过程:是把程序跑起来的过程,是执行程序的一次执行过程,进程是系统资源分配的单位,一个进程中包含若干个线程,至少包含一个线程
	线程:是cpu调度和执行的单位,main是程序的需线程,另外还有一下jvm自动执行的线程叫守护线程,比如Gc(垃圾回收机制)线程
每个对象都有一把锁,sleep()的时候不会释放锁

## ***核心:***:
	1.线程就是独立执行的路径
	2.在程序运行的时候,即使没有创建线程,后台也会有多个线程在执行,比如Gc线程,主线程等等
	3.main()称之为主线程,位系统的入口,用于执行整个程序
	4.在一个进程中,如果开辟了多个线程,线程的运行是由调度去来安排调度的,调度器于操作系统是密切相关的,先后顺序是认为不能干预的
	5.对同一份资源操作的收,会存在抢资源的问题,需要加入并发机制
	6.线程会带来额外的开销,如cpu调度时间,并发开始开销
	7.每个线程都在自己的工作内存中交互,内存控制不当会造成数据不一致

实现线程的方式:
	1.继承Thraed类(重点),这个的本质也是实现了Runable接口  
	2.实现Runable接口(重点)
	3.实现Callable(了解)

创建线程的方式1:继承Thread类
	步骤:1.继承Thread类;2.重写run方法;3.创建线程的实例;4.调用   线程类.start()开启线程
	总结:线程开启并不一定立刻执行,由cpu调度
创建线程的方式2:实现Runable接口
	步骤:1.实现Runable接口;2.重写run()方法;3.创建线程对象,new Thread(线程类).start();
Thread.sleep()   //延迟,需要try catch来捕获异常
	语法:new Thread(线程类,线程的名字).start();,Thread.currentThread().getName获取线程的名字
创建按线程的方式3:实现Callable接口
	步骤1:1.实现Callable接口implements Callable<Boolean>;参数可以自己定义,方便合适即可 2.重写call方法;3.创建线程对象 new;4.创建执行服务.ExecutorService ser= Executors.newFixedThreadPool(3);后面的数字是几个线程的意思;5.执行线程服务:Future<Boolean> r1=ser.submit(t1);用submit来执行,t1是线程的实例;6.boolean rs1=r1.get();获取执行的结果;7.ser.shutdownNow();关闭服务
	步骤2:1.FutureTask<返回值类型> t=new FutureTask<返回值类型>(线程的实体类);2.new Thread(t).start();3.返回值=t.get()获取返回值,需要捕获异常
	好处:1‘可以定义返回值,;2.可以抛出异常
静态代理模式:线程的底层实现原理
	总结:1.真实对象和代理对象,都要实现同一个接口;2.代理对象要代理真是觉得,也就是有参构造,
	好处:代理对象可以做很多真实对象做不了的事情;真实对象专注自己的事情
lambda表达式:JDK8才出来的,语法规则:(参数)->{重写的方法体}
	前提,必须是函数值接口:只含有一个方法的接口,并且这个唯一方法是抽象方法
	实质:函数式编程
	简化方式:1.参数的类型可以省略,也可不省略,一个参数的时候()可省略;多个参数的时候,返回值可以全部省去,要留就都留,要去掉就都去掉,但是必须加();2.当方法主体只有一句话的时候,可以省去{},否则,不许加上{}
线程五大状态:
	新生状态:new 线程类
	就绪状态:start()之后,进入就绪状态
	运行状态
	阻塞状态:sleep(),wait(),同步锁等等
	死亡状态,线程一旦中断或者死亡之后,不能重新start().,这能重新new 线程类之后,再重新start()启动
线程停止:
	1.不建议使用死循环,不建议使用已经过去的,或者jvm不推荐使用的方法
	2.最好的方法是让线程自己停止,一般是设置标志位,就是一个状态监听器
	3.不要使用stop(),destroy()灯过时方法
线程休眠:sleep()使用的时候不会释放锁
	网络延迟好处:方法问题的发生性
线程礼让:yield():
	定义:让当前执行的线程暂停,跟其他线程一样退回起跑线,从运行状态转为就绪状态,等待cpu调度
	特点:线程礼让不一定成功,看CPU心情
线程强制执行:join(),插队,强制执行
线程状态:getState();
	线程死亡之后,就不能再次start().必须重新new之后,才能再次开启
线程的优先级:获取优先级Thread.currentThread().getPriority(),设置优先级:Thread..setPriority(1);
	要先设置优先级,在获取
	范围是1~10,越大越快被调度 ,设置超出后,运行会报错
	main主线程,默认优先级是5,修改不了
	优先级高的等待优先级低的,会造成优先级倒置的问题,会影响性能
守护线程:daemon  thread.setDaemon(true);//默认是false,false是用户线程
	线程分为:守护线程用户线程
	虚拟机必须等待用户线程完毕
	虚拟机不必等待守护线程是否执行完毕
线程同步:synchronized
	并发:多个线程同时操作同一个对象
	锁机制:synchronized
线程锁(线程同步):synchronized
	分为:synchronized方法和synchronized块
	synchronized加到方法上,这个方法就是同步方法
	synchronized:默认锁的是本身,不用设定同步监视器,这里默认的是this
	synchronized块:语法:synchronized(Obj){},这里的Obj是同时监视器,obj可以是任何的对象,但是推荐使用共享资源作为同步监视器,j就是需要修改的对象,所以,前提是需要确定操作的对象哪个才是变化的本质
安全变成JUC:java1.5之后出现的工具包concurrent这个包效的方法,都是线程安全的,
	面试问题:HashMap和HashTable和concurrecntHashMap
					HashMap:继承了Map集合类,底层数组+链表,初始值为16,每次扩容在原先基础上的2次幂,插入数据的时候再判断是否扩容,线程不安全,线程安全的做法是锁住整个HashMap。
					HashTable:继承了Map集合类底层数组+链表,线程安全,初始值为11,每次扩容,原先基础上的2次幂+1,实现线程安全的方式是锁住整个HashTable()
					concurrentHashMap:继承了concurrentHashMap,底层分段数组+链表,线程安全,底层使用了锁分离技术,是的效率提升了默认16倍
死锁:多个线程互相抱着对方需要的资源,形成对峙的局面,就是死锁
	产生死锁的4个必要条件:1.互斥条件:一个资源只能被一个进程使用;2.请求与保持条件:一个进程因请求资源而阻塞,对以获得的资源保持不放;3.不剥夺条件:进程已获得的资源,在使用完之前,不进行剥夺;4.循环等待:若干进程之间形成收尾相连的循环等待资源关系
Lock锁:可重入锁:private final ReentrantLock lock=new ReentrantLock();
	源自concurrent工具类,是控制多个线程对共享资源进行访问的工具 
	步骤:1.声明锁 2.lock.lock()枷锁  3.枷锁之后协商方法体 4,最后执行lock.unlock()解锁
	一般用try{}catch(){}fially{},try中加锁finally中解锁。
	跟synchronized对比:1.ReentrantLock 是显示的锁,需要手动加锁和解锁,synchronized是隐式的锁;2.ReentrantLock只有代码块的锁,synchronized有方法锁和代码快锁;3.使用ReentrantLock锁的时候,jvm花费较少的时间来调度,性能好,并且有很好的扩展性,
	使用顺序推荐:Lock>同步代码块>同步方法 
线程通信:线程同步的问题:生产者和消费者共享同一线程,并且之间相互依赖,互为条件。
	sleep(时间):线程等待多长时间,在等待期间,会一直持有苏哦,不释放
	wait():线程一直等待,等待其他现车给通知,等待过程中会释放锁
	wait(long 时间):指定等待多长时间,
	notify():唤醒一个处于等待中的线程
	notifyAll():唤醒同一个对象上的所有调用wait()方法的线程,优先级别高的先调度
解决线程通信问题的方式1:
	管程法:利用缓冲区解决,线程之间的交流放在缓冲区,通过等待和唤醒来进行调度
	灯信号法:通过标志位切换,控制等待和唤醒操作
线程池:
	好处:1.提高响应速度,减少创建线程的时间;2.降低资源消耗,可以重复利用线程池中的线程,不需要每次都创建;3.便于线程管理
	步骤:1.ExecutorService executorService= Executors.newFixedThreadPool(10);,数字是这个线程池中有几个线程;2.executorService.execute(new MyThread());用这个方法来执行线程 ;3.executorService.shutdown();关闭服务
	
	
注解(Annotation)和反射(reflection):JDK5.0之后引入注解
	注解可以被其他程序读取
内置注解:
	@Override:重写的注解
	@Deprecated:已过时的注解,不推荐使用的但是是可以使用的,
	@SuppressWarnings:镇压警告,可放入参数
元注解:解释其他注解的注解
	@Target:用于描述注解的适用范围(即:被描述的注解可以用在什么地方)
	@Documented:说明该注解将被包含在javadoc中,表示是否将我们的注解生成在javadoc中
	@Inherited:说明子类可以继承父类中的该注解
	@Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期,rumtime(运行的任何时候都有效)>class(只在类有效)>source(只在源码有效)
自定义注解:语法:@interface
	格式:@Target(value= {ElementType.METHOD,ElementType.TYPE})//这个自定义的注解必须放在类和或者方法上
			@Retention(RetentionPolicy.RUNTIME)  //在任何时候都有效
 			@interface MyAnnotation{
					String name  default;//注解的参数:参数类型+参数名();default有默认值,如果没有这个,则用这个注解的时候,必须加参数
				}
		注意:当只有一个参数的时候,建议参数名为value
反射(reflection):
	正常方式:引入包-->通过new 实例化-->  获取类的对象
	反射:实例化对象--> getClass方法-->获得完整的的类对象
反射的作用:
	1.在运行时判断任何一个对象所属的类;、
	2.在运行的时候,构造任意对象的类;
	3.运行时,判断任何一个类所具有的成员变量和方法;
	4.运行时获取泛型信息;
	5.在运行时调用任何一个对象的成员变量和方法;
	6.运行时处理注解;
	7.生成动态代理
反射的优缺点:
	优点:可以实现动态创建对象和编译,体现出很大的灵活性
	缺点:对性能有影响;使用反射其实是一种解释操作,这类的操作总是慢于直接执行相同的操作 
一个类在内存中,只有一个class对象,因此,hashCode是固定的
一个类被加载后,类的整个结构都封装在class的对象中
class类的创建方式
	1.通过对象:new 类名.getClass()
	2.通过forname:Class.forName(包名+类名);绝对路径
	3.通过类名:类名.class:
	4.基本内置类型的包装类都有一个type:Integer.type;不是没个类都有的
类记载内存分析:
	加载:将class字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个了的java.lang.Class对象;因为,只有在加载的时候,才能生成这个类,我们只能获取,不能自己造
	链接:将java类的二进制代码合并到JVM的运行状态之中的过程
		验证:确保加载的类信息符合JVM的规范,没有安全方面的问题
		准备:正式为类变量static分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配
		解析:虚拟机常量池中内的符号引用(常量名)替换为直接引用(地址)的过程
	初始化:
			执行类构造器<clinit>()方法的过程,类构造器方法是由编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的
			当初始化一个类的时候,若是发现其父类还没有初始化,则需要先触发其父类的初始化
			虚拟机会保证一个类的构造器方法在多线程中被正确的加锁和同步
类加载器:
	java的核心包:rt.jar;路径:jdk--jre--lib--rt.jarx
	获取系统类加载器的方式:ClassLoader ststemClassLoader=ClassLoader.getSystemClassLoader();
	获取系统类加载器的父类(扩展类加载器):ClassLoader parent=ststemClassLoader.getParent();
	获取扩展类加载器的父类加载器(根加载器):ClassLoader parent1=parent.getParent();\
	获取系统类加载器可以加载的路径:System.getProperty("java.class.path")
双亲委派机制:就是当你自己定义了一个类,类加载的时候,会父类去找,如果,父类中有一类是跟你的类一摸一样,你的类,就不会生效,就比如,你自己写一个java.lang.Object的类,就不会生效,这个是个安全机制
类的反射能做什么:
	1.通过反射,获取一个类的对象(与new一样):Calss.newInstance();这个方法本身就是调用无参构造
	2.通过构造器获取对象:Class.getDeclaredConstructor(String.class,int.class);需要string的参数,就传String.class等等;然后再Calss.newInstance()传入想穿的参数,就可以创建一个新的对象了
	3.怎么通过反射调用里面的方法:通过反射获取一个方法;然后 方法.invoke(对象,值);就可以激活这个方法了,然后对象就可以使用了
	4.通过反射不能操作私有属性,需要获取属性之后,先关闭安全检测(属性.setAccessible(true)//true是关闭)才能使用		
spring
优点:1.开源  2.轻量级的,非入侵式的 3.控制反转(IOC)和面向切面(AOP)  4.支持事务,对框架的整合
总结:spring是一个轻量级的控制反转和面向切面编程的框架  
组成:7大模块,网上有

IOC理论推到:
实现IOC的方式L:
	1.xml配置
	2.注解
	3.自动装配
DI(依赖注入):本质是set注入
IOC创建对象的方式:
	1.采用无参构造(默认)
	2.有参构造:
		有参构造方式1:采用下标的方式: <constructor-arg index="0" value="我爱小红"/>  有参构造的第一个值,并且赋值,多个参数的时候,继续网上加
		参数类型如复制(不建议使用,因为:如果两个参数都是String的,或者别的一样的,就没办法表示了):采用参数类型赋值:<constructor-arg type="java.lang.String" value="我爱小红"/>
		通过引用别的类:<constructor-arg ref="beanTwo"/>  这里的beanTw是bean容器中定义好的类
		通过名称:<constructor-arg name="name" value="我爱小红"/> 构造函数传的值是什么,这个就些什么,比如这里的name
	总结:再配置文件加载的时候,容器中管理的对象就全部被初始化了
spring配置:
	别名:alias:<alias name="user" alias="sdad"></alias>就是给user起个别名,获取bean的时候可以使用
	bean:id:就是bean的唯一标识符,也就是对象名,class:类的路径;name:bean中的那么也是别名的意思,可以同时起多个别名,按逗号或者空格或者分号分开,比如 name="name1,name2..."
	import:一般用于团队开发,它可以将多个配置文件导入合并为1个;<import resource="beans.xml"></import>

依赖注入的方式:
	1.构造器注入
	2.set注入(set):本质
		依赖:bean对象的创建依赖于容器
		注入:	bean对象的所有的属性,都由容器来注入
		1.普通值注入:<property name="name" value="小红"></property>
		2.引用类型注入:<property name="address" ref="address"></property>
		3.Map注入:
			<property name="card">
	            <map>
	                <entry key="身份证" value="619191626496266320"></entry>
	                <entry key="银行卡" value="526262364603603160303"></entry>
	            </map>
        	</property>
		4.数组注入:
			<property name="books">
	            <array>
	                <value>红楼梦</value>
	                <value>西游记</value>
	                <value>水浒传</value>
	                <value>三国演义</value>
	            </array>
	        </property>
		5.list注入:
			<property name="hobbys">
	            <list>
	                <value>听歌</value>
	            </list>
        	</property>
		6.set注入:
			<property name="games">
	            <set>
	                <value>LOL</value>
	                <value>BOB</value>
	                <value>COC</value>
	            </set>
        	</property>
       7.null值设定:
	       	<property name="wife">
	            <null></null>
	        </property>
	p/c命名空间:
		1。都需要第三方约束:需要再上方beans一个电放约束
		2.p命名空间:主要是set注入:p=property,主要是给属性赋值,语法规则:p:属性=值
		3.c命名空间:主要是构造函数注入,c=constructor-arg;前提必须有有参构造:语法规则:c:属性(_ref)=值(引用)
bean的作用域:
	关键字:scope,默认的是单例
	单例模式:singleton;每次从容器中获取一个类的时候,不管获取几次,都用的是同一个bean
	原型:prototype;每次从容器中获取一个类,都会创建一个新的类
	其余的类型:request.session,application都只能使用在web开发中。
bean的自动装配
	自动状态是spring满足bean依赖的一种方式!
	 spring会在上下文中自动寻找,并自动给bean装配。
	 spring的三种装配方式:1.xml配置;2.java中显示配置;3.隐式的自动装配(重点重点)
	 autowire="byName":自动装配,自动在上下文寻找当前类中set方法后面相对应的bean的id,前提必须保证bean的id必须存在,并且唯一,并且这个bean需要和自动注入的属性set方法一致。
	 autowire="byType":自动装配,自动在上下文寻找当前类跟属性相对应的bean的id,前提是该类型必须全局唯一,bean中的class必循存在并且唯一,id有没有都一样,并且这个bean需要和自动注入的属性的类型一致
使用注解自动装配:
	1.导入约束:context关于上下文的约束
	2.配置注解的支持:<context:annotation-config/>
	3.@Autowire:1.直接在属性上使用,或者set方式上使用;2.使用这个注解我们可以不应编写set方法了,前提是你这个自动装配的属性在spring容器中存在,且符合ByName的命名规则
	4.科普:@Autowired(required = false),这个注解对象可以为空,否则不可以为空,required默认为true
		如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解完成的时候,我们可以使用 @Qualifier(value = "xxx")配合使用,xxx是指定的唯一的bean的id,意思是指定唯一的bean注入。
		@Resource也可以实现自动装配,但前提是spring容器中的bean是唯一的,,要么bean的id唯一,要么bean的class唯一,否则,需要 @Resource(name = "xxx")来通过name=bean的id指定唯一的bean
		@Autowired和@Resource异同点:
			1.都是用来自动装配的,都可以放在属性字段上
			2.@Autowired默认是通过byType的方式实现的,而且必须要求这个对象必须存在
				@Resource默认是通过ByName的方式实现的,如果找不到名字,则通过ByType的方式实现,如果两个都找不到,报错
			3.执行顺序不同:@Autowired通过byType执行
使用注解开发:
	在spring4之后,要只用注解开发,必须要保证AOP包的导入
	还用注解需要导入context约束,增加注解的支持
	1.@Component  //组件:等价于在xml文件中:<bean id="user" class="com.kuang.pojo.User"></bean>,放在类上,说明这个类被spring管理了;@value(“值”),赋值,与@Component配和使用
	@service:代表将这个类给spring管理 
	@Controller:代表将这个类给spring管理
小结;
	xml与注解:
		xml更加万能,适用于任何场合,维护简单方便
		注解不是自己的类,不能使用,维护相对复杂
	xml与注解的最佳实践:
		xml用来管理bean
		注解只负责完成属性的注入
	我们在使用d的过程中,只需要著一个问题:必须让注解生效,就需要开启注解的支持	
拓展(纯java配置的注解):@Configurable
	@Configurable注解的类,算是一个配置文件,相当于xml文件;这个类里面的一些方法用@Bean注解,这个相当一声明了一个bean,跟xml文件是一样的,
	测试的时候: ApplicationContext context = new AnnotationConfigApplicationContext(KuangConfig.class)的方式获取值,KuangConfig.class就是@Configurable注解的类.class,User user = context.getBean("getUser", User.class);getUser是@Bean注解的方法的方法名。
代理模式:
	为什么要学习代理模式:因为这是springAop的底层
	代理模式分类:
		静态代理:角色分析:1.抽象角色,代理角色和被代理的角色需要做的事情,一般用接口或者抽象类来实现;2.真实觉得,比如租房中的房东;3.代理角色:比如租房中的中介公司  4.访问者,比如我要租房中的我 
		静态代理代码步骤:1.接口;2.真实觉得;3.代理角色;4.客户端访问代理角色
		静态代理的好处:1.可以使真实觉得业务更加纯粹,不用去管公共的业务;2.公共哦那个业务交给代理模式,实现了业务的分工;3.公共业务发生扩展的时候,方便集中
		静态代理的缺点:一个真实角色,就会产生一个代理,多个真实的角色的时候,代码量就会翻好几倍.
	动态代理: 角色分析:跟静态代理一样,动态代理的代理类是动态生成的,不是我们直接写好的
		动态代理分为两大类:1.基于接口的动态代理;2.基于类的动态代理
			基于接口的:JDK原生的动态代理
			基于类:cglib类
			java字节码码实现:javasist
		JDK原生的动态代理:
			认识两个类:proxy(代理);InvocationHandler(调用处理程序),必须要这两个类
			自动生成代理的的程序:格式可以说是死的,重点在理解

				public class PorxyInvocationHandler implements InvocationHandler { //一个类实现InvocationHandler,重写invoke方法
					private Object target;  //代理的对象,也就是真实角色
					
					public void setTarget(Object target) {//塞入数据。塞入真实角色,实现代理的功效
					    this.target = target;
					}
					//生成得到的代理类
					public Object getProxy(){   //生成代理类
					    return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
					}
					
					//处理代理实例,并返回结果
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
					    //
					    log(method.getName());  //利用了反射
					    Object result = method.invoke(target, args);
					    return result;
					}
					
					public void log(String type){
					    System.out.println("实现了"+type+"的方法");
					}
				}
			访问程序:
				UserServiceImpl userService=new UserServiceImpl();  //真实觉得

		        PorxyInvocationHandler porxyInvocationHandler=new PorxyInvocationHandler();  
		        porxyInvocationHandler.setTarget(userService);   //塞入真实角色
		        UserService userService1= (UserService) porxyInvocationHandler.getProxy();  //动态生成代理类
		        userService1.add();  //  执行方法
		动态代理的好处:
			1.可以使真实觉得业务更加纯粹,不用去管公共的业务;2.公共哦那个业务交给代理模式,实现了业务的分工;3.公共业务发生扩展的时候,方便集中;4.一动态代理类代理的是一个接口,一般就是一类业务;5.一个动态代理可以代理多个类,只要是实现接口就可以了
Aop:导入包:org.aspectj:aspectjweaver
	方式1:使用spring的API接口:方法中需要实导入Aop的包
		前置方法:实现MethodBeforeAdvice接口,重写before:参数意义://method:要执行的方法; //args:参数;//target:目标对象
		后置方法:实现AfterReturningAdvice/AfterAdvice接口,两者的差别是一个有返回值,一个没有,其他类型都跟前置方法一样
		xml中的aop配置:
				<!--方式1:-->
				    <!--配置aop:需要导入aop的约束-->
				    <aop:config>
				        <!--配置切入点,id="起的名字",expression="表达式":表达式的意思:要执行的位置;格式:execution(public 返回值 类名 方法名 参数)-->
				        <aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/><!--这里的意义是:com.kuang.service.UserServiceImpl类下的所有方法,任意参数-->
				        <!--执行环绕-->
				        <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>  <!--在id="pointcut"的位置,执行环绕方法-->
				        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
				    </aop:config>
		总结:动态代理代理的是接口,不是实现类,所以,当你代理实现类的时候,就会报错
	方式2:使用自定义类来实现(常用)
	前置方法和后置方法都需要自己写,自定义
	xml配置文件:
		<bean id="diy" class="com.kuang.diy.DiyPointCut"/>   //自定义的类
	    <aop:config>
	        <!--自定义切面:要用ref要引用类-->
	        <aop:aspect ref="diy">
	            <!--切入点-->
	            <aop:pointcut id="point" expression="execution(* com.kuang.service.UserServiceImpl.*(..))" />
	            <aop:before method="before" pointcut-ref="point"/>  //自定义的前置方法
	            <aop:after method="after" pointcut-ref="point"/>  //自定义的后置方法
	        </aop:aspect>
	    </aop:config>
	 方式3:使用注解
	 	例子:切面程序
	 		@Aspect    //定义这个是切入点
			public class AnnotationPointcut {
			
			    @Before("execution(* com.kuang.service.UserServiceImpl.*(..))")   //方法执行的位置
			    public void before(){
			        System.out.println("方法执行前============");
			    }
			    @After("execution(* com.kuang.service.UserServiceImpl.*(..))")   //方法执行的位置
			    public void after(){
			        System.out.println("方法执行后=================");
			    }
			
			    @Around("execution(* com.kuang.service.UserServiceImpl.*(..))")
			    public void arount(ProceedingJoinPoint point) throws Throwable { //环绕
			        System.out.println("环绕前");
			        Object proceed = point.proceed();   //真实的方法执行
			        System.out.println("环绕后");
			
			    }
			}
		xml文件配置:
			<!--方式3:-->
		    <bean id="annotationPointcut" class="com.kuang.diy.AnnotationPointcut"/>
		    <aop:aspectj-autoproxy/>  <!--开启aop注解 proxy-target-class不写的时候,默认的是false,也就是JDK远程的动态代理,true的时候,是cglib类的动态代理-->
	
事务:
	ACID原则:
	1.原子性:确保要么都成功要么都失败
	2.一致性:事务一旦完成,要么都提交,要么都不提交,状态一直保持一致
	3.隔离性:多个业务操作同一个资源,互不干扰,防止数据损坏
	4.持久性:事务一旦提交,无论系统发生什么,结果都不会被影响,被持久化的写道存储器中
事务的隔离机制:
       读未提交   读已提交     可重复读   串行化
spring 中的事务管理:
	声明式事务:AOP 
	编程时事务:需要在代码中,进行事务管理
Docker:	
	概述:解决项目上线的问题,就是解决了,上线的时候,又要部署项目,又要配置项目运行的环境的事情,用Docker之后,项目开发完成之后,打包装箱,连带运行环境都打包进去,这样的话,只需要下载打好的包,就可以直接运行了,类似于手机应用商店下载软件,安装即可使用,通过一种隔离机制,把服务器压榨到极致
		官网logo解析:灵感来源于集装箱,就是互相可以运行,互补干扰,相当于应用上商店。
		官网地址:https://www.docker/
		文档地址:https://docs.docker/  超详细
		仓库地址:https://hub.docker/
	安装:
		镜像(image):docker镜像就好比一个模板,可以通过这个模板来创建容器服务,比如tomcat镜像(镜像是不能启动的,只有运行起来,才能启动),这个镜像运行起来之后,就相当于一个容器服务,tomcat服务(提供具体的容器);通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)
		容器(container)::Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的;基本命令:启动,停止,删除等等
		仓库(repository):存放镜像的地方,有共有仓库和私有仓库,官方Docker.hub,默认是国外的,国内也有,比如阿里云等等的,但是需要配置镜像加速
	命令:
		镜像命令:
		容器命令:
		操作命令
	Docker镜像(重点):
	容器数据卷(重点)
	DocherFile:
	Docher网络原理:
	IDEA整理Docker:
	Docker Compose:
	Docker Swarm
	CD/CI jenkins:
limit分页查询:
	limit 参数1 ,参数2
			参数1:偏移量,一般是:页码*每页的数据量
			参数2:每页的数据量
索引失效:
	like下:
		like %**  失效
		like  **% 有效
		like %**%  失效
	范围:betwen   、and 、or等
	is null  或者  is not null
	< > !=的时候
	
javaWeb
	tomcat:面试题:谈谈网站是如何访问的? 答案:1.输入域名,回车;2.发送一个请求;3.检查本机的host文件夹中有没有这个域名的配置,有直接返回d对应的ip地址,如果没有,就去DNS(全世界的域名都在这里)上去找,找到返回ip,获取相应的响应返回到客户端。找不到,就报找不到的错误。
	修改端口:
		<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
     默认访问的位置:部署的时候,需要把文件放到tomcat的这个目录下,访问的时候,直接加地址就可以了
     	<Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
	tomcat默认端口号:8080
	http默认端口号:80:
	https默认的端口号:443
	mysql:3301
	orclae:1521
servlet:
	就是sun公司开发动态web的一门技术
	sun公司提供了一个接口:servlet,编写servlet的程序只需要两步:
		1.写一个java类,实现servlet接口
		2.把写好的java类部署到程序中,就可以了
	具体步骤如下:
		1.写一个java类,继承(extends)HttpServlet接口,就可以了,这是因为HttpServlet已经实现了servlet这个接口了,
		2.重写doGet方法和doPsot方法,因为这两个是最重要的方法体,需要实现我们具体的业务
		3.写servlet的映射(其实就是配置文件,web.xml),具体实现如下
			<servlet>  //注册servlet
        		<servlet-name>AppUploadFile</servlet-name>   //自己起的名字,但是必须跟下面的名字一摸一样
        		<servlet-class>org.zyyd.base.servlet.AppUploadFile</servlet-class>   //需要访问的方法
   		 	</servlet>
    		<servlet-mapping>   //servlet的路径请求
		        <servlet-name>AppUploadFile</servlet-name>  //跟上面的名字一致
        		<url-pattern>/appUploadFile</url-pattern>   //访问的时候的请求路径
    		</servlet-mapping>
    	4.配置tomcat
    	5.启动测试
    servlet原理:
    	浏览器发送http请求到web服务器,然后web服务器会根据请求头(request)的信息,调用servlet方法中的service方法(这里面是的doGet方法和doPsot方法是自己实现的方法),这样就得到相应的数据,然后放在响应中(response),这样响应信息会被web服务器读取到,然后,然会给浏览器,这样,浏览器就获取到响应的数据了。
    映射中的mapping问题:主要是*的应用
    	1个servlet可以指定一个映射
    	1个servlet可以指定多个映射
    	一个servlet可以指定通用映射
    	1个servlet可以指定前缀或者后缀
    servletContext:
    	web容器在启动的时候,会给每个web程序都创建一个对应的servletContext,他代表了当前的web应用
    		作用:
    			1.共享数据:我在这个sevlet的值,可以在另一个servlet中使用
    			2.先要setAttribute()。塞入数据,然后再通过getAttribute获取
springmvc知识点:
	mvc:模型(model,service),视图(jsp)  控制层(servlet)

springmvc执行原理:整个都是围绕dispatcherServlet展开的
	1.用户通过浏览器发送请求,先会到调度器dispatcherServlet
	2.然后dispatcherServlet调用handlerMapping处理器映射器
	3.处理器映射器找到对应的处理器,返回给dispatcherServlet
	4.dispatcherServlet调用handleraddpter处理器适配器
	5.处理器是配置经过适配调用对应的controller
	6.controller执行完成之后生成modelAndView,;
	7.handleraddpter把croller生成的modelAndView传给dispatcherServlet
	8.dispatcherServlet把modelAndView传给试图解析器ViewReslover
	9.ViewReslover解析后返回view;
	10.dispatcherServlet根据view进行视图渲染
	11.dispatcherServlet响应客户
javaWeb运行的顺序:浏览器输入地址,点击回车,先会走web.xml,从上往下走,然后会根据web.xml的配置,首先进去响应的程序,比如dispatcherServlet,然后才会分配到响应的controller上执行代码
面试:
	mybatis原理:
		通过sqlSesstionFactionBuilder的build方法,获取到sqlSessionFaction,然后在获取到sqlSession,调用sql执行,然后关闭关闭
微服务阶段:
	springboot:
		1.springboot所有的依赖,都是使用spring-boot-starter-这个开头的
		2.自动装配的原理:
			总结:springboot所有的自动配置都是在启动的时候扫描并加载:spring.factories,所有的自动配置类都在这里面,但是不一定生效,所以,要判断条件是否成立,只需要导入对应的start,就有了对应的启动器,有了启动器,我们的自动装配就会生效,然后就配置成功了
				精髓:
					1.springboot启动会加载大量的自动装配的类(xxxAutoConfiguration:自动装配的类)
					2.我们看我们需要的东西是不是在springboot默认写好的自动装配的类中,如果,我们直接可以动态修改,如果没有,我需要我们手动写
					3.给容器中自动配置的类中添加组件的时候,会从欧冠properties类中获取某些属性值,我们只需要动他修改就好了
					4.xxxAutoConfigurartion:自动配置的类,给容器中添加组件;xxxproperties:封装配置文件中的相关属性
			pom.xml:spring-boot-dependencies 核心依赖在父工程中(版本管理)
					1.<parent>
					        <groupId>org.springframework.boot</groupId>
					        <artifactId>spring-boot-starter-parent</artifactId>
					        <version>2.3.4.RELEASE</version>
					        <relativePath/> <!-- lookup parent from repository -->
					    </parent>
					    我们在写或者引入一些springboot依赖的时候,不需要指定版本,就是因为有这个版本仓库,直接调用即可
		启动器:
				<dependency>  javaweb的驱动器
		            <groupId>org.springframework.boot</groupId>
		            <artifactId>spring-boot-starter-web</artifactId>
	        </dependency>
	        说白了就是springboot使用的场景,比如上面的web环境的启动器
	        springboot会将所有的场景都变成一个个的启动器
	        如果我们需要什么功能,就只需要找到相应的启动器就可以了
	    主程序
	    	注解:@SpringBootApplication  表明这个类是springboot应用
	    		@SpringBootConfiguration
				@EnableAutoConfiguration
	    	启动:SpringApplication.run(Springboot01HelloworldApplication.class, args)  将springboot应用启动
	   在springboot中,我们可以使用以下方式可以处理静态资源:
	   		webjars
	   		resource-->public:   优先级最后
	   		resource-->static:  优先级第二(默认)
	   		resource-->resource:	  优先级最高
	   		一旦在配置文件中设定了目录:上面说的几种方式,全部失效
	   	springboot中配文件的位置:
	   		file./config/ (项目路径下创建config,放配置文件):  优先级1 
	   		file. (项目下直接放配置文件): 优先级2
	   		classpath./config (resource下创建config,放配置文件): 优先级3
	   		classpath:(resource下放配置文件)  优先级4
springboot中创建一个拦截器:不需要重新添加依赖
	步骤1:手写一个类,实现handalerInterceptor,重写prehandler方法,renturn true 就是放行,return false就是拦截
		重写的prehandler方法中就是自己的手写实现类,
		步骤2:手写一个类,实现WebMvcConfigurer接口,并用@configuration注解,重写addInterceptors方法,然后里面配置拦截什么,放行什么,就可以了
		







	 RPC:远程过程调用,是一种进程间通信方式,使用哦个rpc是因为无法再一个进程内甚至无法在一个计算机内通过本地d调用d的方式完成需求,比如不同的系统间d的通讯,甚至不同组织间的通信,由于计算能力需要横向扩展,需要在多态机器组成的集群上部署应用。RPC就是要像调用本地函数一样去调远程函数
	 RPC的核心重点:通讯,序列化(方便数据传输)  
	 dubbo就是一种RPC;
	 zookeeper:就是一个分布式应用程序协调服务:默认端口:2181
	 	 dubbo-admin:监控管办理后台,可以查看信息,默认端口7001
redis存储的数据类型:String、set、list、hash、sort set
redis 主从复制:是指把一个redis服务器的数据,复制到其他redis服务器上,前者为主(master/leader),后者为从(slave/follower),必须是单向复制,必须是从主复制到从,主以写为主,从为读
	作用:
		数据冗余:实现热备份,是持久化的一种数据冗余方式
		故障恢复:当主节点出现故障的时候,可以由从节点提供服务,实现快速回复故障,实际上是一种服务的冗余
		负载均衡:再主从复制的基础上,配合读写分离,可以由直接点一共写服务,从节点提供读的服务,分担服务器负载,尤其是写少读多的场景下,通过多个从节点分担读负载,可以大大提高redis服务器的并发量
		高可用基石:主从复制还是哨兵和集群能够实施的基础。
	注意:
		默认情况下,每个redis服务器都是主节点,
		一个主节点可以有多个从节点,但是一个从节点只能有1个主节点。
	命令:
		拷贝:cp redis.conf  语法:cp  原文件名 复制后文件的名
		redis启动:redis-server redis.conf
		进入redis服务的命令 redis-cli -p 6379  语法:redis-cli -p 端口
		查看当前服务的状态:info replication
	配置主从复制的方式1:通过命令配置
	主机79  --从机80
				--从机81
		步骤
			1.需要准备多个redis服务,cp命令
			2.修改各自的配置信息:redis.conf
				vim redis.conf命令进去详情配置
				需要该的参数:
					端口:port 6379  修改成自己的端口就好了
					后台开启:daemonize yes 
					pidfile:pidfile /var/run/redis_6379.pid  改成自己的名字
					日志:logfile ""  改成自己想要的  比如:logfile "6379.log"
					dbfilename:dbfilename dump.rdb  改成自己想要名字  比如:dbfilename dump6379.rdb
			3.配置从机:
				命令:SLAVEOF 127.0.0.1 6379	语法:SLAVEOF 主机的IP  主机的端口
		主从复制的配置方式2:配饰文件配置
			步骤:
				1.命令vim redis.conf  进去找到
					# replicaof <masterip> <masterport>  masterip:主机的端ip masterport:主机的端口
					及
					# masterauth <master-password>   master-password  主机的密码
			细节:
				1.主机可以写,从机只能读不能够写,主机中所有的信息和数据,都会自动被从机保存,从机写会报错
				2.主机断开,从机依旧能够链接到主机,依旧只有读的操作,这个时候主机回来了,从机能自动链接到主机上
				3.从机断开了,主机下少一个从机,这个时候从机回来了,这个时候,断开的从机默认为主机(配置文件配置之后起来还是从机)
				4。主机新增的从机,立刻就会从主机中获取值
			概念:
				从机启动成功之后链接到一个主机,会发用一个同步命令,主机接到命令之后,启动后台的存盘进程,同时收集所有接受到的用于修改数据集的命令,在后台进程执行完毕之后,主机将传送所有整个数据文件到从机,并完成一次完全能同步
				全量复制:从机服务在接收到数据库文件数据后,将其存盘并加载到内存中
				增量复制:主机继续将新的所有收集到的修改命令一次传给从机,完成同步
			但是只要是重新链接主机,一次完全同步(全量复制)将被自动执行。
主从复制方式2:
  主机7)----从机80(79的从机,81的主机)---从机81(80的从机)
  
	如果没有主机了或者主机挂掉了怎么办:
	命令:SLAVEOF no one :设置自己为主机,需要手动
哨兵模式:
	原理:哨兵通过发送命令,等待redis服务器响应,从而监控运行多个redis实例
	好处:会通过监听情况,自动把从机转化成主机
	实现过程:
		假设主机宕机,这个时候哨兵检测到这个结果之后,并不会立刻进行投票,而是认为主机不可用,这个情况被成为主观线下线,当后面的哨兵也发现这个主机死亡之后,并且数量达到一定的时候,那么哨兵之间就会进行一次投票,有其中的一个哨兵发起,进行故障转移,就是要在剩余的从机中选择一个当主机,之前的主机就不用了,新主机产生,这个过程被成为客观下线。
	集群搭建:
		配置哨兵:
			建立哨兵扫描文件: vim sentinel.conf
				sentinel monitor myredis 127.0.0.1 6379  1 语法:sentinel monitor 自己起名字 监控的主机ip  监控的主机端口 1:代表主机挂掉回去投票选另外的主机
		启动哨兵:redis-sentinel sentinel.conf,就可以了
		注意:如果说主机挂掉,选出另外的主机,这个时候,之前的主机修好了,只能当当前主机的从机
		哨兵模式默认延迟30秒;
	哨兵模式的优点:
		1.哨兵集群,基于主从复制模式,主从模式的优点他都有
		2.主从却换,故障转移,增加系统的可用性
		3.主从模式的升级,从手动变成自动,更加健壮
	缺点:
		1.redis不好在线扩容,集群容量一旦达到上线,在线扩容j就十分麻烦
		2.哨兵模式配置麻烦,里面有很多选择
		

	缓存穿透:redis没有,数据库有没有,大量的访问访问数据库,造成程序瘫痪
		解决办法:1.查询到空值,存一个空值,缺点就是空值太多也不好
			2.布隆过滤器,收集到空的可能情况,存起来,然后进行校验,不符合丢弃 
	redis击穿:热点数据访问量大,在失效的瞬间,数据库的压力会瞬间增大,造成程序瘫痪
		解决办法:1.热点设置不过期,缺点:太多了的话占空间
			2.加锁,在缓存和数据库之间,加锁,同一时间只能保证有一个线程可以访问,其余的等待
	redis雪崩:大量数据在同一时间段过期,数据库访问量加大,造成程序瘫痪
		解决办法:1.过期时间随机化 
redis高可用的解决办法:
	1.加服务器,异地多活
	2.限流降级:通过枷锁或者队列来控制数据库写缓存的线程数量,
	3.数据预热,就是先把可能的数据加载到缓存中
	4.过期时间设置成随机,不要让在同一时间过期。	
dubbo+zookeeper+springboot;
	前提:zookeeper服务已开启
	1.提供者提供服务,
		1.导入依赖,
		2.配置注册中心的地址,以及服务发现名,和扫描的包;如下:
			发现名:dubbo.application.name=自己的名字
			注册中心的地址:dubbo.registry.adress=zookeeper://ip:端口
			扫描的包:dubbo.scan.base-packages=包的路径
		3.在想要被注册的服务上面增加注解 @Service  一定要是dubbo的service
	2.消费者如何消费
		1.导入依赖,跟上面一样的依赖
		2.配置注册中心的地址,配置自己的服务名
			发现名:dubbo.application.name=自己的名字
			注册中心的地址:dubbo.registry.adress=zookeeper://ip:端口
		3.从远程注入服务  @Reference 
	注意:@Component  把主机的类放到容器中
jvm知识:
	方法区:存 static 、final、class类信息、常量池。被所有线程共享。
	栈:存  8种基本类型、对象的引用、实例之后点的方法
		栈的作用:主管程序的运行,生命周期和线程同步,一旦线程结束,栈就结束了
		栈运行原理:栈帧
	堆:一个jvm只有一个堆内存
		类的运行回收:类首先诞生在新生区,比如,伊甸园区有10个空间,然后存了10个实例,这个时候,满了,出发轻GC,结果只有一个存活,存活的这个,会移动到幸存区中,这个时候,伊甸园区还剩9个空间,当伊甸园区和幸存区都满了之后,执行重GC,存活下来的,进入到养老区,当新生去和养老区都满了之后,程序报堆内存满的异常 
		新生区:
			伊甸园:
			幸存区(form区和to区):from区和to区是不停的交换的,to区一直为空,负责复制实例到from区中
			养老区:
			永久存储区:主要存储JDK自身携带的clss对象和包括一些接口数据,其实存储的是java运行时的一些环境。,这个区域不存在垃圾回收,关闭虚拟机就会释放这个区域的内存。
				异常的类型:
					一个启动类加载了大量的第三方jar包,
					tomcat部署了太多的应用了
					大量动态生成的反射类,不段的被加载,知道内存满了
		永久存储区时代区分:
			jdk1.6:名字叫永久代,常量池实在方法区中
			jdk1.7:名字叫永久代,但是慢慢退化成  去永久代了,常量池在堆中
			jdk1.8:名字叫原空间,常量池在原空间之中
			
	naive本地方法:凡是带有这个关键字的,说明java的作用范围达不到了,会调用底层C语言的库。胡进入本地栈,调用本地方法的接口(JNi)
		JNI的作用:拓展java的使用,融合不同的语言为java所用
		在内存中专门开辟了一快标记区域,就是本地方法栈,在最终被执行的时候,加载本地方法库中的方法通过JNI接口
	PC寄存器(程序计数器):没个线程都有一个程序计数器	
垃圾回收机制GC:
	主要i发生在新生区和养老去,更细分是伊甸园区和养老区
	轻GC:内存没满的时候,是轻GC
	重GC:内存满的,执行这个
	GC算法:
		标记清除算法:第一次扫描,如果有引用就证明活着呢,然后标记,第二次扫描,把没有被标记的,清除
			缺点:2次扫描,消耗大,会留下内存碎片,因为清除之后的内存是空下来的,浪费资源
			好处:不需要额外的空间
		标记压缩法:
			第一次扫描,如果有引用就证明活着呢,然后标记,第二次扫描,把没有被标记的,清除,第三次扫描,把存活的内存往一端移动,消除内存碎片
			好处:优化了标记清清除算法,没有内存碎片。
			缺点:3次扫描,浪费时间,
		复制算法(新生代主要用复制算法):谁空谁是to
			每次GC都会将活的实例,移到i幸村区中:一但伊甸园区被GC后,就是空的,每次GC之后,幸村区都有一个是空的,也就是to区,一般默认经过15次GC之后还能存活,就是进去养老区(可以通过参数设置)。
		引用计数器算法:、
			给每个对象分一个计数器,每个对象被调用1次,就记为1,为0的就会被清除
			缺点: 分配计数器也是一种成本,每次计数也是一种消耗		


jvm调优:
	1.参数调优,idea中的代码添加命令如下:
		-Xms1024m -Xmx1024m -XX: +PrintGCDetails   解释:初始内存和总内存都改成1024了,并且控制台打印的时候,会打印出GC清理的过程      语法规则:-Xms数字4m -Xmx数字m -XX: +PrintGCDetails
		-Xms:这是初始化内存分配大小,默认是64分之1
		-Xmx:设置最大分配内存,默认是4分之1
	2.如果调了参数还是报错,我们需要专业的工具检查代码的编写是不是有错误  专业的工具:MAT(eclipse集成),Jprofile
		 Jprofile之类的工具作用:快速分析Dump文件,埃苏定位内存泄漏问题
		 	获取到堆中的数据,获得大的数据对象
		 步骤:idea下载插件重启,启动之后在插件位置的却动选中bin目录下的Jprofile.exe文件,确定
		 命令:-XX:+HeapDumpOnOutOfMemoryError  解释:当发生堆内存异常的时候,把dump文件拷出来一份,
		 控制台会打印出拷出来的文件名,找到就可以了(一般情况实在根目录下),双击打开据可以了,然后分析
TCP/Ip知识点记录
应用层    //http协议,ftp协议等等
表示层
会话层
传输层         //TCP/UDP 协议         
网络层         //ip
数据联络层    //以太网协议头,并进行CRC编码,为最后的数据传输做准备。
物理层        //电压,物理机等等
IP:一种无状态(通信双方信息不同步,简单,高效)、无连接(不会提前连接,所以,每次都带着目的地址)、不可靠(不保证传到,只是尽最大努力)的协议。httph和udp协议很类似。
进制
十进制  example: 975.36  可以表示为:9*10^2+7*10^1+5*10^0+3*10^-1+6*10^-2
	总结:以小数点分割,整数越往左,*10^X中的X越大,从0开始,小数部分越往右,*10^X中的X越小,从-1开始,这里的10就是权重  10^2是位权,+是连接,并不是加法运算,9/7/5/3/6 这些叫做基数。比如二进制,只有0/1两个基数
		二进制也是类似,比如  01.1   0*2^1+1*2^0+1*2^-1

本文标签: 基础知识