原力计划 Java岗大厂面试百日冲刺

 相信大家和我一样, 都有一个大厂梦 ,作为一名资深Java选手,深知面试重要性,接下来我准备用100天时间,基于Java岗面试中的高频面试题,以 每日3题 的形式,带你过一遍热门面试题及恰如其分的解答。当然,我不会太深入,因为我怕记不住!!

因此,不足的地方希望各位在评论区补充疑惑、见解以及面试中遇到的奇葩问法 ,希望这100天能够让我们有质的飞越,一起冲进大厂!!,让我们一起学(juan)起来!!!

在群友一致认为济南并感慨一番后,被作者告知这是 深圳 。。。

作者: 對你何止一句钟意 (mavic 2航拍)

车票

  • 面试题1:聊一下你对AOP的理解吧?
    • 追问1:Advice通知的类型有哪几种?
    • 追问2:在同一个切面(Aspect)中,不同Advice的执行顺序
  • 面试题2:AspectJ AOP 和 Spring AOP 有什么区别?
    • 追问1:了解JDK动态代理和CGLIB动态代理的原理么?他俩有哪些区别?
  • 面试题3:什么是基于Java的Spring注解配置? 给一些注解的例子

  本栏目Java开发岗高频面试题主要出自以下各技术栈: Java基础知识 、 集合容器 、 并发编程 、 JVM 、 Spring全家桶 、 MyBatis等ORMapping框架 、 MySQL数据库 、 Redis缓存 、 RabbitMQ消息队列 、 Linux操作技巧 等。

面试题1:聊一下你对AOP的理解吧?

   AOP (Aspect Oriented Programming),面向切面思想,是Spring的三大核心思想之一(两外两个:IOC-控制反转、DI-依赖注入)。AOP主要应用于处理一些 具有横切性质的系统级服务 ,如 日志收集 、 事务管理 、 安全检查(权限校验) 、 缓存 、 对象池管理 等。

  那么AOP是干啥的?在我们的程序中,经常存在一些系统性的需求,比如权限校验、记录日志等,这些代码会散落穿插在各个业务逻辑中,非常冗余且不利于维护。例如下面这个示意图:

  有多少业务操作,就要写多少重复的校验和日志记录代码,这显然是无法接受的。当然,用面向对象的思想,我们可以把这些 重复的代码抽离出来,写成公共方法 ,就是下面这样:

  这样,代码冗余和可维护性的问题得到了解决,但每个业务方法中依然要依次手动调用这些公共方法,也是略显繁琐。有没有更好的方式呢?有的,那就是 AOP ,AOP将权限校验、日志记录等非业务代码完全提取出来,与业务代码分离,并寻找节点切入业务代码中:

  使用AOP的好处主要是 降低模块的耦合度 、 使系统容易扩展 、 提高代码复用性 。

  简单地去理解,其实AOP要做三类事:

  • 在哪里切入,也就是权限校验等非业务操作在哪些业务代码中执行。
  • 在什么时候切入,是业务代码执行前还是执行后。
  • 切入后做什么事,比如做权限校验、日志记录等。

因此,AOP的体系可以梳理为下图:

AOP的一些概念:

  • 切入点(Pointcut) :决定处理如权限校验、日志记录等在何处切入业务代码中(即织入切面)。切点分为execution方式和annotation方式。前者可以用路径表达式指定哪些类织入切面,后者可以指定被哪些注解修饰的代码织入切面。
  • 通知(Advice) :我们也叫它处理(即 “切面”对于某个“连接点”所产生的动作 ),包括处理时机和处理内容。处理内容就是要做什么事,比如校验权限和记录日志。处理时机就是在什么时机执行处理内容,分为前置处理(即业务代码执行前)、后置处理(业务代码执行后)等。
  • 切面(Aspect) :即Pointcut和Advice。
  • 连接点(Joint point) :是程序执行的一个点。例如,一个方法的执行或者一个异常的处理。在 Spring AOP 中,一个连接点总是代表一个方法执行。
  • 织入(Weaving) :就是通过动态代理,在目标对象方法中执行处理内容的过程。
  • 目标对象(Target Object) :被一个或者多个切面所通知的对象。
  • AOP代理(AOP Proxy) 在Spring AOP中有两种代理方式, JDK动态代理和CGLIB代理 。

追问1:Advice通知的类型有哪几种?

在AOP术语中,切面的工作被称为 通知 ,实际上是 程序执行时要通过SpringAOP框架触发的代码段 。

Spring切面可以应用5种类型的通知:

在被通知的方法调用之前和调用之后执行自定义的行为

追问2:在同一个切面(Aspect)中,不同Advice的执行顺序

 异常情况下:

/*************不同Advice的执行顺序*****************/
1. around before advice
2. before advice
3. target method (执行代码段)
4. around after advice
5. after advice
/*******************前五个都一样*******************/
6. afterReturning
/*************************************************/

 异常情况下:

/*************不同Advice的执行顺序*****************/
1. around before advice
2. before advice
3. target method (执行代码段)
4. around after advice
5. after advice
/*******************前五个都一样*******************/
6. afterThrowing:异常发生
7. java.lang.RuntimeException: 异常发生
/*************************************************/

被群友一致认为的济南泉城广场。。。坐标: 深圳

作者: 對你何止一句钟意 (航拍)

面试题2:AspectJ AOP 和 Spring AOP 有什么区别?

AOP实现的关键在于 代理模式 ,AOP代理主要分为 静态代理 和 动态代理 。

  • 静态代理的代表为AspectJ;
  • 动态代理则以Spring AOP为代表;

Spring AOP和AspectJ有不同的目标。

  • Spring AOP旨在通过Spring IoC提供一个简单的AOP实现,以解决编码人员面临的最常出现的问题。这并不是完整的AOP解决方案, 它只能用于Spring容器管理的beans 。

  • 另一方面,AspectJ是最原始的AOP实现技术,提供了玩这个的AOP解决方案。AspectJ更为健壮,相对于Spring AOP也显得更为复杂。值得注意的是,AspectJ能够被应用于所有的领域对象。

从原理上看:

Spring AOP

  1. 基于动态代理来实现,默认如果使用接口的,用JDK提供的动态代理实现,如果是方法则使用CGLIB实现

  2. Spring AOP需要依赖IOC容器来管理,并且只能作用于Spring容器,使用纯Java代码实现

  3. 在性能上,由于Spring AOP是基于动态代理来实现的,在容器启动时需要生成代理实例,在方法调用上也会增加栈的深度,使得Spring AOP的性能不如AspectJ的那么好

AspectJ

AspectJ属于静态代理(织入),通过修改代码来实现,有如下几个织入的时机:

编译期织入
编译后织入
类加载后织入

  AspectJ可以做Spring AOP干不了的事情,它是AOP编程的完全解决方案,Spring AOP则致力于解决企业级开发中最普遍的AOP(方法织入)。而不是成为像AspectJ一样的AOP方案。

  因为AspectJ在实际运行之前就完成了织入,所以说它生成的类是没有额外运行时开销的

指标项Spring AOPAspectJ
使用语言在纯 Java 中实现使用 Java 编程语言的扩展实现
是否需要编译不需要单独的编译过程除非设置 LTW,否则需要 AspectJ 编译器 (ajc)
织入方式只能使用运行时织入运行时织入不可用。支持编译时、编译后和加载时织入
织入能力功能不强-仅支持方法级编织更强大 – 可以编织字段、方法、构造函数、静态初始值设定项、最终类/方法等……。
适用范围只能在由 Spring 容器管理的 bean 上实现可以在所有域对象上实现
切入点要求仅支持方法执行切入点支持所有切入点
代理局限代理是由目标对象创建的, 并且切面应用在这些代理上在执行应用程序之前 (在运行时) 前, 各方面直接在代码中进行织入
性能比 AspectJ 慢很多更好的性能
复杂度易于学习和应用相对于 Spring AOP 来说更复杂

追问1:了解JDK动态代理和CGLIB动态代理的原理么?他俩有哪些区别?

  Spring AOP中的动态代理主要有两种方式, JDK动态代理 和 CGLIB动态代理 :

JDK动态代理 :是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用 InvokeHandler 来处理,他有一个限制,就是 它只能为接口创建代理实例,那么对于没有通过接口定义业务方法的类 ,就要用 CGLIB动态代理 了。

CGLIB(Code Generation Library)动态代理 :是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。CGLIB通过继承方式实现代理,在子类中采用方法拦截的技术拦截所有父类方法的调用并顺势织入横切逻辑。

JDK动态代理具体实现原理:

  • 通过实现InvocationHandler接口创建自己的调用处理器;
  • 通过为Proxy类指定ClassLoader对象和一组interface来创建动态代理;
  • 通过反射机制获取动态代理类的构造函数,其唯一参数类型就是调用处理器接口类型;
  • 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数参入;

  JDK动态代理是面向接口的代理模式,如果被代理目标没有接口那么Spring也无能为力,Spring通过Java的反射机制生产被代理接口的新的匿名实现类,重写了其中AOP的增强方法。

CGLib动态代理:

  利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

  1. 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP;
  2. 如果目标对象实现了接口,可以强制使用CGLIB实现AOP;
  3. 如果目标对象 没有实现了接口 , 必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换 ;

3、两者对比:

面向接口的
对指定的类生成一个子类,覆盖其中的方法

开阔!!坐标: 深圳 。。。

作者: 對你何止一句钟意 (航拍)

面试题3:什么是基于Java的Spring注解配置? 给一些注解的例子

  基于Java的配置,允许你在少量的Java注解的帮助下进行大部分Spring配置,而非通过XML文件。当然,也不不建议啥都用注解配置,毕竟如果修改就要动class文件很麻烦。因此建议: 不会修改、极少修改的用注解,会修改的用xml配置,如AOP的配置我就用XML,因为这个需要改的场景比较多。

  以 @Configuration 注解 为例,它用来标记类可以当做一个bean的定义,被Spring IOC容器使用。另一个是通过 @Bean注解 ,它表示此方法将要返回一个对象,作为一个bean注册进Spring应用上下文。

@Configuration
public class StudentConfig {
 
    @Bean
    public StudentBean myStudent() {
 
        return new StudentBean();
    }

怎样开启注解装配呢?

  注解装配在默认情况下是不开启的,为了使用注解装配,我们必须在Spring配置文件中配置 <context:annotation-config/> 元素。

一些常见的注解:

1、@Component :

  这将 java 类标记为 bean。它是任何 Spring 管理组件的通用构造型。spring 的组件扫描机制现在可以将其拾取并将其拉入应用程序环境中。

2、@Controller :

  这将一个类标记为 Spring Web MVC 控制器。标有它的 Bean 会自动导入到 IoC 容器中。

3、 @Service :

  此注解是组件注解的特化。它不会对 @Component 注解提供任何其他行为。我们可以在服务层类中使用 @Service 而不是 @Component,因为它以更好的方式指定了意图。

4、@Repository :

  这个注解是具有类似用途和功能的 @Component 注解的特化。它为 DAO 提供了额外的好处。它将 DAO 导入 IoC 容器,并使未经检查的异常有资格转换为 Spring DataAccessException。

5、@Required :

  这个注解表明bean的属性必须在配置的时候设置,通过一个bean定义的显式的属性值或通过自动装配,若@Required注解的bean属性未被设置,容器将抛出 BeanInitializationException 。

示例:

public class Employee {
 
    private String name;
    @Required
    public void setName(String name){
 
        this.name=name;
    }
    public string getName(){
 
        return name;
    }
}

6、@Autowired :

  @Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。 @Autowired 注解提供了更细粒度的控制,包括在何处以及如何完成自动装配 。它的用法和@Required一样,修饰setter方法、构造器、属性或者具有任意名称和/或多个参数的PN方法。

public class Employee {
 
    private String name;
    @Autowired
    public void setName(String name) {
 
        this.name=name;
    }
    public string getName(){
 
        return name;
    }

@Autowired和@Resource 的区别

@Autowired可用于:构造函数、成员变量、Setter方法

@Autowired和@Resource之间的区别

  • @Autowired :默认是按照 类型 装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。

  • @Resource :默认是按照 名称 来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。

7、@Qualifier :

  当创建多个相同类型的 bean 并希望仅使用属性装配其中一个 bean 时,可以使用@Qualifier 注解和 @Autowired 通过指定应该装配哪个确切的 bean 来消除歧义。

8、@RequestMapping :

  @RequestMapping 注解用于将特定 HTTP 请求方法映射到将处理相应请求的控制器中的特定类/方法。此注释可应用于两个级别:

  • 类级别:映射请求的 URL
  • 方法级别:映射 URL 以及 HTTP 请求方法

每日小结

  今天我们复习了面试中常考的 Spring框架 相关的三个问题,你做到心中有数了么? 对了,如果你的朋友也在准备面试,请将这个系列扔给他,如果他认真对待,肯定会感谢你的!! 好了,今天就到这里,学废了的同学, 记得在评论区留言:打卡。 ,给同学们以激励。

需要资料的小伙伴,点赞加收藏,关注我之后添加小助理vx:bjmsb0606006 即可获取免费下载方式

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值