前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >长达100分钟的阿里二三面,惊险刺激!乔戈里又和学弟要来了面经!

长达100分钟的阿里二三面,惊险刺激!乔戈里又和学弟要来了面经!

作者头像
乔戈里
发布2020-04-24 17:32:07
4290
发布2020-04-24 17:32:07
举报
文章被收录于专栏:Java那些事Java那些事

电话面。这一面,项目为主,基础知识为辅,重点是需要将自己做的项目用比较清楚的话语表述清楚,让面试官能够最短时间了解到你做的项目,同时切忌注意,自己不了解不深入的知识点尽量不要提及,这是大忌。

  • 当将业务水平分库后,转账业务如何保证事务的一致性?

这是典型的分布式事务,理论有 CAP 「C (一致性),A (可用性),P (分区容错性),只能选择 AP or CP」,BASE「Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent (最终一致性)三个短语的缩写。是对CAP中AP的一个扩展」 常见的分布式解决方案:

  1. 2PC,两阶段提交,事务管理器来协调,全部okay了才okay,这样效率很低,因为是如果没成功就一直阻塞。
  2. TCC(Try-Confirm-Cancel)最大努力交付,在更新多个资源时,将多个资源的提交尽量延后到最后一刻处理,这样的话,如果业务流程出现问题,则所有的资源更新都可以回滚,事务仍然保持一致。唯一可能出现问题的情况是在提交多个资源时发生了系统问题,比如网络问题等,但是这种情况是非常罕见的,一旦出现这种情况,就需要进行实时补偿,将已提交的事务进行回滚。
  3. 事务补偿机制。在数据库分库分表后,如果涉及的多个更新操作在某一个数据库范围内完成,则可以使用数据库内的本地事务保证一致性;对于跨库的多个操作,可通过补偿和重试,使其在一定的时间窗口内完成操作,这样就可以实现事务的最终一致性,突破事务遇到问题就滚回的传统思路。

参考:https://juejin.im/post/5b5a0bf9f265da0f6523913b#heading-16 https://cloud.tencent.com/developer/news/200316 说实话…还没看太懂…

  • zookeeper中的两阶段提交是怎么去做的?

CAP理论中,zookeeper就是CP,放弃可用性,追求一致性和分区容错性,追求的是强一致。

  • 在项目中假如一级调度器挂了,怎么处理?

我说没处理…正常应该是类似于 Mysql 一样有个主备切换的机制。

  • SpringBoot中的 AOP 分为几类,

AOP 主要是两种方式,一种是直接通过 JDK 动态代理,一种是通过cglib。 先来回顾一下 Spring 中 AOP 的流程:

  1. 代理的创建。 注意:创建代理对象时,同时会创建一个外层拦截器,这个拦截器就是 Spring 内核的拦截器。用于控制整个 AOP 的流程。
    1. 需要创建代理工厂,代理工厂需要 3 个重要的信息:拦截器数组,目标对象接口数组,目标对象。
    2. 创建代理工厂时,默认会在拦截器数组尾部再增加一个默认拦截器 —— 用于最终的调用目标方法。
    3. 当调用 getProxy 方法的时候,会根据接口数量大余 0 条件返回一个代理对象(JDK or Cglib)。
  2. 代理的调用
    1. 当对代理对象进行调用时,就会触发外层拦截器。
    2. 外层拦截器根据代理配置信息,创建内层拦截器链。创建的过程中,会根据表达式判断当前拦截是否匹配这个拦截器。而这个拦截器链设计模式就是职责链模式。
    3. 当整个链条执行到最后时,就会触发创建代理时那个尾部的默认拦截器,从而调用目标方法。最后返回。

AOPAOP过程[1] 参考:https://www.jianshu.com/p/e18fd44964eb

  • 讲讲 cglib 如何使用并实现的?

动态代理再熟悉不过了,是只能代理接口,cglib现在我们来具体看一下。 我们知道,动态代理是代理类实现被代理类的接口,而cglib则是代理类继承被代理类,也就是子类增强父类的手段。cglib其实也就是字节码增强类库。 具体如何使用 cglib:https://zhuanlan.zhihu.com/p/37886319

  • 动态代理和cglib的区别?

  • 一个是代理类实现接口,一个是代理类继承类,我觉得差不太多。
  • 动态代理用到的接口有 InnvocationHandler,通过实现其 invoke 方法增强方法,并且通过 Proxy.newInstace() 实现代理过程。而cglib则使用 MethodInterceptor 接口,通过实现其 intercept() 方法增强方法,并且通过 Enhancer.create() 方法实现代理过程。

下面我放一下自己写的动态代理和 cglib 的实现

代码语言:javascript
复制
// 动态代理,总共有四个类

// 1. 接口
package AOP.Proxy;

public interface Person {
    void play();
    void dance();

}

// 2. 实现类,也就是要被代理的类
package AOP.Proxy;

public class Universities implements  Person {
    @Override
    public void play() {
        System.out.println("I like play computer");

    }

    @Override
    public void dance() {
        System.out.println("I like dance");
    }
}




// 3. 实现 InnocationHandler 接口,完成代理的任务
package AOP.Proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Dynamic implements InvocationHandler {
    // 整容的人是谁,我得知道
    private Object obj;
    public Dynamic(Object obj){
        this.obj = obj;
    }
  // 整容的过程
    public Object myDynamic(){
        return Proxy.newProxyInstance(this.obj.getClass().getClassLoader(),this.obj.getClass().getInterfaces(),this);
    }
    // 整容的地方交代清楚
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始为" + method.getName() + "方法进行代理");
        Object result = method.invoke(obj,args);
        System.out.println("结束" + method.getName() + "方法的代理");
        return result;
    }
}


// 4. 测试类
// 这里我采用了两种方法测试,一种是直接在 test 类中写出整容的过程
// 另外一种是直接调用我在 Dynamic 已经包装好整容过程的方法,建议使用这种
// 因为这样代码就少了,下面 cglib 就是采用方法二哈
package AOP.Proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class test {
    public static void main(String[] args) {
        // 相当于做生意的过程,比如我去医院整容,首先我要确保我有钱(也就是有接口)
        Universities person = new Universities();
        // 其次,我得去医院找到相应的医生,也就是把我想代理的对象,即我本人,告知给医生
        // 医生肯定得有能整容的技术,那就是得继承 InvocationHandler
        InvocationHandler dynamic_person = new Dynamic(person);
        // 进行交易的过程,一手交钱一手交换,医生拿到钱,会返回一个有钱的处理好的美女,也就是代理完成了
        // 这里必须强调代理返回的是 接口对象,也就是医生只会对有钱人进行代理,没钱的代理就失败了
        // 如果最开始我没钱,我就去找医生了,那在这一步交易的过程就会出错,因为医生只会处理有钱人,并且返回有钱人的代理好的对象
        // 有钱人得到代理后的对象,就可以为所欲为了
        Person pp = (Person) Proxy.newProxyInstance(person.getClass().getClassLoader(),person.getClass().getInterfaces(),dynamic_person);
        
        pp.dance();
        System.out.println("-----------");
        
        
        Person pp2 = (Person) new Dynamic(person).myDynamic();
        pp2.dance();



    }
}

cglib 实现

代码语言:javascript
复制
// cglib 实现
//1. 导包,在pom.xml 导包
    <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib-nodep</artifactId>
            <version>3.2.0</version>
        </dependency>

        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.0</version>
        </dependency>
        
// 2. 需要被代理的类
package AOP.Cglib;

public class SomeService {
    public String doFirst() {
        System.out.println("执行doFirst()方法");
        return "abc";
    }

    public void doSecond() {
        System.out.println("doSecond()方法");
    }
}

// 3. 进行代理过程
package AOP.Cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibFactory implements MethodInterceptor {

    private Object object;

    public CglibFactory(Object object) {
        this.object = object;
    }

    public Object myCglibCreator() {
        Enhancer enhancer = new Enhancer();
        //将目标类设置为父类,cglib动态代理增强的原理就是子类增强父类,cglib不能增强目标类为final的类
        //因为final类不能有子类
        enhancer.setSuperclass(this.object.getClass());
        //设置回调接口,这里的MethodInterceptor实现类回调接口,而我们又实现了MethodInterceptor,其实
        //这里的回调接口就是本类对象,调用的方法其实就是intercept()方法
        enhancer.setCallback(this);
        //create()方法用于创建cglib动态代理对象
        return enhancer.create();
    }

    //回调接口的方法
    //回调接口的方法执行的条件是:代理对象执行目标方法时会调用回调接口的方法
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        Object result = methodProxy.invokeSuper(o, objects);

        //这里实现将返回值字符串变为大写的逻辑
        if(result != null) {
            result = ((String) result).toUpperCase();
        }
        return result;
    }
}

// 4. 测试
package AOP.Cglib;

public class Test {
    public static void main(String[] args) {
        SomeService target = new SomeService();

        SomeService proxy = (SomeService) new CglibFactory(target).myCglibCreator();

        String result = proxy.doFirst();
        System.out.println(result);
        proxy.doSecond();
    }
}
  • Spring中 Ioc 和 DI 讲一下?

参考:https://juejin.im/post/5df5bab0e51d45582427104e https://www.jianshu.com/p/17b66e6390fd

IoC(Inversion of Control 控制反转):是一种面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度。其基本思想是:借助于“第三方”实现具有依赖关系的对象之间的解耦。 DI(Dependence Injection 依赖注入):将实例变量传入到一个对象中去(Dependency injection means giving an object its instance variables)。 也就是说 DI 是 Ioc 的 实现,Ioc 是一种设计原则。 Spring 作者 Rod Johnson 设计了两个接口用以表示容器。

  • BeanFactory
  • ApplicationContext

BeanFactory 粗暴简单,可以理解为就是个 HashMap,Key 是 BeanName,Value 是 Bean 实例。通常只提供注册(put),获取(get)这两个功能。我们可以称之为 “低级容器”。 ApplicationContext 可以称之为 “高级容器”。因为他比 BeanFactory 多了更多的功能。他继承了多个接口。因此具备了更多的功能。例如资源的获取,支持多种消息(例如 JSP tag 的支持),对 BeanFactory 多了工具级别的支持等待。所以你看他的名字,已经不是 BeanFactory 之类的工厂了,而是 “应用上下文”, 代表着整个大容器的所有功能。该接口定义了一个 refresh 方法,此方法是所有阅读 Spring 源码的人的最熟悉的方法,用于刷新整个容器,即重新加载/刷新所有的 bean。 Ioc 的过程: a. 加载配置文件,解析成 BeanDefinition 放在 Map 里。 b. 调用 getBean 的时候,从 BeanDefinition 所属的 Map 里,拿出 Class 对象进行实例化,同时,如果有依赖关系,将递归调用 getBean 方法 —— 完成依赖注入。

  • ORM框架有哪些?有什么好处?什么是mysql注入?$ 和 # 有什么区别

JPA是orm框架标准,主流的orm框架都实现了这个标准。 MyBatis没有实现JPA,他和orm框架的设计思路完全不一样。MyBatis是拥抱sql,而orm则更靠近面向对象,不建议写sql,实在要写推荐你写hql代替。 Mybatis是sql mapping框架而不是orm框架,当然orm和Mybatis都是持久层框架。 所以说hibernate是典型的ORM框架,好处就是我们可以用面向对象的思想去对数据库进行操作,我觉得主要就是比较省代码,解决面向对象的设计方式和关系型数据库之间的关联,Java主要面向对象设计,因此在分析业务的时候会以对象的角度来看待问题。然而数据库是关系型的,对于Java程序员而言是不符合面向对象设计的,因此才会出现ORM这种东西。有了ORM,Java开发人员在整个代码设计都将遵循对象的思维模式,这就是好处。 mysql注入:参数进行转义与过滤 如何解决:使用 Prepare Statement $ 和 # 的区别: Sql: delete from student where name=${name} 假如 name = jerome OR 1 = 1 在 Mybatis 中,如果写 ${name},那就是直接将 name 拼接到 sql 中,结局就是全删; 如果写 #{name},则 sql 变成 delete from student where name= ’jerome OR 1 = 1‘,这样只有name = jerome OR 1 = 1 的才会删除,否则不会删除任何东西。

阿里三面

从这一面开始面试官就是阿里 P9 了,所以说实话压力还是非常大的,这一面还是跟前面一样是电话面。这一面基本上没有问任何基础,全部在讲项目,建议大家一定要有一个讲的很溜的项目,我因为提及了一下毕设,然后就被一直抓着问,而自己本身其实是没有好好准备这个项目的,所以有些问题竟然被问了后,答得不是特别理想。但是还好,答得也没有很差,后面的项目介绍的还是让面试官很满意的。

介绍完后,面试官可能觉得才半小时,于是就问了几个问题,只是探寻一下我知识的广度吧,全部没有深入。

例如:

  • 了解 tomcat 吗?「当然了这是我在讲双亲委派模型引申出来的」
  • 用过 nginx 吗?
  • spring 中用过吗?

这些,我因为说不太了解 or 用过没深入,所以面试官也就索性没有问下去。

最后,花了10分钟介绍了下自己的部门,然后就到了反转环节了,我觉得大家可以好好抓住反转环节,因为我们往往可以从这个环节探到面试官对本次面试的看法,比如,我问的第一个问题就是:

”我觉得今天的表现不是很好,第一个项目没讲的非常清楚,您后面问的几个知识点我也不太会,没深入了解过。“

很让我意外的是,面试官给我的回答让我备受鼓舞:

”前面可能是你太着急太紧张了,所以讲的不是很好,但是后面讲的很清楚了,也能听得出来全是自己用心做了的,我也听明白了,所以不用担心,至于后面的知识点不会也非常正常,你还年轻的很,不会是非常正常的,你要都会了我还需要在这吗?你还年轻,是非常有潜力的。“

至此,开始期待四面。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员乔戈里 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 阿里三面
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档