Spring相关面试题--总结版

springboot:

作用:

  • 主要重点是自动配置和内嵌服务器和约定大于配置(通过约定的方式来降低开发人员的配置,比如AutoConfiguration的按需加载):在run里面的refresh相关地方
  • 通过spring的条件配置决定哪些bean可以配置,然后定义成Configuration,配置到META-INF下的AutoConfiguration.imports中
    • 常见条件配置:
      • @Conditional(.class)有class才创建

run和@springbootApplication的联动

  • @springbootApplication:
    • springbootconfiguration:即configuration,配置类
    • @Enableautoconfiguration:@Enable一脉相承,都是通过Import将相关bean进行加载
      • @AutoConfigurationPackage

        • 将注解所在的包及其子包中的所有组件自动注册为 Spring 的 Bean,这样就不需要手动在配置文件中指定这些包。

      • @Import(AutoConfigurationImportSelector.class)

        • AutoConfigurationImportSelector会去扫描,然后进行自动配置,具体看这些自动配置的条件是否满足

    • componentscan:扫描包
  • run:
    • 创建应用上下文
    • 准备上下文:
    • 刷新上下文:主要就是创建BeanFactory,然后再通过工厂实例化,加载tomcat

启动流程:

  • 准备环境:加载配置文件
  • 创建applicationcontext
  • 执行ApplicationContextInitializer
  • 加载并注册bean
  • 自动配置
  • refreshApplicationContext,启动嵌入的tomcat

Spring:

IOC:

  • 将对象的创建、维护、对象之间的关系交给容器去控制。
  • 好处:
    • 不用关心细节
    • 不用创建多个
  • 实现方式:
    • 依赖注入:@Resources、@Autowired
  • 实现原理:
    • bean的定义(beandefine)、bean的注册(beanDefineRegistry)、bean的创建(BeanFactory有beanDefine),bean的存储(ApplicationContext)

DI作用和实现

  • 作用:用于将对象的依赖关系从外部注入,而不是自己创建和管理,解耦和简化代码,更细粒度的生命周期
  • 实现:通过xml、注解、配置
  • 原本简单工厂的OCP问题:通过依赖注入和配置来解决简单工厂的问题,比如就像一个bean会有beandefinition,注册进beanfactory(注意:AbstractAutowiredCapableBeanFactory继承了defaultlistablebeanfactory实现了beanregistry接口),存在一个map里面,实现动态的注入。

作用域:

  • singleton
  • prototype:每次请求都会创建
  • request:一次HTTP请求对应一次
  • session:一次HTTP会话对应一次
  • webSocket:一次websocket连接创建一个
  • 自定义

生命周期

都在AbstractAutowiredCapableBeanFactory中调用

  • 实例化
  • 设置属性
  • 下面就是初始化
  • 检查Aware相关接口:可以和框架内部组件交互,比如说获取属性值啥的。
  • beanPostprocessorbefore:修改bean的状态
  • afterpropertiesSet:实现initializingBean,自定义逻辑
  • init-method:自定义逻辑,在项目里是启动了worker()后台线程
  • beanPostprocessorafter:AOP,WrapIfNecessary
  • Desrtuction:如果实现了DisposableBean接口或者定义了销毁方法,就会注册一个销毁回调。
  • 使用
  • 调用destroy方法(在DisposableBeanAdapter中)
  • 调用自定义的destroy-method方法

初始化和实例化的区别?

  • 实例化是指创建了对象,但没有进行任何处理(懒加载针对这里)
  • 实例化是完成了属性注入和配置

AOP:

把一下公共的部分提取出来,减少代码量,事务、日志、权限管理、缓存、异常处理

动态代理不是基于aop,是aop基于动态代理

  • 切面
  • 切点:要拦截的哪些连接点
  • 通知
  • 连接点:方法的执行
  • 目标:增强的对象
  • 代理对象
  • 织入
  • //返回值 包名 类名 方法名 入参
    execution(String com.example.service.UserService.*(..))
    //注解
    @Before("@annotation(org.springframework.transaction.annotation.Transactional)")
    

    顺序around before around 具体afterreturning或者afterthrowing  after

代理模式?

  • 代理类和目标类

  • 静态代理 

    • 静态代理就是保留目标对象,去增强去调用

    • 假设有一个目标对象OrderService

      public class Client {
          public static void main(String[] args) {
              // 创建目标对象
              OrderService target = new OrderServiceImpl();
              // 创建代理对象
              OrderService proxy = new OrderServiceProxy(target);
              // 调用代理对象的代理方法
              proxy.generate();
              proxy.modify();
              proxy.detail();
          }
      }

      缺点是一个接口就要写一个代理类,导致类爆炸

  • 动态代理
    •  JDK动态代理:这里可能会想,那岂不是所有方法都要执行invoke了,其实可以在invoke中加判断是否被这个注解修饰了
    • public static void main(String[] args) {
              // 第一步:创建目标对象
              OrderService target = new OrderServiceImpl();
              // 第二步:创建代理对象
              OrderService orderServiceProxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), 调用处理器对象);
              // 第三步:调用代理对象的代理方法
              orderServiceProxy.detail();
      }
      
      public class TimerInvocationHandler implements InvocationHandler {
          // 目标对象
          private Object target;
      
          // 通过构造方法来传目标对象
          public TimerInvocationHandler(Object target) {
              this.target = target;
          }
      
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
              return null;
          }
      }

    • CGLIB动态代理:通过继承的方式
      •  
        public static void main(String[] args) {
                // 创建字节码增强器
                Enhancer enhancer = new Enhancer();
                // 告诉cglib要继承哪个类
                enhancer.setSuperclass(UserService.class);
                // 设置回调接口
                enhancer.setCallback(方法拦截器对象);
                // 生成源码,编译class,加载到JVM,并创建代理对象
                UserService userServiceProxy = (UserService)enhancer.create();
        
                userServiceProxy.login();
                userServiceProxy.logout();
        
            }
        public class TimerMethodInterceptor implements MethodInterceptor {
            @Override
            public Object intercept(Object target, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                // 前增强
                long begin = System.currentTimeMillis();
                // 调用目标
                Object retValue = methodProxy.invokeSuper(target, objects);
                // 后增强
                long end = System.currentTimeMillis();
                System.out.println("耗时" + (end - begin) + "毫秒");
                // 一定要返回
                return retValue;
            }
        }

        为什么有了JDK动态代理还要有CGLIB:无接口的类和更高的性能

事务传播机制:

  • Mandatory:强制有事务
  • require:无事务自己启动一个
  • require_new:新建一个事务,前面的挂起
  • support:有就加入,没有就普通执行
  • not_supported:有事务就挂起
  • never:有事务报异常
  • nested:嵌套,子事务回滚不影响父事务
  • 失效情况:
    • 事务方法调用非事务方法,即在代理对象中调用target
    • @Transactional AOP失效:非public、final(无法被子类化或者覆盖)、static(属于类不属于对象)相关的方法
    • rollback设置错误
    • 异常报备捕获
    • 多线程,基于ThreadLocal实现

循环依赖

  • 三级缓存:singletonFactories,单例bean的创建工厂
  • 二级缓存:earlySingletonObjects初始化好未完全创建好的单例bean,打破循环依赖
  • 一级缓存:singletonObjects,完整的单例Bean
  • creatingset:查看是否发生循环依赖

启动流程

  • 启动类加载器加载配置文件
  • 创建ApplicationContext实例
  • 读取配置扫描注解转换成beandefinition对象
  • 实例化BeanFactoryPostProcessor,对bean定义进行修改
  • 实例化BeanPostProcessor
  • 实例化和注入bean
  • 初始化bean
  • 发布事件

如果你自己来实现一个spring容器,你会怎么做才能支持IOC的各种特性

//todo

MVC:

  • 核心思想是将应用程序的表示和处理分开来
  • model:核心业务逻辑和数据
  • view:应用程序的用户界面
  • control:应用程序的处理逻辑

全局异常处理:

  • @ControllerAdvice
  • @ExceptionHandler
  • 依赖于拦截器链(共用的)

spring webflux:

Scheduler

Scheduler是Reactor中用于调度任务执行的抽象。Reactor提供了几种不同类型的Schedulers,用于不同的调度策略:

  • Schedulers.immediate():在当前线程上执行任务。
  • Schedulers.single():在单一后台线程上执行任务。
  • Schedulers.boundedElastic():适用于I/O阻塞操作的弹性线程池。
  • Schedulers.parallel():适用于CPU密集型操作的固定大小线程池。
  • Schedulers.fromExecutor():使用自定义Executor。

 Publishers (Flux and Mono)

  • Flux:用于表示0到N个元素的异步序列。Flux可以是无限的,并可以处理背压。
  • Mono:用于表示0到1个元素的异步序列。适用于只需要一个结果或没有结果的情况。

SpringCloud

nacos服务注册和服务发现的原理?

  • 注册:将自己的ip端口相关元数据发送给Nacos服务端(register消息
    • 有心跳机制和健康检查
  • 发现:discovery消息
    • nacos返回实例列表
    • 负载均衡选择实例调用
  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值