哈啦曼

Spring学习记录1
  1. Spring框架核心 IOC & AOP
    IoC(Inverse of Control-控制反转):只是一种设计思想,将对象的创建和管理工作交给Spring框架、IoC容器实现
    AOP(Aspect-Oriented Programming-面向切面编程):可以将一些非业务逻辑(事务、日志、权限..)嵌入到业务模块当中,以达到去重和解耦的作用,方便拓展

Spring AOP基于动态代理实现,当被代理对象为实现接口形式时,使用JDK Proxy去创建代理对象,对于没有实现接口的被代理对象,使用CGlib生成一个被代理对象的子类来作为代理

    Spring AOP 和 AspectJ AOP 有什么区别?   
    Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation),后者的运行效率比前者快很多
  1. 单例bean的线程安全问题
    Spring中的bean默认都是单例(singleton),那么在多线程情况下必然会产生线程安全问题,这样就要求在定义bean对象时避免出现可变成员变量(推荐使用ThreadLocal来保存可变成员变量),另外像Service、Dao这些对象都是无状态(没有实例变量)的,这种情况bean是线程安全的

  2. SpringMVC原理
    Java Web应用开发演变历程:
    Model 1时代:几乎全部由JSP页面组成,少量JavaBean处理数据库连接访问]
    ==> Model 2时代:Java Bean(Model)+ JSP(View)+Servlet(Controller)]
    ==> SpringMVC时代:Service 层(处理业务)、Dao 层(数据库操作)、Entity 层(实体类)、Controller 层(控制层,返回数据给前台页面)

    原理流程图:
    SpringMVC原理.png
    ①向服务器发送 HTTP 请求,请求被前端控制器 DispatcherServlet 捕获

    ②DispatcherServlet 根据 -servlet.xml 中的配置对请求的 URL 进行解析,得到请求资源标识符(URI)。然后根据该 URI,调用 HandlerMapping 获得该 Handler 配置的所有相关的对象(包括 Handler 对象以及 Handler 对象对应的拦截器),最后以HandlerExecutionChain 对象的形式返回

    ③DispatcherServlet 根据获得的Handler,选择一个合适的 HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的 preHandler(…)方法)

    ④提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。在填充Handler的入参过程中,根据你的配置,Spring 将帮你做一些额外的工作:

    • HttpMessageConveter:将请求消息(如 Json、xml 等数据)转换成一个对象,将对象转换为指定的响应信息。

    • 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等。

    • 数据格式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等。

    • 数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中。

    ⑤Handler(Controller)执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象;

    ⑥根据返回的ModelAndView,选择一个适合的 ViewResolver(必须是已经注册到 Spring 容器中的ViewResolver)返回给DispatcherServlet。

    ⑦ViewResolver 结合Model和View,来渲染视图。

    ⑧视图负责将渲染结果返回给客户端。

  3. @Transactional(rollbackFor = Exception.class)注解 --- 该注解如果不配置rollbackFor属性,事务只有在遇到RuntimeException的时候才会回滚,加上 rollbackFor=Exception.class,可以让事务在遇到非运行时异常时也回滚

  4. Spring框架用到的设计模式汇总:
    Spring用到的设计模式.png

  5. 观察者模式 & Spring事件驱动模型
    Spring 事件驱动模型就是观察者模式很经典的一个应用

    • 观察者模式:

    观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新

    • 事件机制的三个重要组成部分-事件源、事件、事件监听器,对应Spring中的实现:
      ①事件源 => ApplicationEventPublisher(事件发布接口)中的publishEvent方法发布事件 ,其默认实现AbstractApplicationContext中关键代码如下
     protected void publishEvent(Object event, @Nullable ResolvableType eventType) {    
         // 如果可能,现在就进行多播 - 或者在多播器初始化后懒惰地进行
         if (this.earlyApplicationEvents != null) {
             // 暂存事件
             this.earlyApplicationEvents.add(applicationEvent);
         }
         else {
             // 获取事件广播器广播事件
             getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
         }
     }
    

    其中ApplicationEventMulticaster(事件广播器)的广播实现源码如下:

    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    	ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    	Executor executor = getTaskExecutor();
        // 遍历事件监听器
    	for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
    		if (executor != null) {
                // 多线程执行监听器onApplicationEvent方法
    			executor.execute(() -> invokeListener(listener, event));
    		}
    		else {
                // 直接执行onApplicationEvent方法
    			invokeListener(listener, event);
    		}
    	}
    }
    

    ②事件 => ApplicationEvent,可通过继承该类进行扩展
    ③监听器 => ApplicationListener(用程序事件监听器实现的接口),处理应用程序事件方法onApplicationEvent,可以实现该接口和方法对事件监听器进行扩展

    Spring事件驱动模型结构:
    Spring事件驱动模型.png

  6. FactoryBean & BeanFactor
    FactoryBean是Bean,可以通过实现 FactoryBean 接口定制实例化 Bean 的逻辑,通过代理一个Bean对象,对方法前后做一些操作

  7. SpringBean的生命周期
    SpringBean的生命周期.png

  8. Spring如何解决循环依赖问题
    Spring解决循环依赖是依赖三级缓存实现,通过三级缓存提前拿未初始化的对象,最终实现基于以下两点:

    • Spring通过递归方式获取Bean和它所依赖的Bean (doGetBean方法,先是缓存获取,缓存没有则doCreateBean方法创建)
    • Spring创建Bean分为两步,首先实例化目标Bean,然后初始化就注入属性

    看下doGetBean方法的部分逻辑:

    protected <T> T doGetBean(
    		String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
    		throws BeansException {
        // 查询三级缓存中的Bean实例
        Object sharedInstance = getSingleton(beanName);
        if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
                try {
                    // 创建Bean实例,并保存到三级缓存(singletonFactories)中
                    return createBean(beanName, mbd, args);
                }
                catch (BeansException ex) {
                    destroySingleton(beanName);
                    throw ex;
                }
            });
            beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }
    }
    

    getSingleton方法,获取缓存bean实例的具体实现---读取三级缓存:

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    	Object singletonObject = this.singletonObjects.get(beanName);
    	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    		singletonObject = this.earlySingletonObjects.get(beanName);
    		if (singletonObject == null && allowEarlyReference) {
    			synchronized (this.singletonObjects) {
    				singletonObject = this.singletonObjects.get(beanName);
    				if (singletonObject == null) {
    					singletonObject = this.earlySingletonObjects.get(beanName);
    					if (singletonObject == null) {
    						ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    						if (singletonFactory != null) {
    							singletonObject = singletonFactory.getObject();
    							this.earlySingletonObjects.put(beanName, singletonObject);
    							this.singletonFactories.remove(beanName);
    						}
    					}
    				}
    			}
    		}
    	}
    	return singletonObject;
    }
    

    createBean方法的相关实现:这里可以看到实现循环依赖的先决条件有[isSingleton(单例) & allowCircularReferences(开启循环依赖) & allowCircularReferences(对象正在创建)]

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    		throws BeanCreationException {
        // 前面部分代码实现bean的构建
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                    isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            // 新增实例到三级缓存
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }
    }
    
    
    
         一级缓存(singletonObjects):用来保存实例化、初始化都完成的对象
         二级缓存(earlySingletonObjects):用来保存实例化完成,但是未初始化完成的对象
         三级缓存(singletonFactories):用来保存一个对象工厂,提供一个匿名内部类,用于创建二级缓存中的对象
    

    示例:循环依赖A->B,B->A
    循环依赖.png

    为什么使用三级缓存而不是二级缓存?
    为了生成代理对象,因为三级缓存中放的是生成具体对象的匿名内部类,他可以生成代理对象,也可以是普通的实例对象

  9. Spring的事务传播机制

        PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,这也是通常我们的默认选择  
        PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务
        PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行
        PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
        PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常
        PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常
        PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行
    

参考内容
https://www.cnblogs.com/fingerboy/p/6393644.html
https://javaguide.cn/system-design/framework/spring/spring-design-patterns-summary/
https://mp.weixin.qq.com/s/euzbHPpQG2BSKl93N5L1Hg

posted on 2022-02-10 13:55  哈啦曼  阅读(23)  评论(0编辑  收藏  举报