栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring

一.Spring4和Spring5 AOP执行流程差别

advice

1.Spring4

正常执行:@Before======@After======@AfterReturning

异常执行:@Before======@After======@AfterThrowing

2.Spring5

正常执行:@Before(前置通知)=======@AfterReturning(返回后通知)=======@After(后置通知)

异常执行:@Before========@AfterThrowing====@After

二.AOP的底层实现原理

AOP是IOC的扩展功能,先有IOC,AOP是整个流程的一个新增扩展点:BeanPostProcessor(后置处理方法)

1.代理对象的创建过程(advice,切面,切点)

2.通过jdk或cglib的方式来生成代理对象。

面向切面编程,与面向对象编程相辅相成。在OOP中以类为基本单元,而AOP是aspect切面。实现方式有静态代理和动态代理。

(1)静态代理:编译阶段就可生成AOP代理类。

(2)动态代理:运行时生成。分为JDK(利用反射,并且要求被代理的类必须实现一个接口,核心是invocationHandler接口和proxy类)和CGLIB(没有实现接口,就用整个代理目标类,通过继承实现,如果一个类是final修饰无法动态代理)

java动态代理实现与原理详细分析 - Gonjian - 博客园 (cnblogs.com)

三.循环依赖及三级缓存

什么是循环依赖?多个bean之前相互依赖,形成一个闭环。spring容器一般指默认的单例Bean里。

两种注入方式(基于构造方法和单例模式下的setter的依赖注入,非单例无法处理)对循环依赖的影响,避免使用构造方法会抛出异常,spring解决不了,直接抛出异常。我们AB循环依赖问题只要A的注入方式是setter且singleton就不会有循环依赖问题。

spring的单例对象初始化分为:createbeanInstance实例化(调用构造方法);populateBean填充属性(多bean的依赖属性注入);InitializeBean初始化(init方法)。依赖注入就发生在第一二步。

 默认的单例(singleton)的场景是支持循环依赖的,不报错;原型(prototype)的场景是不支持循环依赖的,会报错。

关键在于先把非完整状态的对象优先赋值,即只完成了实例化但是还未初始化。提前暴露不完整对象的引用,先赋值再等后续操作完成赋值。当所有对象完成实例化和初始化操作后,还要把完整对象放到容器里,此时容器里有两个状态,完成实例化还未初始化,完整状态。因为都在容器中,所有要使用不同的map来进行存储,就有了一级缓存和二级缓存。如果一级缓存有了,那么二级缓存中就不会存在同名对象。一级放的是完整对象,二级缓存是非完整对象。

为啥需要三级缓存?三级缓存的value类型是ObjectFactory,是一个函数式接口。存在的意义是保证整个容器的运行工程中同名的bean对象只能有一个。

如果一个对象被代理,或者要生成代理对象,那么要优先生成一个普通对象。两者不能再容器中共存,当一个对象要被代理时,使用代理对象覆盖普通对象。当调用对象时,会回调机制,优先判断对象是否需要被代理。lambda表达式执行对象覆盖。 

  因此,所有bean对象再创建时优先放到三级缓存中,在后续使用中,如果需要被代理则返回代理对象,不然直接返回普通对象。

三级缓存:createBeanInstance之后,addSingletonFactory

二级缓存:第一次从三级缓存确定对象是代理对象还是普通对象,同时删除三级缓存;

一级缓存:生成完整对象后放一级,删除二三级缓存。

spring内部通过三级缓存解决缓存依赖(DefaultSingletonBeanRegistry)

第一级缓存(也叫单例池)singletonObjects:存放已经经历了完成生命周期的bean对象

第二级缓存: earlySingletonObjects,存放早期暴露出来的bean对象,bean的生命周期未结束,也就是已经实例化(申请了内存空间)但未初始化(还没放值)的bean放入该缓存里。

第三级缓存:singletonFactories, 存放可以生成bean的工厂

 refresh()方法就是加载容器初始化的方法。

 

 四,spring的事务如何回滚

就是怎么实现?(分为编程式事务管理和声明式事务管理)

总:spring的事务是由AOP来实现的,首先要生成具体的代理对象,然后按照AOP的流程执行具体操作。正常要通过通知完成核心功能,但是事务不是,是通过一个TransactionInterceptor(事务拦截器),然后调用invoke实现具体的逻辑。

分:1.准备工作,解析各个方法上事务相关属性,根据属性判断是否开启新事务。

       2.当开启时,获取数据库连接,关闭自动提交,开启事务

      3.执行具体SQL逻辑操作

      4.操作失败通过completeTransactionAfterThrowing,完成事务回滚,具体回滚通过doRollBack方法实现。

     5.没有意外,commiteTransactionAfterThrowing,实现doCommite

五.spring的传播特性

1.使用Spring的好处

(1)轻量,基本版本2M;

(2)控制反转;

(3)AOP;面向切面编程,提取公共业务逻辑,和服务分开;

(4)容器;

(5)MVC框架;

(6)事务管理

(7)异常处理。

2.依赖注入

不必创建对象,但必须描述怎么创建。描述配置文件中哪些组件需要哪些服务,有IOC容器将它们装配在一起。

(1)构造函数注入

(2)setter注入

(3)接口注入

在spring framework中,仅使用构造函数和setter注入。

3.

BeanFactory(主要的有DefaultListableBeanFactory的功能)将利用BeanDefinition来生成bean对象,BeanDefinition相当于BeanFactory的原材料,bean对象就是产品。

4.构造函数和setter注入区别

 5.spring的配置方式

(1)XML配置,以bean标签开头;

(2)注解配置,需要在spring配置文件中启动;

(3)基于Java API配置:通过@Bean和@Configuration

6.spring的bean的作用域

(1)singleton:默认是单例的

(2)prototype:每次请求都会创建一个新的bean实例

(3)request:每次HTTP请求产生一个新的bean,仅在当前HTTP request内有效;

(4)session:在一个session中,一个session对应一个实例。

(5)Global-session

最后三个仅当用户使用applicationcontext可用。

7.如何理解IOC和DI

一个是思想,一个是设计模式。

IOC不用我们自己创建对象,交给bean工厂创建管理,通过面向接口编程的方式来实现对业务组件的动态依赖。IOC是spring争对解决程序耦合存在的。

实际中,spring通过配置文件(如XML或properties)指定需要实例化的Java类,包括类的一组初始化值,通过加载读取配置文件,用spring提供的方法(getbean())获取进行初始化的实例对象。

传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。

DI(依赖注入)其实就是IOC的一种类型,还有一种是DL(Dependency Lookup依赖查找)。  DL由Martin Fowler 在2004年初的一篇论文中首次提出的。他总结:控制的什么被反转了?就是:获得依赖对象的方式反转了。

理解Spring中的IoC和DI - 超超不会飞 - 博客园 (cnblogs.com)

8.将一个类声明为bean的注解

一般使用@autowired注解自动装配bean,要想把类标识成可用于@autowired注解自动装配的bean的类,可用以下:

(1)@component,通用注解

(2)@repository ,对应持久层即Dao层

(3)@service,对应服务层,需要用到Dao层

(4)@controller对应MVC的控制层,接受用户请求并调用service层返回的数据给前端页面。

9.bean的生命周期

 

 

 

 10,spring的内部bean

只有将bean用作另一个bean的属性时,才能将bean声明为内部bean。

11.spring装配

当bean在容器中组合在一起,称为bean装配。spring容器需要知道需要什么bean以及如何使用依赖将bean绑定起来。

通过检查beanfactory,不同模式:

(1)no;(2)byName;(3)byType(4)构造函数,有大量参数;(5)autodetect,尝试通过构造函数使用auto wired装配,不能就尝试通过bytype自动装配。

 12.如果出现同名bean

(1)同一配置文件的,以最上面定义为准

(2)不同配置文件的,以后解析的为准,覆盖

(3)同文件的@bean和@componentscan,以bean生效;

13.spring中单例bean的线程安全问题

线程安全问题都是由全局变量及静态变量引起的。如果只读没问题,但是多线程同时写有问题。

无状态和有状态bean

有状态就是有实例变量的对象,可以保存数据,是非线程安全的。适用于prototype原型模式。

无状态就是一次操作,不能保存数据。是线程安全的。适用于单例模式。

spring适用threadlocal解决线程安全问题。

@value($())是在XML中找Key,@value(“”)是直接指定字符串,

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/749873.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号