Spring介绍与实现

作者水平很有限,如有什么错误点,欢迎各位大佬指点。

spring是什么

spring轻量级框架、核心功能IOC、AOP Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。

  • 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
  • Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
  • Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能 , 集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理任何支持 AOP的对象。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。
  • Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
  • Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
  • Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
  • Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

Spring不同类型的事件

Spring 提供了以下5种标准的事件:

  1. 上下文更新事件(ContextRefreshedEvent):在调用 ConfigurableApplicationContext 接口中的refresh()方法时被触发。
  2. 上下文开始事件(ContextStartedEvent):当容器调用 ConfigurableApplicationContext的Start()方法开始/重新开始容器时触 发该事件。
  3. 上下文停止事件(ContextStoppedEvent):当容器调用 ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
  4. 上下文关闭事件(ContextClosedEvent):当ApplicationContext被 关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
  5. 请求处理事件(RequestHandledEvent):在Web应用中,当一个 http请求(request)结束触发该事件。如果一个bean实现了 ApplicationListener接口,当一个ApplicationEvent 被发布以后,bean 会自动被通知。

分割线


@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
       //前置工作  主要设置、准备  
      prepareRefresh();
      // 创建容器对象:DefaultListableBeanFactory
      // 加载xml配置文件的属性值到当前工厂中,最重要的就是BeanDefinition
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      // beanFactory的准备工作,对各种属性进行填充
      prepareBeanFactory(beanFactory);
      try {
     	 // 子类覆盖方法做额外的处理
         postProcessBeanFactory(beanFactory);
         // 调用各种beanFactory处理器
         invokeBeanFactoryPostProcessors(beanFactory);
         // 注册bean处理器,这里只是注册功能,真正调用的是getBean方法
         registerBeanPostProcessors(beanFactory);
         // 为上下文初始化message源,即不同语言的消息体,国际化处理
         initMessageSource();
         // 初始化事件监听多路广播器
         initApplicationEventMulticaster();
         // 留给子类来初始化其他的bean
         onRefresh();
         // 在所有注册的bean中查找listener bean,注册到消息广播器中
         registerListeners();
         // 初始化剩下的单实例(非懒加载的)
         finishBeanFactoryInitialization(beanFactory);
         // 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }
         // 为防止bean资源占用,在异常处理中,销毁已经在前面过程中生成的单件bean
         destroyBeans();
         // Reset 'active' flag.
         // 重置active标志
         cancelRefresh(ex);
         throw ex;
      }

      finally {
         resetCommonCaches();
      }
   }
}

在这里插入图片描述

SpringIOC

spring IOC(控制反转):解耦、将原来对对象的管理是使用者来进行控制->对象的管理交给spring来进行管理。

DI(依赖注入):把对应的属性的值注入到具体的对象种,@Autowried,populateBean完成属性值的注入
实现:
通过createBeanFactory创建Bean工厂 (DefaultListable BF)
开始循环创建对象,容器中的对象默认是单例,先通过getBean->doGetBean 从容器中查找查找不到再去创建
通过createBean->doCreateBean方法,用反射的方式创建对象
对对象属性进行填充 populateBean
进行其他初始化操作 initalizingBean

springBean

Spring beans 是那些形成Spring应用的主干的java对象。它们被Spring IOC容器初始化,装配,和管理。这些beans通过容器中配置的元数据创建。比如,以XML文件中 的形式定义。一个Spring Bean 的定义包含容器必知的所有配置元数据,包括bean,它的生命周期详情及它的依赖。

  • XML配置文件。
  • 基于注解的配置。
  • 基于java的配置。

Spring框架支持以下五种bean的作用域:

  • singleton : bean在每个Spring ioc 容器中只有一个实例。
  • prototype:一个bean的定义可以有多个实例。
  • request:每次http请求都会创建一个bean,该作用域仅在基于web的SpringApplicationContext情形下有效。
  • session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
  • global-session:在一个全局的HTTP Session中,一个bean定义对应一个

Spring框架中的单例bean不是线程安全的。spring 中的 bean 默认是单例模式,spring 框架并没有对单例 bean 进行多线程的封装处理。

Bean 的生命周期

请添加图片描述

1、实例化bean:反射的方式生成对象
2、填充bean的属性:populateBean()
3、aware接口相关的方法:invokeAwareMethod(完成BeanName,BeanFactory,BeanClassLoader对象的属性设置)
4、调用BeanPostProcessor中的前置处理方法
5、调用initmethod方法:invokeInitmethod(),判断是否实现了initializingBean接口,如果有,调用afterPropertiesSet方法,没有就不调用
6、调用BeanPostProcessor的后置处理方法:spring的aop就是在此处实现的
7、获取到完整的对象,可以通过getBean的方式来进行对象的获取
8、销毁流程,是否实现了DispoableBean接口,调用destroyMethod方法

循环依赖

循环依赖是什么?
请添加图片描述

A 等B ,B等A
死路,不通。 三级缓存提前暴露对象,在创建过程中是 实例化在初始化再去填充属性的

先创建A->实例化A->进行初始化在赋值b的时候去容器中查找有就可以直接赋值没有需要创建…

在B去找A的时候A是存在的 不过它不是一个完整的对象 (相当于半成品)只实例化了还没有完成初始化。所以在程序调用过程中,拥有了某个对象的引用,能否在后期给他完成赋值操作,优先把非完整状态的对象优先赋值,相当于提前暴露了某个不完整的对象的引用,所以解决循环依赖在于 实例化与初始化分开操作。

​当所有的对象都完成实例化和初始化操作之后,还要把完整的对象放到容器中,此时容器中存在 实例化完成未初始化的对象 完整状态的对象,都在容器里,所以使用不同的map来实现的 也就是一级二级缓存,如果一级缓存中存在了那么二级缓存中不应该存在同名的对象(你让我用那个?有成品不给我?)他们的查找顺序式 123这样的方式来查找的,一级缓存存放的是完整对象,二级缓存存放的是半成品。

三级缓存:它的V 是一个ObjectFactory,函数接口,lambda表达式,如果一个对象要生成代理对象,那么要优先生成一个普通对象。

普通对象和代理对象是不能同时出现在容器里的,因此当一个对象需要被代理的时候,就要使用代理对象覆盖掉之前的普通对象,在实际调用过程中,无法确定对象什么时候被使用的,所以当某个对象被调用的时候,优先判断是否需要代理,因此传入lambda表达式的时候,可以通过lambda表达式来执行对象的覆盖过程。

所以所有的bean对象在创建的时候都要优先放到三级缓存中去,如果需要代理则返回代理对象,否则返回普通对象。

一二三级缓存 什么时候放 什么时候删?

    // 一级缓存 完整对象
   private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
   
   // 三级缓存 单例工厂 
   private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

   // 二级缓存 存放半成品bean 提前引用
   private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

一级缓存:生成完整的对象之后放到一级缓存,删除2 3
二级缓存:第一次从三级缓存确定对象是代理对象还是普通对象,删除3
三级缓存:create , addsingletonObjects

SpringAOP

AOP(Aspect-Oriented Programming),一般称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理等。

AOP相关概念:

切面(Aspect) :官方的抽象定义为“一个关注点的模块化,这个关注点可能会横切多个对象”。
连接点(Joinpoint) :程序执行过程中的某一行为。
通知(Advice) :“切面”对于某个“连接点”所产生的动作。
切入点(Pointcut) :匹配连接点的断言,在AOP中通知和一个切入点表达式关联。
目标对象(Target Object) :被一个或者多个切面所通知的对象。
AOP代理(AOP Proxy) 在Spring AOP中有两种代理方式,JDK动态代理和CGLIB代理。
织入(Weaving):织入是把切面应用到目标对象并创建新的代理对象的过程。在目标对象的生命周期里有多少个点可以进行织入

实现:

Bean的创建过程中可以对bean进行扩展,aop它本身就是一个扩展功能,所以在BeanPostProcessor 后置处理方法中来实现的它

代理对象的创建 advice 切面,切点
通过jdk还是cglib的方式生成代理对象
在执行方法调用的时候,会去调用生成的字节码文件中,直接回找到DynamicAdvisoredInterceptor类中的intercept方法,从此方法开始执行
根据之前定义好的通知来生成拦截器链
从拦截器链中依次获取每一个通知开始执行,在执行过程中,为了方便找到下一个通知在哪里 会有一个CglibMethodInvocation的对象,找的时候是从-1的位置一次开始查找并且执行的。

事务回滚

事务是一个不可分割操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。

spring的事务是由aop来实现的,首先要生成具体的代理对象,然后按照aop的流程来执行具体的操作,正常情况下要通过通知来完成核心功能,但是事务不是通过通知来实现的,而是通过一个TransactionInterceptor来实现的,然后调用invoke来实现具体的逻辑

事务:创建数据源事务对象->判断是否存在一个事务->很多的分支来判断到底怎么执行,具体还是去执行具体的逻辑 进行处理 ->可能正常结束了(清除事务信息) 也可能异常结束的(Afterthrowing 完成当前事务的回滚操作) -> 以正常的方式提交事务

事务传播

支持的事务传播行为

① PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。

② PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。

③ PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。

④ PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。

⑤ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

⑥ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

⑦ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。

隔离级别

默认值为 ISOLATION_DEFAULT(使用数据库的设置),其他四个隔离级别和数据库的隔离级别一致:

  1. ISOLATION_DEFAULT:用底层数据库的设置隔离级别,数据库设置的是什么我就用什么;

  2. ISOLATION_READ_UNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读);

  3. ISOLATION_READ_COMMITTED:提交读,一个事务提交后才能被其他事务读取到(会造成幻读、不可重复读),SQL server 的默认级别;

  4. ISOLATION_REPEATABLE_READ:可重复读,保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会造成幻读),MySQL 的默认级别;

  5. ISOLATION_SERIALIZABLE:序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。

脏读 :表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记录 A,此时该事务还未提交,然后另一个事务尝试读取到了记录 A。

不可重复读 :是指在一个事务内,多次读同一数据。

幻读 :指同一个事务内多次查询返回的结果集不一样。比如同一个事务 A 第一次查询时候有 n 条记录,但是第二次同等条件下查询却有 n+1 条记录,这就好像产生了幻觉。发生幻读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,所有数据行的记录就变多或者变少了。

  • 22
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值