2024年java面试(三)--spring篇

文章目录

  • 1.spring的bean是线程安全的吗?
  • 2.什么是Spring IOC 容器?
  • 3.DI 依赖注入
  • 4.如何实现一个IOC容器
  • 5.Spring 的 IoC支持哪些功能?
  • 6.IOC初始化过程
  • 7.面向切面编程(AOP)
  • 8.AOP 思想
  • 9.AOP的应用场景
  • 10.AOP通知类型
  • 11.Spring AOP编程两种方式
  • 12.使用注解@Aspect流程
  • 13.AOP的相关术语
  • 14.AOP编程底层实现机制


1.spring的bean是线程安全的吗?

spring的默认bean作用域是单例的,单例的bean不是线程安全的,但是开发中大部分的bean都是无状态的,不具备存储功能,比如controller、service、dao,他们不需要保证线程安全。
如果要保证线程安全,可以将bean的作用域改为prototype,比如像Model View。
另外还可以采用ThreadLocal来解决线程安全问题。ThreadLocal为每个线程保存一个副本变量,每个线程只操作自己的副本变量。


2.什么是Spring IOC 容器?

IoC(Inverse of Control:控制反转)是⼀种设计思想,就是将原本在程序中⼿动创建对象的控制权,交由Spring框架来管理。 IoC 在其他语⾔中也有应⽤,并⾮ Spring 特有。
IoC 容器是 Spring⽤来实现 IoC 的载体,将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注⼊。这样可以很⼤程度上简化应⽤的开发,把应⽤从复杂的依赖关系中解放出来。 IoC 容器就像是⼀个⼯⼚⼀样,当我们需要创建⼀个对象的时候,只需要配置好配置⽂件/注解即可,完全不⽤考虑对象是如何被创建出来的。


3.DI 依赖注入

DI:(Dependancy Injection:依赖注入)站在容器的角度,将对象创建依赖的其他对象注入到对象中。


4.如何实现一个IOC容器

① 配置文件配置包扫描路径
② 递归包扫描获取.class文件
③ 反射、确定需要交给IOC管理的类
④ 对需要注入的类进行依赖注入

  • 配置文件中指定需要扫描的包路径
  • 定义一些注解,分别表示访问控制层、业务服务层、数据持久层、依赖注入注解、获取配置文件注解
  • 从配置文件中获取需要扫描的包路径,获取到当前路径下的文件信息及文件夹信息,我们将当前路径下所有以.class结尾的文件添加到一个Set集合中进行存储
  • 遍历这个set集合,获取在类上有指定注解的类,并将其交给IOC容器,定义一个安全的Map用来存储这些对象
  • 遍历这个IOC容器,获取到每一个类的实例,判断里面是有有依赖其他的类的实例,然后进行递归注入。

5.Spring 的 IoC支持哪些功能?

Spring 的 IoC 设计支持以下功能:

①依赖注入
②依赖检查
③自动装配
④支持集合
⑤指定初始化方法和销毁方法
⑥支持回调某些方法(但是需要实现 Spring 接口,略有侵入)

其中,最重要的就是依赖注入,从 XML 的配置上说,即 ref 标签。对应 Spring RuntimeBeanReference 对象。

对于 IoC 来说,最重要的就是容器。容器管理着 Bean 的生命周期,控制着 Bean 的依赖注入。


6.IOC初始化过程

IOC容器初始化是由refresh()方法来启动的,这个方法标志着IOC容器的正式启动。Spring将IOC容器启动的过程分开,并使用不同的模块来完成,如使用ResourceLoader,BeanDefinition等模块, IOC容器的启动主要包括三个过程:

Resource定位过程: Resource定位指beanDefinition的资源定位,由ResourceLoader通过统一的Resource接口来完成,这个Resource对各种形式的BeanDefinition的使用都提供了统一的接口。这个过程类似于容器寻找数据的过程。

BeanDefinition的载入: BeanDefinition载入过程指的是把用户定义好的Bean表示为容器内部的数据结构,这个容器的数据结构其实就是BeanDefinition。实际上BeanDefinition就是POJO对象在容器的抽象,通过BeanDefinition来定义的数据结构,像是世间万物在java中的抽象,java的对象又在容器中的抽象就是BeanDefinition。

向容器注册BeanDefinition: 这个注册过程是通过调用BeanDefinitionRegistry接口来完成的,就是把载入过程中解析得到的BeanDefinition向IOC容器进行注册。通过下面的源码可以得到,注册过程就是在IOC容器将BeanDefinition注入到一个HashMap中,IOC容器就是通过这个HashMap来持有BeanDefinition数据的。


7.面向切面编程(AOP)

2024年java面试(三)--spring篇_第1张图片
AOP (Aspect Oriented Programing) 称为:面向切面编程,它是一种编程思想。

AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码的编写方式(例如性能监视、事务管理、安全检查、缓存、日志记录等)。

Spring AOP就是基于动态代理的,如果要代理的对象,实现了某个接⼝,那么Spring AOP会使⽤JDKProxy,去创建代理对象,⽽对于没有实现接⼝的对象,就⽆法使⽤ JDK Proxy 去进⾏代理了,这时候Spring AOP会使⽤基于asm框架字节流的Cglib动态代理 ,这时候Spring AOP会使⽤ Cglib ⽣成⼀个被代理对象的⼦类来作为代理。


8.AOP 思想

基于代理思想,对原来目标对象,创建代理对象,在不修改原对象代码情况下,通过代理对象,调用增强功能的代码,从而对原有业务方法进行增强 ! 切面:需要代理一些方法和增强代码 。


9.AOP的应用场景

场景一: 记录日志

场景二: 监控方法运行时间 (监控性能)

场景三: 权限控制(通过Around,可以在执行方法前进行权限验证)

场景四: 缓存优化 (第一次调用查询数据库,将查询结果放入内存对象, 第二次调用, 直接从内存对象返回,不需要查询数据库 )

场景五: 事务管理 (调用方法前开启事务, 调用方法后提交或者回滚、关闭事务 )


10.AOP通知类型

前置通知 Before advice:在连接点前面执行,前置通知不会影响连接点的执行,除非此处抛出异常

后置通知 After returning advice:在连接点正常执行完成后执行,如果连接点抛出异常,则不会执行

异常通知 After throwing advice:在连接点抛出异常后执行

最终通知 After (finally) advice:在连接点执行完成后执行,不管是正常执行完成,还是抛出异常,都会执行返回通知中的内容

环绕通知 Around advice:环绕通知围绕在连接点前后,能在方法调用前后自定义一些操作,还需要负责决定是继续处理 join point (调用 ProceedingJoinPoint 的 proceed 方法)还是中断执行


11.Spring AOP编程两种方式

①Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类植入增强代码。

②AsPectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持。


12.使用注解@Aspect流程

1.切面类 @Aspect: 定义切面类,加上@Aspect、@Component注解

2.切点 @Pointcut

3.Advice通知,在切入点上执行的增强处理,主要有五个注解

4.JoinPoint :方法中的参数JoinPoint为连接点对象,它可以获取当前切入的方法的参数、代理类等信息,因此可以记录一些信息,验证一些信息等;

@Aspect
@Component
//设置注解执行的顺序
@Order(1)
public class AspectTest {
 
    /**
     * 定义切点,切点为对应controller
     */
    @Pointcut("execution(public * com.example.zcs.Aop.controller.*.*(..))")
    public void aopPointCut(){
 
    }
 
    @Before("aopPointCut()")
    public void testbefor(JoinPoint joinPoint) {
        illegalParam(joinPoint);
        System.out.println("执行方法之前执行。。。。。");
    }
    
 
    @After("aopPointCut()")
    public void testAfter(JoinPoint joinPoint) {
        //illegalParam(joinPoint);
        System.out.println("执行方法之后执行。。。。。");
    }
 
    /**
     *获取请求参数
     * @param joinPoint
     * @return
     */
    private static void  illegalParam(JoinPoint joinPoint) {
        if(joinPoint == null){
            return;
        }
        boolean flag = false;
        try{
            // 参数值
            Object[] args = joinPoint.getArgs();
            if (args != null) {
                for (Object o : args) {
                    System.out.println(o);
 
                }
            }
        }catch(Exception e){
        }
    }
    
}


13.AOP的相关术语

Aspect(切面) : 是通知和切入点的结合,通知和切入点共同定义了关于切面的全部内容—它的功能、在何时和何地完成其功能

joinpoint(连接点) :所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.

Pointcut(切入点) :所谓切入点是指我们要对哪些joinpoint进行拦截的定义.
通知定义了切面的”什么”和”何时”,切入点就定义了”何地”.

Advice(通知) :所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)

Target(目标对象) :代理的目标对象

weaving(织入) :是指把切面应用到目标对象来创建新的代理对象的过程.切面在指定的连接点织入到目标对象

Introduction(引介) :在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.


14.AOP编程底层实现机制

AOP 就是要对目标进行代理对象的创建, Spring AOP是基于动态代理的,基于两种动态代理机制: JDK动态代理和CGLIB动态代理

JDK动态代理
JDK动态代理,针对目标对象的接口进行代理 ,动态生成接口的实现类 !(必须有接口)
JDK动态代理的缺点: 只能面向接口代理,不能直接对目标类进行代理 ,如果没有接口,则不能使用JDK代理。
Cglib动态代理
Cglib动态代理基于父类,Cglib的引入为了解决类的直接代理问题(生成代理子类),不需要接口也可以代理 !
什么是cglib ? CGLIB(Code Generation Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。

静态代理
静态代理相当于是多写了一个代理类,在调用的时候调用的是代理类,在代理类中的处理还是原生的处理逻辑,不过在前后添加上需要添加的代码。 缺点:需要为每一个被代理的对象都创建一个代理类。
特点
代理角色和真实角色都需要实现同一个接口,
真实角色专注于自己的事情,
代理角色目的就是帮助真实角色完成一件事情
多线程的实现方式2:实现一个接口Runnable 使用的就是"静态代理"的思想

代理知识小结
区别
①Jdk代理:基于接口的代理,一定是基于接口,会生成目标对象的接口类型的子对象。
②Cglib代理:基于类的代理,不需要基于接口,会生成目标对象类型的子对象。
③Spring AOP 优先对接口进行代理 (使用Jdk动态代理)
④如果目标对象没有实现任何接口,才会对类进行代理 (使用cglib动态代理)

你可能感兴趣的:(面试题,java,面试,spring)