整理-中邮消费金融面经

杨大大...大约 13 分钟

1.介绍一个实习中项目,有什么收获,主要工作是什么,项目中遇到问题如何解决,如何处理协作问题?

2.问了遇到的最大难题,当前offer情况?

3.java中用了哪些技术?

  • 面向对象技术 - java是一门纯面向对象的语言,支持封装、继承和多态等面向对象特性。
  • JVM技术 - java代码运行在JVM上,JVM负责内存管理、垃圾回收等,支持跨平台运行。
  • 多线程技术 - java提供了线程机制,可以通过继承Thread类或实现Runnable接口来创建线程,还提供了线程同步、线程通信等功能。
  • 集合框架 - java提供了丰富的集合类,如List、Set、Map等,大大简化了集合操作。
  • 泛型技术 - 泛型提供了编译时的类型安全检测机制,可以在编译时发现问题。
  • 反射技术 - 反射机制允许程序在运行时动态获取类的信息,创建对象等。

4.提高反射的性能 setAccessable?

  • 使用setAccessible(true)

通过setAccessible方法可以关闭Java语言访问检查,提高反射的效率。这个方法可以提高直接访问私有属性和方法的效率。

  • 缓存反射对象

可以缓存反射调用的Method和Field对象,避免重复获取,因为获取反射对象的过程比较消耗性能。

5.静态代理与动态代理的区别?

  • 实现时机不同

静态代理在编译时就已经实现了代理类,而动态代理是在运行时动态生成代理类。

  • 实现方式不同

静态代理在编译时生成的代理类需要实现与目标对象相同的接口,然后在代理类中进行功能增强。动态代理是利用JDK的Proxy类或第三方库在运行时动态生成目标类的代理对象。

  • 灵活性不同

静态代理的代理类只能为一个目标对象服务,如果要为多个目标对象服务需要定义不同的代理类。动态代理可以通过参数不同,为不同的目标对象生成代理实例,灵活性更高。

  • 易用性不同

静态代理需要额外定义许多代理类,工作量大,不易管理。动态代理可以直接使用JDK的Proxy类或第三方框架,使用更加方便。

  • 接口要求不同

静态代理要求目标对象必须实现接口,否则无法使用接口进行编程。动态代理的目标对象可以是类或者接口。

静态代理

  1. 定义接口:
java

Copy code

public interface IHello {
    void sayHello(); 
}

2.实现类:

java

Copy code

public class HelloImpl implements IHello {

    @Override
    public void sayHello() {
        System.out.println("Hello World!");
    }
}

3.代理类:

java

Copy code

public class HelloProxy implements IHello {

    private HelloImpl helloImpl;

    public HelloProxy() {
        helloImpl = new HelloImpl();
    }

    @Override
    public void sayHello() {
        //额外功能
        System.out.println("开始代理");
        
        helloImpl.sayHello();
        
        //额外功能
        System.out.println("结束代理");
    }
}

4.测试:

java

Copy code

public class ProxyTest {
    public static void main(String[] args) {
        IHello helloProxy = new HelloProxy();
        helloProxy.sayHello(); 
    }
}

输出:

开始代理

Hello World!

结束代理

动态代理

  1. 定义与静态代理相同的接口IHello和实现类HelloImpl
  2. 代理处理器类:
java

Copy code

public class DynamicProxy implements InvocationHandler {

    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始代理");
        
        Object result = method.invoke(target, args);
        
        System.out.println("结束代理");
        return result;
    }
}

3.获取代理对象:

java

Copy code

IHello hello = (IHello) Proxy.newProxyInstance(
  HelloImpl.class.getClassLoader(), 
  new Class[]{IHello.class}, 
  new DynamicProxy(new HelloImpl()));

4.测试:

java

Copy code

public class ProxyTest {
  public static void main(String[] args) {
    IHello hello = getProxy();
    hello.sayHello();
  }
  
  private static IHello getProxy() {
    // 步骤3代码
  }
}

输出与静态代理相同。

6.是否会dubbo?

  • Dubbo是什么

Dubbo是阿里巴巴开源的一个高性能、轻量级的Java RPC框架。其架构图主要包含:服务提供者、服务消费者、注册中心和监控中心四部分。利用Dubbo可以很方便地实现服务化,以及SOA服务治理架构。

  • Dubbo的工作原理

Dubbo的工作原理主要是基于RPC远程调用。服务提供者启动时会将自己提供的服务注册到注册中心,同时开启RPC服务器监听服务请求。服务消费者启动时会向注册中心订阅自己需要的服务,REGISTER中心会返回服务提供者的地址列表。然后服务消费者会基于RPC协议向提供者发送服务调用请求,提供者收到请求后执行服务并返回结果给消费者。

  • Dubbo的优点

Dubbo最大的优点是透明化、易用性强。采用全Spring配置方式,可以和Spring程序无缝集成。另外Dubbo实现了软负载均衡及故障容错机制,服务淘汰及自我保护机制,在大并发下保证系统可用性。

  • Dubbo的典型应用

Dubbo最典型的应用场景是跨系统的分布式服务调用。如电商系统中订单服务要调用用户服务获取用户信息,调用商品服务获取商品信息。Dubbo可以提供透明的跨系统调用,实现SOA服务治理。

7.排查full gc?

  • 观察GC日志,注意full gc的次数、耗时以及再次full gc的间隔时间,如果过于频繁可能是内存溢出导致。
  • 使用jstat -gc utilization工具观察老年代占用率,如果接近100%时就会引发full gc。可以适当提高老年代比例避免memory exhaustion。
  • 生成heap dump进行脱机分析,查看对象存活数量及大小,找出是否存在存活时间过长的对象引发内存泄漏。

8.提高数据库查询性能?

  • 优化查询语句,使用Explain查看执行计划,避免全表扫描,使用索引进行查询。使用合理的条件过滤,避免返回大量无用数据。
  • 索引
  • redis

9.大学中印象最深的课程?

操作系统

10.最熟悉的算法?

二分查找

11.平时学习技术的途径和方法?

网站、自学

12.对哪种数据结构印象深刻?Java里怎么用的??

HashMap

13.校园实践的收获?遇到过哪些问题?

大一志愿服务

14.密码学:常见的对称加密和非对称加密算法?RSA为什么比DES效率高?

  • 常见的对称加密算法有DES、AES等,特点是加密和解密使用同一密钥。

  • 常见的非对称加密算法有RSA、ECC等,特点是加密和解密使用不同的密钥。

  • RSA之所以效率高于DES:

​ RSA可以选择密钥长度,典型取1024或2048位,密钥越大加密强度越高。DES密钥仅56位。

15.为什么想来广州?

16.项目是基于微服务架构,怎么分割不同的架构的?

  • 按业务领域来拆分,不同业务领域的服务可以拆分出来,比如用户服务、订单服务、支付服务等。
  • 按团队结构来拆分,不同的服务可以由不同的团队来负责。
  • 将对外提供的开放API拆分为独立服务。
  • 将一些通用能力如日志、配置、监控等拆分出基础服务。

17.spring框架,AOP

  • AOP的概念 - 在程序运行期间,动态地将代码切入到方法或者函数的调用点上的这种编程方式,可以不修改源代码实现对程序功能的增强。
  • AOP的实现原理 - Spring AOP使用了动态代理,在运行时通过生成代理对象,实现对目标对象方法的拦截从而实现增强功能。
  • AOP的重要组件 - aspect、pointcut、advice等,分别用于声明切面、确定joinpoint、执行增强代码。
  • AOP的主要作用 - 日志记录、性能监控、安全控制、事务处理等方面对程序进行增强。
  • AOP和OOP的区别 - OOP是静态的代码封装和重用,而AOP是动态地通过代理方式实现运行期间的代码增强。
  • Spring AOP与 AspectJ AOP的区别 - Spring只支持方法级别的切入,而AspectJ通过修改字节码支持类和方法级别的切入。
  • AOP的典型应用 - Spring事务管理就是通过AOP实现的,转译了业务方法的调用过程,减少了重复代码。
  • 如何优化AOP的性能 - 采用AspectJ编译时织入提高性能,只为Really需要的Joinpoint生成代理等。

1、定义一个接口及其实现类:

java

Copy code

public interface UserService {
    void addUser();
}

public class UserServiceImpl implements UserService {
    public void addUser() {
        // 方法实现 
    }
}

2、定义一个切面类:

java

Copy code

@Aspect
public class LoggingAspect {

    @Before("execution(* com.example.UserServiceImpl.addUser(..))")
    public void logBefore(JoinPoint joinPoint) {
        // 前置通知实现 
    }

    @AfterReturning("execution(* com.example.UserServiceImpl.addUser(..))")
    public void logAfter(JoinPoint joinPoint) {
        // 后置通知实现
    }
}

这里通过@Before和@AfterReturning注解定义了前置通知和后置通知。

3、配置Spring AOP扫描该切面类:

java

Copy code

@EnableAspectJAutoProxy
@Configuration
public class AppConfig {

}

4、调用UserService的addUser方法将自动触发前置通知和后置通知的执行。

18.拦截器底层协议是什么?

  • 拦截器的实现是基于Java的动态代理机制,Spring AOP与拦截器实现类似。
  • Spring MVC中的拦截器通过HandlerInterceptor接口实现请求拦截,底层是基于Servlet过滤器链。
  • 拦截器链中的拦截器实例是以单例模式管理的,线程不安全需要注意。
  • 拦截器只能拦截Controller请求,对静态资源没有效果。Filter过滤器可以处理更底层的请求信息。

拦截器的根本规范就是JSR-250,这可以看作是它的底层协议。

19.怎么保证单点登录?

单点登录(Single Sign On,SSO)的核心理念是实现一次登录,处处可达。理解SSO的关键是:

  • 单一认证系统

这是一个统一的认证系统(可基于服务或OAuth),所有其他应用依赖这个系统进行认证,不再各自实现认证机制。

  • 认证信息共享

这个统一认证系统负责对用户进行认证,并提供认证信息(如授权令牌)给其他应用,以实现认证信息的共享。

  • 认证信息有效性

认证信息需要在一定时间内保持有效,在有效期内访问其他应用都无需重新认证。

  • 应用信任联盟

所有的应用都信任这个统一认证系统,并基于它提供的认证信息认可用户身份。

  • 无缝切换

用户可以在一个应用进入另一个应用,没有认证界限,实现了真正的单点体验。

所以SSO的本质是:依赖统一认证,认证信息共享,实现一次登录多处受信,无需重复登录。

使用JWT(JSON Web Token)实现单点登录的流程如下:

  • 用户使用用户名密码首次在认证服务器登录
  • 认证服务器验证用户信息无误后,生成一个JWT,并将用户信息、权限等数据编码进JWT
  • 客户端拿到JWT,保存到本地(比如浏览器localStorage)
  • 访问其他需要权限验证的服务器时,客户端带上这个JWT
  • 服务器通过校验JWT签名等信息,认证用户身份和权限
  • 这样客户端在多个服务器之间就可以通过这个JWT实现统一的认证和鉴权

JWT自包含了用户认证信息,不同服务器可以共享解析,无需每个服务器单独认证,即实现了SSO(Single Sign On)。

JWT也可以设置过期时间,单点登录后一定时间内访问都无需重新登录,提升了用户体验。

当JWT过期时,需要重新获取新的JWT才能继续访问,以保证SSO的安全性。

所以基于JWT的单点登录,主要依赖于JWT作为用户身份令牌在多个系统中共享,省去重复认证的步骤,从而实现单点登录的效果。

20.项目用到了spring boot的什么API?

  • 自动配置 - 说明使用了Spring Boot的自动配置功能。
  • Starter - 说明使用了哪些Spring Boot Starter模块,如spring-boot-starter-web、spring-boot-starter-jdbc等,快速引入需要的依赖。

21.mybatis 一级缓存二级缓存,#和$的区别?

  • 一级缓存是SqlSession级别的缓存,同一个SqlSession查询过的数据会被缓存,多次查询从缓存中直接获取,默认开启。
  • 二级缓存是SqlSessionFactory级别,多个SqlSession可以共用二级缓存,需要手动配置开启和清空,效果更好。
  • 主要区别是一级缓存仅在一个SqlSession内有效,二级缓存对整个MyBatis系统都有效。
  • #表示一个占位符,它可以限制变量的类型。#{name} 会限制name必须为字符串类型。
  • 表示拼接SQL字符串,对变量类型不做限制。表示拼接SQL字符串,对变量类型不做限制。可以接受任何类型的变量。
  • 注意需要转义为需要转义为{},并且外面要用一个字符串引起来。
  • 一般来说为了安全性,尽量使用#参数占位符。

22.有没有在linux部署过项目?

什么情况下打包为war包:

Java Web项目、不包含Tomcat依赖的项目

什么情况下打包为jar包:

SpringBoot项目、SpringCloud项目

打包, 将war包上传到云服务器的webapps目录

使用IDEA打包jar,直接将JAR 放入服务器 使用命令:

java -jar

使用后台运行进程
nohup java -jar

23.怎么想到用redis做限流的?

  • 内存存储:Redis是一个内存数据库,它能够快速读取和写入数据,这使得它非常适合用于高速的限流决策。在Redis中执行限流操作比在传统数据库中更快速。
  • 过期时间:Redis支持为存储的数据设置过期时间。这意味着你可以为每个令牌或限流规则设置一个超时时间,一旦时间到期,令牌将自动删除,从而不再占用内存。
  • 数据结构:Redis提供了多种数据结构,如有序集合(sorted set)和列表,这些数据结构非常适合用于实现不同类型的限流算法,如令牌桶算法或漏桶算法。

24.怎么防sql注入?

PreparedStatement来执行参数化查询。用户输入通过setString方法绑定到查询的占位符位置,而不是直接将用户输入嵌入到SQL查询中。

使用ORM框架

25.JWT单点登陆,怎么理解单点?

26.在学校的经历?

27.最近读什么书?

28.了解Linux、Docker吗?

29.平时如何学习新的知识?

30.竞赛获奖?

31.Redis和MySQL数据一致性?

Cache Aside Pattern 是我们平时使用比较多的一个缓存读写模式,比较适合读请求比较多的场景。

  • 先更新 DB
  • 然后直接删除 cache 。

:

  • 从 cache 中读取数据,读取到就直接返回
  • cache中读取不到的话,就从 DB 中读取数据返回
  • 再把数据放到 cache 中。

32.职业规划?

成为一名软件架构师:

我计划不断深入学习关键技术。密切关注新兴技术趋势,包括人工智能和大数据处理。积累更多的项目经验。提高我的团队协作和领导技能,以便有效地传达架构决策和理念。

33.学习方式?