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返回实例列表
- 负载均衡选择实例调用