Java基础
1.八种基础数据类型
byte、int、short、long
float、double
char、布尔
2.封装、继承、多态
封装:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。
好处:重用、安全、不用关心具体实现
继承:类与类的一种关系,子类拥有父类的所有属性和方法(除了private修饰的属性不能拥有)从而实现了实现代码的复用。
多态:事物在运行过程中存在不同的状态。
多态的存在有三个前提:
1.要有继承关系
2.子类要重写父类的方法
3.父类引用指向子类对象
二、基本数据类型和封装类的区别
1.包装类型可以为 null,而基本类型不可以
基本数据是变量,封装类是对象
类 对象
不能 能序列化
不需 需要new对象
== equals比较大小
值传递 地址传递
三、String、StringBuffer、StringBuilder区别
1.String为字符串常量,而StringBuilder和StringBuffer均为字符串变量
2. 运行速度:StringBuilder >StringBuffer >String
因为string是不断创建新的对 象并对旧的对象进行回收,其他两个可以直接更改对象,不用创建和回收,所以速度快
3.线程安全:StringBuilder是线程不安全的,而StringBuffer是线程安全的
因为StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。
使用场景
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
四、运行时异常和非运行时异常区别
运行时异常:都是RuntimeException类及其子类异常,如null、数组越界、类转换、ArrayStoreException(数据存储异常,操作数组时类型不一致)、IO操作的BufferOverflowException异常
非运行时异常:是RuntimeException以外的异常,类型上都属于Exception类及其子类。如IOException、SQLException等以及用户自定义的Exception异常。Java编译器强制要我们对这些进行catch处理
五、重写和重载的区别
重写:继承父类的方法,对父类的方法不满意,方法名称、参数、返回值要相同
重载:在同一个类中,就是不同的情况写不同的方法
六、是否可以继承String类?
不能,因为public final class String extends Object,里边有final关键字,所以不能被继承。
七、构造器(constructor)是否可被重写(override)?
不能被继承,所以不能重写,但是可以重载
八、抽象类和接口的区别
1.抽象类里可以有普通方法,接口里只能是抽象方法
2.抽象类里的变量可以是普通变量,接口里都是public final
3抽象类可以用public和protected修饰,接口里只能是public abstract
4.一个类可以继承一个抽象类,可以实现多个接口
九、反射的用途及实现
它允许运行中的Java程序对自身进行检查,并能直接操作程序的内部属性或方法。
反射就是让你可以通过名称来得到对象(类,属性,方法)的技术。
十、HTTP请求的GET与POST方式的区别
1、get在浏览器后退/刷新时是无害的,post的数据会被重新提交
2、Get是不安全的,因为在传输过程,数据被放在请求的URL中;Post的所有操作对用户来说都是不可见的;
3、GET 方法向 URL 添加数据,URL的长度是受限制的(URL 的最大长度是 2048 个字符,2K),而POST没有。
4、GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
5、GET参数通过URL传递,POST放在Request body( HTTP 消息主体)中。
6、对于参数的数据类型,GET只接受ASCII字符,而POST没有限制。
十一、cookies和session的区别
1、数据存放位置不同:
cookie存放在客户端浏览器,session存放在服务器上
2、安全程度
cookie不安全,可以分析放在本地的cookie
3、性能
session会在一定时间内保存在服务器上,当访问量增多,会占用服务器性能
4、数据存储大小不同
单个cookie存储不超过4k,session没有限制
5、会话机制不同
session会话机制:session会话机制是一种服务器端机制,它使用类似于哈希表(可能还有哈希表)的结构来保存信息。
cookies会话机制:cookie是服务器存储在本地计算机上的小块文本,并随每个请求发送到同一服务器。 Web服务器使用HTTP标头将cookie发送到客户端。在客户端终端,浏览器解析cookie并将其保存为本地文件,该文件自动将来自同一服务器的任何请求绑定到这些cookie。
十二、Jdbc流程
1.加载驱动 (forname)
2.提供jdbc连接的URL
3.连接数据库(getConnection)
4.创建一个statement
5.执行SQL语句(execute)
6.处理结果(查询后返回一个resultset)
7.关闭JDBC对象
十三、MVC设计思想
(1)最上面的一层,是直接面向最终用户的"视图层"(View)。它是提供给用户的操作界面,是程序的外壳。
(2)最底下的一层,是核心的"数据层"(Model),也就是程序需要操作的数据或信息。
(3)中间的一层,就是"控制层"(Controller),它负责根据用户从"视图层"输入的指令,选取"数据层"中的数据,然后对其进行相应的操作,产生最终结果。
每一层内部的变化不影响其他层。每一层都对外提供接口(Interface),供上面一层调用。
十五、List和Set区别
list:有序,可重复,基于数组,查找快增删慢
set:无序,不可重复,查找慢,增删快
十六、List和Map区别
List是对象集合,允许对象重复
Map是键值对的集合,不允许key重复
十七、Arraylist 与 LinkedList 区别
ArrayList是基于动态数组,地址连续,查询速度快,但因地址连续,插入删除较慢
linkedlist是基于链表的,地址是任意的,所以增删快,因为要移动指针,所以查询较慢
十八、ArrayList 与 Vector 区别
Vector是线程安全的,也是线程同步的,所以效率比较低
在集合中使用数据量比较大的数据时用Vector比较好
十九、HashMap 和 Hashtable 的区别
都可以使用来存储key-value的数据
- 1.HashMap是线程不安全的,效率高,JDK1.2版本
- Hashtable是线程安全的,效率低,JDK1.0版本
- 2.HashMap可以存储null键和null值
- Hashtable不可以存储null键和null值
二十、HashSet 和 HashMap 区别
HashMap实现了Map接口 HashSet实现了Set接口
HashMap储存键值对 HashSet仅仅存储对象
使用put()方法将元素放入map中 使用add()方法将元素放入set中
HashMap中使用键对象来计算hashcode值 HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false
HashMap比较快,因为是使用唯一的键来获取对象 HashSet较HashMap来说比较慢
二十一、HashMap 和 ConcurrentHashMap 的区别
ConcurrentHashMap是线程安全的HashMap的实现。
(1)ConcurrentHashMap一段一段的锁,hashtable锁整个坑。
ConcurrentHashMap高效的原因:CAS + 局部(synchronized)锁定分段式锁
(2)HashMap的键值对允许有null,但是ConCurrentHashMap都不允许。
二十二、CAS与Synchronized:乐观锁,悲观锁。
CAS:认为别人去拿数据的时候不会修改,但是在更新的时候会判断在此区间是否有别人去更新这个数据
Synchronized:每次去拿数据的时候都认为别人会修改,所以每次拿数据的时候都会上锁,别人拿数据的时候就会阻塞
二十三、线程:
1.并发和并行:
并发:两个或多个事件在同一时间段内发生
并行:两个或多个事件在同一时刻发生(同时发生)
2.创建线程的三种方式
并发:多个操作同时进行
1.继承thread类
d定义Thread类的子类,并重写该类的run()方法,该方法的方法体就是线程需要完成的任务,run()方法也称为线程执行体。
2】创建Thread子类的实例,也就是创建了线程对象
3】启动线程,即调用线程的start()方法
代码实例
public class MyThread extends Thread{//继承Thread类
public void run(){
//重写run方法
}
}
public class Main {
public static void main(String[] args){
new MyThread().start();//创建并启动线程
}
}
2、实现runable接口
通过实现Runnable接口创建并启动线程一般步骤如下:
1】定义Runnable接口的实现类,一样要重写run()方法,这个run()方法和Thread中的run()方法一样是线程的执行体
2】创建Runnable实现类的实例,并用这个实例作为Thread的target来创建Thread对象,这个Thread对象才是真正的线程对象
3】第三部依然是通过调用线程对象的start()方法来启动线程
代码实例:
public class MyThread2 implements Runnable {//实现Runnable接口
public void run(){
//重写run方法
}
}
public class Main {
public static void main(String[] args){
//创建并启动线程
MyThread2 myThread=new MyThread2();
Thread thread=new Thread(myThread);
thread().start();
//或者 new Thread(new MyThread2()).start();
}
}
3.实现callable接口
可以返回线程执行的结果
3.sleep() 和 wait() 有什么区别
sleep:是线程类的静态方法,因为sleep() 是static静态的方法,他不能改变对象的机锁,当一个synchronized块中调用了sleep() 方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象。
并发包:
1.CountDownLatch
允许一个或多个线程等待其他线程完成完成操作,再执行自己
一个构造器:
public CountDownLatch(int count) { }; //参数count为计数值,当为0时,被await阻塞的线程将会唤醒
三个方法:
public void await() throws InterruptedException { }; //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public void countDown() { }; //将count值减1
2.CyclicBarrier
与CountDownLatch的区别在于它可重用
当一组线程到达某个屏障时阻塞,直到最后一个线程到达后,所有被屏障拦截的线程才会继续运行。
构造器:
public CyclicBarrier(int parties, Runnable barrierAction)// 用于在线程到达屏障时,优先执行barrierAction,方便处理更复杂的业务场景
方法:
public int await()// 每个线程调用await方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞
3.Semaphore(信号量)
控制并发占锁的数量,就是一段时间内同时可以允许多少线程进行访问
构造方法:
public Semaphore(int permits) //permits 表示许可线程的数量
public Semaphore(int permits, boolean fair) //fair 表示公平性,如果这个设为 true 的话,下次执行的线程会是等待最久的线程
方法:
public void acquire() throws InterruptedException //表示获取许可
public void release() // 表示释放许可
acquire()用来获取一个许可,若无许可能够获得,则会一直等待,直到获得许可。
release()用来释放许可。注意,在释放许可之前,必须先获获得许可。
4.Exchanger(媒婆)
当两个线程都执行完,将本线程生产出来的数据与对方进行交换。如果等不到对方的数据交换就会造成死锁。
构造方法:
public Exchanger()
方法:
public V exchange(V x)
使用场景:数据校对工作
ThreadLocal:
为每一个线程提供一个副本变量,让他们同时访问时互不干扰
特点:
1.线程并发:多个操作同时进行
2.传递数据:保存每个线程绑定的数据,在需要的地方set获取,避免直接传参带来的代码耦合问题
3.线程隔离:各线程之间的数据相互隔离又具备并发性
ThreadLocal使用场景为 用来解决 数据库连接、Session管理
里面有ThreadLocalMap,没有实现map接口。成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。
线程的生命周期:
新建(New)、
就绪(Runnable):start
运行(Running):执行run方法
阻塞(Blocked):sleep和wait
死亡(Dead)5种状态
线程池的作用:
四种线程池:
1.newCachedThreadPool:创建非固定数量,可缓存的,若线程池超过处理需求,可灵活的回收空线程,当需求增加时,则创建新线程。
2.newFixedThreadPool:固定线程池,底层是无界队列,可控制最大并发数,超出的线程会在队列中等待,如果在关闭前的执行期间任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)
3.newScheduledThread:定时执行线程池,支持定时及周期性任务执行
4.newSingleThreadPool:单线程化的线程池,只会用唯一一个工作线程来执行任务,保证所有的任务按照指定顺序执行。
线程池的好处:
1.限定线程的个数,不会导致由于线程过多导致系统运行缓慢或崩溃
2.线程池每次都不需要创建和销毁,节约了资源
3.线程池不需要每次去创建,响应时间更快
单例集合:
保证一个类只有一个实例,只能创建一个对象
饿汉:
在类加载的时候就进行了实例化,避免了多线程同步的问题,缺点是实例没有使用内存就浪费了
懒汉:
只有在用的时候才会实例化
优点:
1.由于系统只存一个对象,因此可以节约系统资源,需要频繁创建和销毁对象时可以提高系统性能
2.避免共享资源的多重占用
数据存储:
索引的创建、删除
一个表的索引数最好不要超过6个
索引的类型:
UNIQUE(唯一索引):不可以出现相同的值,可以有NULL值
INDEX(普通索引):允许出现相同的索引内容
PROMARY KEY(主键索引):不允许出现相同的值
fulltext index(全文索引):可以针对值中的某个单词,但效率确实不敢恭维
组合索引:实质上是将多个字段建到一个索引里,列值的组合必须唯一
ALTER TABLE 表名 ADD 索引类型 (unique,primary key,fulltext,index)[索引名](字段名)
//普通索引
alter table table_name add index index_name (column_list) ;
//唯一索引
alter table table_name add unique (column_list) ;
//主键索引
alter table table_name add primary key (column_list) ;
ALTER TABLE可用于创建普通索引、UNIQUE索引和PRIMARY KEY索引3种索引格式,table_name是要增加索引的表名,column_list指出对哪些列进行索引,多列时各列之间用逗号分隔。索引名index_name可选,缺省时,MySQL将根据第一个索引列赋一个名称。另外,ALTER TABLE允许在单个语句中更改多个表,因此可以同时创建多个索引。
SQL优化:
1.在where及order by涉及的列上建立索引
2.尽量不要在where子句中对字段进行null值判断、!=或<>,会导致引擎放弃使用索引造成全表扫描
3.避免在where子句中写表达式或函数操作
4.避免or,用union all
5.避免not in 或 in,连续的数值用between,用exists 代替 in
小表驱动大表,即小的数据集驱动大的数据集:
当B表的数据集比A表小时,用in优化 exist两表执行顺序是先查B表再查 A表查询语句:SELECT * FROM tb_dept WHERE id in (SELECT id FROM tb_dept) ;
当A表的数据集比B表小时,用exist优化in ,两表执行顺序是先查A表,再查B表,查询语句:SELECT * FROM A WHERE EXISTS (SELECT id FROM B WHERE A.id = B.ID) ;
6.不要用select *
7.尽量使用连接代替子查询,因为使用 join 时,MySQL 不会在内存中创建临时表。
Oracle和Mysql的区别:
Redis:
key-value存储
1.redis默认分多少个数据库:
16
适合存在redis中的数据:
1.关系不密切的数据,比如用户信息,评论数量等
2.量比较大的数据,入访问记录
3.访问比较频繁的数据,入用户信息等
类型:
- 字符串类型 string(string可以包含任何数据)
- 哈希类型 hash : map格式
- 列表类型 list : linkedlist格式。支持重复元素
- 集合类型 set : 不允许重复元素
- 有序集合类型 sortedset:不允许重复元素,且元素有顺序
持久化三种方式:
1.快照(RDB)
原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化
缺点:出现宕机的情况,没有来得及写入磁盘的数据将丢失
2.AOF
原理是将Reids的操作日志以追加的方式写入文件
servlet:
理解:
作用:在于交互式地浏览++
修改数据,生成动态的web内容。
是提供基于协议的request/response服务的java类------是手工编写的.class文件
必须存放在一个web服务器里,比如Tomcat
连接浏览器和数据库的一个桥梁
生命周期:
初始化:init方法---------响应用户请求阶段:service方法--------终止阶段:destroy
当用户第一次访问servlet的时候,服务器创建一个servlet实例,执行init方法,每次请求服务器都会创建一个线程访问servlet中的service方法,在service方法内部根据请求的不同调用doget、dopost方法,当servlet从服务器中移除掉或关闭服务器,servlet实例就会被销毁,destory方法就会执行
forward和redirect的区别:
直接转发就相当于:“A找B借钱,B说没有,B去找C借,借到借不到都会把消息传递给A”;
间接转发就相当于:“A找B借钱,B说没有,让A去找C借”。
直接(forward):
客户端和浏览器只发出一次请求,是服务器内部的重定向,服务器直接访问目标地址的 url网址,把里面的东西读取出来,但是客户端并不知道,因此用forward的话,客户端浏览器的网址是不会发生变化的
间接(Redirect):
两次HTTP请求,服务器端响应第一次请求的时候,让浏览器再向另一个URL发送请求
forword转发是服务器上的行为,而redirect重定向是客户端的行为
Spring:
1.为啥使用Spring:
从大小与开销两方面而言它是轻量级的
2.Bean:
bean就是由IoC容器初始化、装配及管理的对象 .
线程不安全
对象和bean的区别:
bean拿出的是有属性赋值的对象,它会先实例化
3.AOP:
简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度
4.IOC(控制反转):
将对象的创建交给容器
5.Spring常用的注入方式
构造方法注入、set注入、基于注解的注入
6.spring支持几种bean的作用域:
1.singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例,默认bean都是单例的。IOC容器仅创建一个Bean实例
2.prototype:原型模式,每次请求,都将创建一个新的Bean实例,IOC容器可以创建多个Bean实例
3.request:每次HTTP请求将会产生一个新的Bean实例,每个HTTP请求都会有各自的bean实例,只有在web应用中使用Spring时该作用域才会生效。
4.session:对于每次HTTP Session,使用session定义的Bean都将产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效(同上)
5.globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效
7.spring 自动装配 bean 有哪些方式
”装配“ 就是指将Bean安装Bean容器中并进行依赖关系配置
1.隐式的bean发现机制和自动装配
2.在java代码或xml中进行显式装配
自动装配:
1.byName(按名称)
当一个bean节点带有 autowire byName的属性时。
将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。
去spring容器中寻找是否有此字符串名称id的对象。
如果有,就取出注入;如果没有,就报空指针异常。
2.byType(按名称)
需保证同一类型的对象在Spring容器中唯一
(这种不行)
8.spring 事务实现方式有哪些
1.编程式事务管理,在代码中调用beginTransation、commit、rollback等事务管理方法
2.基于TransationProxyFactoryBean的声明式事务管理
3.基于@Transational的声明式事务管理
4.基于Aspectj AOP配置事务
https://blog.youkuaiyun.com/meism5/article/details/90446733
9. 说一下 spring 的事务隔离
事务隔离级别是指一个事务对数据的修改与另一个并行的事务的隔离程度,当多个事务同时访问相同数据时,如果没有采用隔离机制就会发生:
脏读:一个事务中读取到另一个事务中未提交的数据
幻读:一个事务对表中的数据进行了修改,这种修改涉及到表中的所有信息行,同时第二个事务也修改这个表中的数据,是像这个表中插入一条新数据,操作第一个事务的用户发现表中还有没有修改的数据,以为发生环境
不可重复读:一个事务中多次读取同一数据,这个事务还没结束时,另一个事务也访问该同一数据,那么第一个事务两次读取数据之间,由于第二个事务的修改,可能导致两次读取的数据不一样,这样就发生了一个事务中两次读取的数据不一样
10.MVC框架要做哪些事情
将url映射到java类或java类的方法 .
封装用户提交的数据 .
处理请求–调用相关的业务处理–封装响应数据 .
将响应的数据进行渲染 . jsp / html 等表示层数据 .
11.Spring MVC有哪些组件
DispatcherServlet:中央控制器,把请求给转发到具体的控制类
Controller:具体处理请求的控制器
HandlerMapping:映射处理器,负责映射中央处理器转发给controller时的映射策略(查到具体的controller)
ModelAndView:服务层返回的数据和视图层的封装类
ViewResolver:视图解析器,解析具体的视图
Interceptors :拦截器,负责拦截我们定义的请求然后做处理工作
12.Spring MVC运行流程
SpringMVC的请求相应步骤如下:
1.用户发送请求到DispatcherServlet
2.DispatcherServlet接收请求调用HanderMapping(处理器映射器)
3.HanderMapping找到具体的处理器(可查找xml配置或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet
4.DispatcherServlet调用HanderAdapter(处理器适配器)
5.HanderAdapter经过适配调用具体的处理器(Handler/Controller)
6.Controller执行完成后返回ModelAndView对象
7.HanderAdapter将执行结果返回给DispatcherServlet
8.DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)
9.ViewReslover解析后返回具体的View(视图)
10.DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)
11.DispatcherServlet响应用户
13.@requestMapping的作用
将 http 请求映射到相应的类/方法上
14.@Autowired 的作用是什么?
@Autowired 它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作,通过@Autowired 的使用来消除 set/get 方法。
存储过程:
1.解释
专门用来干一件事的一段SQL
2.优点
1.只在创建时进行编译,以后每次执行都不会重新编译,普通SQL一般每次执行都会编译,会提高数据库执行速度
2.可以降低网络负载,编译好后会放在数据库,调用时不会传输大量的字符串类型的SQL语句
3.存储过程可重复使用,减少开发工作量
4.维护性高
5.安全性高:完成某个特定功能的存储过程只用特定的用户可以使用
3.代码
1.无参存储过程
CREATE OR REPLACE PROCEDURE demo AS/IS
变量2 DATE;
变量3 NUMBER;
BEGIN
–要处理的业务逻辑
EXCEPTION --存储过程异常
END
这里的as和is一样任选一个,在这里没有区别,其中demo是存储过程名称。
2.有参存储过程
a.带参数的存储过程
CREATE OR REPLACE PROCEDURE 存储过程名称(param1 student.id%TYPE)
AS/IS
name student.name%TYPE;
age number :=20;
BEGIN
–业务处理…
END
第1行:param1 是参数,类型和student表id字段的类型一样。
第4行:声明变量age,类型数数字,初始化为20
b.带参数的存储过程并且进行赋值
CREATE OR REPLACE PROCEDURE 存储过程名称(
s_no in varchar,
s_name out varchar,
s_age number) AS
total NUMBER := 0;
BEGIN
SELECT COUNT(1) INTO total FROM student s WHERE s.age=s_age;
dbms_output.put_line(‘符合该年龄的学生有’||total||‘人’);
EXCEPTION
WHEN too_many_rows THEN
DBMS_OUTPUT.PUT_LINE(‘返回值多于1行’);
END
其中参数IN表示输入参数,是参数的默认模式。
OUT表示返回值参数,类型可以使用任意Oracle中的合法类型。
OUT模式定义的参数只能在过程体内部赋值,表示该参数可以将某个值传递回调用他的过程
IN OUT表示该参数可以向该过程中传递值,也可以将某个值传出去
第7行:查询语句,把参数s_age作为过滤条件,INTO关键字,把查到的结果赋给total变量。
第8行:输出查询结果,在数据库中“||”用来连接字符串
第9—11行:做异常处理
Jquery中页面加载完毕事件:
$(function{}表示的是页面结构被加载完毕
Window.onload表示的是页面被加载完毕
Dubbo:
1.为啥使用:
当前web程序规模太大,分布式体系结构可以确保体系结构有序发展,一些核心的业务被提取并作为独立的服务来提供服务,逐渐形成一个稳定的服务中心,这样前端应用程序可以更好的响应市场需求。分布式框架可以承受更大规模的流量。
2.Dubbo提供了哪3个关键功能?
1.基于接口的远程调用
2.容错(当服务消费者调用服务提供者失败后自动切换到其他服务提供者服务器进行重试)和负载均衡(避免多个请求一直落到一个或几个服务器上,使机器负载很高,这个每次随机调用一个服务提供者的机器)
3.自动服务注册和发现
3.Dubbo服务的关键节点有哪些
4.说一下Dubbo服务注册流程
1.服务容器负责启动、加载、运行服务提供者
2.服务提供者在启动时,向注册中心注册自己提供的服务
3.服务消费者在启动时,向注册中心订阅自己所需的服务
4.注册中心返回服务提供者的地址列表给消费者,若有变更,注册中心将基于长连接推送变更数据给消费者。
5.服务消费者从提供者地址列表中基于负载均衡算法选择一台服务器进行调用,如果调用失败再选择另一台调用。
6.服务调用者和提供者,在内存中累计调用次数和时间,定时每分钟发送一次统计数据到监控中心。
5.Dubbo架构的特点
连通性、健壮性、伸缩性、以及向未来架构的升级性。
6.dubbo对jdk的最小版本需求
jdk1.6
反射
1.反射的用途及实现
它允许运行中的Java程序对自身进行检查,并能直接操作程序的内部属性或方法。
反射就是让你可以通过名称来得到对象(类,属性,方法)的技术。
反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力
在运行时判断任意一个对象所属的类。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法。
在运行时构造任意一个类的对象。
2.什么是 java 序列化?什么情况下需要序列化?
序列化:将 Java 对象转换成字节流的过程
当java对象需要在网络上传输或者需要持久化存储到本地文件中
实现:类实现Serializable 接口
3.什么是动态代理?有哪些应用
相当于中介
代理模式给某一个对象提供了一个代理对象,并由代理对象控制对原对象的引用。
通过使用动态代理,我们可以做一个“统一指示”,从而对所有代理类的方法进行统一处理,而不用逐一修改每个方法。
当某个类或者接口中的方法增加额外的功能,比如日志、事务的时候,可以通过创建一个代理类来实现功能,该代理类不仅包含原有类的功能而且还添加了其他逻辑。这个代理类不是事先定义好的而是动态生成的
应用:Spring的AOP、加事务、权限、日志
动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
基于接口的动态代理----JDK动态代理
基于类的动态代理–cglib
4.怎么实现动态代理
1.创建被代理的类(委托类、真实类)(RealSubject)及其接口(RealSubjectInterface)
2.创建一个实现接口InvocationHandler的类(InvocationHandlerImpl),它必须实现接口的invoke方法
3.通过Proxy的静态方法newProxyInstance(), 创建一个代理对象(realSubjectProxy)
RealSubjectInterface realSubjectProxy= (RealSubjectInterface) Proxy.newProxyInstance(loader,interfaces,handler);
4.通过代理对象(realSubjectProxy)调用 委托类对象( realSubject)的方法
1、通过实现 InvocationHandler 接口创建自己的调用处理器;
2、通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
3、通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
4、通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入
对象拷贝:
1.为什么用
想对一个对象进行处理,又想保留原来的数据进行操作,克隆针对的是类的实例
2.如何实现
实现Cloneable接口并重写Object类中的clone()方法;
实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆
3.浅拷贝和深拷贝分别是什么
浅拷贝只是复制了对象的引用地址,两个对象还是指向同一个内存地址,修改其中一个值,另一个值会改变
深拷贝是将对象及值复制过来,两个对象修改任意一个另一个不会变
zookeeper:
1.什么是zookeeper:
为分布式应用提供协调服务,管理集群,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作,将简单易用
的接口和性能高效、功能稳定的系统提供给用户。
2.特点:
SpringBoot:
1.讲述一下 SpringBoot 自动装配原理
可以从以下几个方面回答:
什么是 SpringBoot 自动装配?
SpringBoot 是如何实现自动装配的?如何实现按需加载?
如何实现一个 Starter?
Spring Boot 通过@EnableAutoConfiguration开启自动装配,通过 SpringFactoriesLoader 最终加载META-INF/spring.factories中的自动配置类实现自动装配,自动配置类其实就是通过@Conditional 按需加载的配置类,想要其生效必须引入spring-boot-starter-xxx 包实现起步依赖