IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 39-面经总结 -> 正文阅读

[Java知识库]39-面经总结

Spring的启动流程?

对于一个web应用,其部署在web容器中,web容器提供一个全局的上下文环境,这个上下文就是ServletContext,为后面的IOC容器提供宿主环境

在web.xml里提供contextLoaderListener,它会监听容器的初始化事件,调用contextInitialized方法启动上下文WebApplicationContext,这个就是IOC容器,初始化完毕后会以key-value的形式存储到ServletContext中

随后开始配置web.xml中配置的Servlet,这样的Servlet可以有多个,经典的比如DIspatcherServlet,它的上下文在初始化的时候会建立自己的IOC上下文,用来持有mvc相关的bean,其过程是:先从ServletContext里拿到根上下文(WebApplicationContext)作为自己上下文的父上下文,在此基础上再初始化自己的上下文,这样以来每个Servlet就都持有了自己的上下文,即拥有量自己bean的独立空间,同时他们共享根上下文中定义的那些bean

Spring和MVC上下文的关系

上下文可以简单的理解为容器,配置文件,web上下文目标对象是所有web应用,spring上下文目标对象是单个web应用,mvc目标对象是单个web应用的spring mvc框架

MVC常用注解以及执行流程

流程:

  • 用户发送请求到DispatcherServelt
  • DispatcherServelt收到请求调用HandlerMapping
  • HandlerMapping找到具体的处理器并且生成处理器对象和处理器拦截器,返回给DispatcherServlet
  • DispatcherServlet调用HandlerAdapter
  • HandlerAdapter经过适配调用具体的Controller
  • Controller被调用返回给HandlerAdapter ModelandView,HandlerAdapter接着返回给DispatcherServlet
  • DispatcherServlet调用视图解析器进行解析返回具体的View
  • 最后由DispatcherServlet返回渲染的视图并且响应用户

常用注解:

  • @Controller:标记在类上,表示是一个Controller对象,其实和Component,Service等注解没什么区别
  • @RequestMapping:用于处理请求地址映射的注解
  • @Resource和@Autowired:用于注入bean,前者其实是jdk的注解并且默认byname注入,后者byType注入
  • @PathVariable:用于取出URL模板中的变量作为参数
  • @RequestParam:将请求的参数绑定到方法参数上,可以是多个也可以是Map集合
  • @RequestBody:取出请求体里的数据自动封装

Controller是否单例?好处是什么?和多线程的关系?

默认是单例的,所以说不要在Controller去定义属性,这样线程是不安全的,如果需要定义属性需要添加@Scope注解改成多例的模式;

由于MVC是基于方法的开发,都是用形参接受值,一个方法结束参数就销毁了,一个单例对象能做完的事情为什么要交给多个多例对象呢

fast-fail机制

是java集合中的错误检测机制,在迭代集合的过程中该集合在结构上发生改变就有可能会发生fast-fail并且抛出ConcurrentModificationException,比如在ArrayList遍历的过程中,刻意的在某一步迭代中调用集合类的remove方法移除一个元素,或者多线程一个线程迭代一个remove;

底层是集合类迭代的next()方法,在访问元素前都会调用checkForComodification方法,这个方法会对modCount这个变量进行判断,如果被更改了就会抛出异常

异常的类别

Throwable类是最大的底下有Exception和Error两个子类;

  • Error一般指的是程序问题,自己无法解决,比如OOM,NoClassFound
  • Exception指的是可以预料的异常情况,可以捕获它并对他进行处理,比如数组越界,空指针

Mybatis的二级缓存

二级缓存是mapper级别的缓存,底层是hashmap实现的,不同的mapper都有一个二级缓存,他们之间互不影响,与一级缓存的区别在于二级缓存的范围更大,多个sqlSession可以共享一个mapper中的二级缓存,Mybatis区分二级缓存靠的是mapper的不同namespace,如果两个mapper的namespace相同,他们将使用相同的二级缓存

在二级缓存的设计上Mybatis大量使用了装饰者模式+责任链模式,CachingExecutor以及各种Cache接口的装饰器,以下是装饰者模式的案例:

public class Solution {
    public static void main(String[] args) {
        Competitor competitor = new Competitor();
        CompetitorDecoratorA decoratorA = new CompetitorDecoratorA(competitor);
        CompetitorDecoratorB decoratorB = new CompetitorDecoratorB(decoratorA);
        decoratorB.sing();//偏偏起舞...我唱唱唱......鼓掌....
    }
}
class Competitor {
    public void sing(){
        System.out.println("我唱唱唱......");}}

class CompetitorDecorator extends Competitor{
    private Competitor competitor;
    public CompetitorDecorator(Competitor competitor){
        this.competitor= competitor;
    }
    public void sing(){
        competitor.sing();
    }
}
class CompetitorDecoratorA extends CompetitorDecorator {
    public CompetitorDecoratorA(Competitor competitor) {
        super(competitor);
    }
    public void sing()
    {
        this.dance();
        super.sing();
    }
    private void dance()
    {
        System.out.println("偏偏起舞....");
    }

}
class CompetitorDecoratorB extends CompetitorDecorator {
    public CompetitorDecoratorB(Competitor competitor) {
        super(competitor);
    }
    public void sing()
    {
        super.sing();
        guzhang();
    }
    private void guzhang()
    {
        System.out.println("鼓掌....");
    }

}

责任链模式:获取缓存要记录缓存命中率,在事务中操作等等,只使用Cache的某个实现类是不行的,普通的责任链模式是或者关系,这个不行就交给下一个做

public abstract class Handler {
    //后继者,即如果处理不了请求要把任务丢给谁
    private Handler successor;
 
    public Handler getSuccessor() {
        return successor;
    }
 
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
    public abstract void HandleRequest(int num);
}

/**
 * @author wuyimin
 * @create 2021-07-29 19:21
 * @description 导师类,最抠门的类
 */
public class Teacher extends Handler {
 
    @Override
    public void HandleRequest(int num) {
        if(num<=600){
            System.out.println("抠门的导师接受了你的请求给了你"+num+"人民币");
        }else{
            System.out.println("你的导师不想给你钱");
            getSuccessor().HandleRequest(num);
        }
    }
}
 
/**
 * @author wuyimin
 * @create 2021-07-29 19:25
 * @description 兄弟类
 */
public class Brother extends Handler {
 
    @Override
    public void HandleRequest(int num) {
        if(num<=2000){
            System.out.println("你的好兄弟答应了要借你"+num+"元");
        }else{
            System.out.println("你的好兄弟没有那么多钱");
            getSuccessor().HandleRequest(num);
        }
    }
}
 
/**
 * @author wuyimin
 * @create 2021-07-29 19:26
 * @description 爹妈类
 */
public class Parent extends Handler {
 
    @Override
    public void HandleRequest(int num) {
        System.out.println("你的爹妈借了你"+num+"元");
    }
 
    public static void main(String[] args) {
        Brother brother = new Brother();
        Teacher teacher = new Teacher();
        Parent parent = new Parent();
        teacher.setSuccessor(brother);
        brother.setSuccessor(parent);
        teacher.HandleRequest(5000);
    }
}

Mybatis的二级缓存是协同关系,就是我处理完了马上就给你处理,把Logging Cache,SynchronizedCache,TransactionalCache等实现类串联起来,走一套流程把事情做完

Linux怎么杀掉一个进程

ps -ef|grep 找到进程id,然后kill pid,加上-9参数是强制杀死,其中9代表信号变量SIGKILL的代号,表示立即终止的意思

讲讲CAS的实现

以AtomicInteger为例,它在rt.jar包下,通过BootStrap加载器进行加载,所以可以通过getUnsafe()方法拿到Unsafe类的实例,其内部方法都是基于Unsafe类实现,Unsafe类是个与底层硬件CPU指令通信的工作累,CAS全名叫compare and swap,其底层原理是Unsafe+自旋锁,其中的getandAddInt方法

//Unsafe类
//获取内存地址为obj+offset的变量值, 并将该变量值加上delta
public final int getAndAddInt(Object obj, long offset, int delta) {
    int v;
    do {
    	//通过对象和偏移量获取变量的值
    	//由于volatile的修饰, 所有线程看到的v都是一样的
        v= this.getIntVolatile(obj, offset);
    /*
	while中的compareAndSwapInt()方法尝试修改v的值,具体地, 该方法也会通过obj和offset获取变量的值
	如果这个值和v不一样, 说明其他线程修改了obj+offset地址处的值, 此时compareAndSwapInt()返回false, 继续循环
	如果这个值和v一样, 说明没有其他线程修改obj+offset地址处的值, 此时可以将obj+offset地址处的值改为v+delta, compareAndSwapInt()返回true, 退出循环
	Unsafe类中的compareAndSwapInt()方法是原子操作, 所以compareAndSwapInt()修改obj+offset地址处的值的时候不会被其他线程中断
	*/
    } while(!this.compareAndSwapInt(obj, offset, v, v + delta));
 
    return v;
}

ABA问题解决,使用atomicStampedReference,拿到版本号再进行业务

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-06 12:48:23  更:2022-03-06 12:52:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:50:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码