spring基础概念

什么是spring IOC 容器? 有什么作用?优点是什么?

IOC就是控制反转 控制了什么? 

UserService userService=new UserService();//耦合度太高 维护不方便,属性值都是空的!

一入IOC 就将创建对象的控制权交给spring的ioc 以前由我们自己控制对象的创建 现在交给spriong的ioc去创建 如果我们要去使用 只需要通过DI(依赖注入)@Autowired(自动注入)就可以使用对象

UserService.class---->无参构造---->对象----->依赖注入(属性赋值)------初始化前-----初始化-----初始化后---->bean

说明:spring先通过无参构造去创建UserService对象,但对象中的@Autowired的属性都是没有值的,spring会去循环找到他们进行属性赋值

初始化前:在对象中会通过@PostConstruct注解去在初始化前的流程中执行此方法,可以对一些需要依赖注入对象进行赋值

 Spring容器必须通过DI注入给我 我才可以使用 DI是是想ioc重要的一环

优点:1 集中管理对象、方便维护  2 降低耦合度

Ioc容器创建的对象就是bean 自己new的就叫对象

Spring IOC的实现机制是什么

简单工厂+反射

简单工厂如果类很多的时候需要一个一个去判断和创建 则采用反射技术来处理(传入的是完整的类路径)

BeanFactory的作用

BeanFactory是spring中非常核心的一个顶层接口

它是bean的工厂 它的主要职责就是生产Bean

它实现了简单工厂的设计模式 通过调用getBean传入标识生产一个Bean

BeanFactory它也是一个容器(管理着Bean的生命周期)

spring容器(管理着Bean的生命周期)ApplicationContext

 BeanDefinition的作用

 首先是配置bean(通过各种方式xml、@Bean)然后把他们都放到BeanDefinitionMap中(因为会有多个配置的bean)map中的key就是beanName 然后通过循环交给bean工厂进行生产实例化这些bean

ApplicationConText和beanFactory区别 

共同点:都可以作为容器

区别:

1 beanFactory也可以作为容器 内存占用率小 作为一个工厂

2 ApplicationConText通知beanFactory去生产bean 自己则不能生产bean

3 ApplicationConText比 beanFactory做的事情更多

比如:ApplicationConText会自动帮我们把我们配置的bean注册进来

BeanFactory 和 FactoryBean 有什么区别?

BeanFactory是一个工厂 也就是一个容器 是来管理和生产bean

FactoryBean是一个bean 但是一个特殊bean 所以也是由BeanFactory来管理的

重点:

假如userService类实现了FactoryBean 所以就寄生在了userService中 因此它就不在返回userService了

等于说现在我们在容器中获得的userService将不再是它本身的对象了 而是通过FactoryBean的getObject方法返回的对象了 在这个方法里可以返回任何自定义对象(比如:roleService)就会狸猫换太子 所以在容器中getBean的时候返回的就不是userService 而是自定义的roleService

如果想依旧返回原本的对象 可以在getbean的key时候前面加上&符号

而且FactoryBean是一种懒加载的模式

正常的单例bean都在在容器加载的时候帮我们创建 并放到容器中

但是被FactoryBean修饰之后就变成了懒加载了 容器加载完之后 只有等主动获取get的时候 才会输出

Spring中 有两个id相同的 bean 会报错吗,如果会报错,在哪个阶段报错

1在同一个XML配置文件里面,不能存在id相同的两个bean,否则spring容器启动的时候会报错

2在两个不同的Spring配置文件里面,可以存在id相同的两个bean。 IOC容器在加载Bean的时候,默认会多个相同id的bean进行覆盖

3在Spring3.x版本以后,@Configuration注解去声明一个配置类,然后使用@Bean注解实现Bean的声明
如果我们在同一个配置类里面声明多个相同名字的bean,在Spring IOC容器中只会注册第一个声明的Bean的实例。后续重复名字的Bean就不会再注册了。

说下 spring IOC容器的加载过程

根据包路径扫描到所有.class文件中有没有配置标准的注解 如果有 就会把当前这个bean注册为BeanDefinition对象

1、实例化一个AppLicationContext的对象

2、通过读取器去读取配置类

3、解析class文件对象

判断当前类是否再excludeFilter相匹配 如果匹配就直接排除 反之如果匹配includeFilter那么就通过

如果是java配置类方式解析的话是基于动态注册BeanDefinition的这个扩展点来解析的 里面有一个配置类解析器 通过解析器中doscan方法进行扫描解析

如果是xml方式解析的话是通过LoadBeanDifinition解析,然后注册BeanDefinition

4、把注册好的BeanDefinition对象put到BeanDefinitionMap中缓存起来

使用工厂模式 通过bean工厂去生产bean 是调用getBean的方法

流程:

1 现在就是开始生产bean了 循环判断所有的BeanDefinition是否符合生产的标准(标准条件:是单例 不是懒加载 不是抽象)满足条件才会生产

2、如果符合标准 接下来会判断是否创建完成(因为getBean这个方法既会创建也会获取数据)如果创建好了就直接返回

3、实例化对象之前,Spring提供了一个扩展点,允许用户来控制是否在某个或某些Bean实例化之前做一些启动动作。叫做postProcessBeforeInstantiation() (在实例化前可以直接返回一个自定义UserService对象。如果是这样,表示不需要Spring来实例化了,直接执行初始化后这一步

4、实例化 如果没有创建 就会先利用推断构造方法确定要使用的构造方法 进行反射的方式进行实例化对象 但这个实例化的bean并不是完整的bean 他是一个没有属性注入的bean

5、Bean对象实例化出来之后,Spring提供了一个扩展点postProcessMergedBeanDefinition(),此扩展点是为了找出注入点并缓存

6、所以实例化后就会进行属性赋值,会遍历所找到的注入点依次进行注入。@Autowired、@Resource、@Value等注解,都是通过postProcessProperties()扩展点来实现的(甚至可以自定义进行注入操作)

7、初始化前,也是Spring提供的一个扩展点postProcessBeforeInitialization()

8、最终进行初始化 这一步会实现很多扩展接口(Aware接口 生命周期回调等 这里如果当前这个bean需要实现aop 动态代理那么就在这里被创建)

9、初始化后,Spring提供的一个扩展点postProcessAfterInitialization(),对Bean最终进行处理,Spring中的AOP就是基于初始化后实现的,初始化后返回的对象才是最终的Bean对象

10、创建完成后 然后放到Map中(单例池)

SpringIoc的扩展点以及调用时机

在注册BeanDefinition阶段时 两个扩展接口

1 动态注册BeanDefinition(如果没有配置bean 但还是希望注册BeanDefinition)接口提供了一个注册器 通过注册器可以创建bean (先执行)

2在所有BeanDefinition注册完后实现BeanFactoryPostProcessor(bean工厂后置处理器)进行自定义扩展(提供了可以查询每一个注册好的BeanDefinition 但是只能通过name查询 并没有BeanDefinitionMap)还可以修改任何一个BeanDefinition中的属性(作用域 懒加载等)

在初始化阶段 钩子方法

Awate接口 BeanNameAware、beanFactoryAware方法去扩展当前bean

例如:初始化阶段调用XXXAware接口的SetXXXAware方法

生命周期回调 扩展的接口

 生命周期的回调:spring在初始化回调 销毁回调的方法

什么是javaBean和springBean和对象的区别

Spring bean

被springIOC容器管理的对象称为bean bean是一个有spring ioc容器实例化和管理的对象

Java Bean

就是类的对象 里面会有构造方法属性之类的

配置bean有哪几种方式

1 xml :<bean class="UserService" id="">

2 注解:@Component(@Controller @Service @Repostory)

3 javaConfig:@Bean 可以自己控制实例化过程

4 @Inport:3种方式

Bean有哪几种作用域

@scope 注解 以及 xml方式配置作用域

作用域有:(5个)

单例(默认作用域)

多例

必须是web应用的话

Request作用域 一个请求会创建一个bean对象

Session作用域 一个会话会创建一个bean对象

Application作用域 一个全局应用共享一个bean对象

Spring的bean是线程安全的吗?

单例bean的情况下 如果再类中声明成员变量 并且有读写操作(有状态)就是线程不安全的

但是 只需要把成员变量声明在方法中(无状态) 单例bean就是安全的

Spring如何处理线程并发问题?

 当两条线程同时去请求UserService类的时候 并且发生了读写请求 那么就会发生线程并发不安全的问题

解决:

1设置为多例:当每条线程访问UserService类时候都是重新new UserService 不会访问同一个

2 将成员变量放在ThreadLocal

3 同步锁 会影响服务器性能

4 把成员变量声明在方法中(无状态

成员变量:Static修饰成为类变量或静态变量,还有就是方法外的变量。生命周期与类相同。
局部变量:就是方法中的变量。生命周期就是再次方法中。

Bean有哪些生命周期的回调方法?有哪几种实现方式?

Bean的生命周期回调有两种

1 bean生命周期初始化的时候

2 bean生命周期销毁的时候

三种实现方式

初始化和销毁同理

第一种是通过注解的方式放到方法上进行实现

第二种是通过实现接口重写的方式进行实现

第三种是通过@Bean上配置参数初始化和销毁的方法进行实现

执行顺序:先初始化后销毁 多个初始化时顺序为(销毁同理):注解方式->实现接口->bean注解上配置参数

Bean的生命周期

Spring是如何解决bean的循环依赖的?

第三级缓存就是打破循环用的? 

Spring如何避免在并发情况下获取不完整的bean

双重检查锁机制

Spring容器启动时 为什么先加载BeanFactoryPostProcess?

因为BeanDefiniton会在ioc容器加载的比bean先注册 而BeanFactoryPostProcess就是所有的BeanDefiniton注册完后做扩展用的 所以要先加载

Bean的创建顺序是什么样的

Bean的创建顺序是由BeanDefinition的顺序来决定的 当然依赖关系也会影响Bean创建顺序

BeanDefinition的注册顺序有什么来决定的?

主要是有注解(配置)的解释顺序来决定的:

1 @Configuration

2 @Component

3 @Import-类

4 @Bean

5 @Import-ImportBeanDefinitionRegistar

javaConfig是如何代替xml的配置方式的

如果让自动注入没有找到依赖Bean是不报错?

@Autowired默认required为ture 当没有找到依赖时 发抛出错误 如果手动置为false就不会报错了

如果自动注入找到了多个依赖Bean时不报错

可以通过想要成功的内个bean类上添加@Primary注解 就不会报错了

@Autowired注解和@Resource之间的区别      

共同点:自动注入

区别:

1 Autowired是基于spring的     Resource是基于jdk的

2 Autowired是根据类型匹配 如果类型匹配到了多个 那就根据name去匹配注入

   Resource默认是根据名字去匹配 如果名字没有匹配到才会根据类型去匹配

@Autowired注解自动装配的过程?

1 在Bean实例化预解析(解析@Autowired标注的属性、方法)

2 在bean属性注入真正解析(拿到上一步缓存的元数据 去ioc容器帮进行查找 并且返回注入)

   首先根据预解析的元数据拿到类型取容器中查找

   如果查询结果为一个 就将该bean装配给@Autowired指定的数据

   如果查询结果为多个 那么@Autowired会根据名称来查找

   如果查询结果为空    那么会抛出异常 解决方法是 使用required=false

@Bean之间的方法调用是怎么保证单例的?

@Configuration加与不加的区别是什么?

1 如果希望@Bean的方法返回的对象是单例 需要在类上面加上@Configuration

2 spring会在invokBeanFactoryPostProcessor 通过内置BeanFactoryPostProcessor中会CGLib生     成动态代理

3 当@Bean方法互调时 则会通过CGLib进行增强 通过调用的方法名作为bean的名称去ioc容器           中获取  进而保证了@Bean方法的单例

Spring AOP中常用名词解释? 

1.切面(Aspect): 在spring aop指定就是"切面类"  切面类 会管理职切点、通知

2.连接点(Joinpoint):指定就是被增强的业务方法

3.通知(Advice): 就是需要增加到业务方法中的公共代码通知有很多类型

4.切点(Pointcut): 由它决定哪些方法需要增强 哪些不需要增强 结合切点表达式实现

5.目标对象(Target Object): 指定的是增强的对象

6.织入(Weaving): spring aop用的织入方式:动态代理

spring通知有哪些类型?

1 前置通知:在目标方法被调用之前通用通知功能

2 后置通知:在目标方法被调用之后通用通知功能 不会关心方法的输出是什么

3 返回通知:在目标方法成功执行后调用同通知

4 异常通知:在目标方法抛出异常后调用通知

5 环绕通知:通知包裹了被通知的方法 再被通知的方法调用之前和调用之后执行自定义的行为

Spring AOP和AspectJ Aop有什么区别?

AOP实现的关键在于代理模式,AOP代理主要分为静态代理和动态代理

静态代理的代表为AspectJ 动态代理则以Spring AOP为代表

Spring AOP使用的动态代理 它基于动态代理来实现 默认

如果使用接口 用JDK提供的动态代理实现

如果没有接口 则使用CGLIB实现

JDK动态代理和CGLIB动态代理的区别?

JDK动态代理只提供接口的代理 不支持类的代理

   1 JDK会在运行时为目标类生成一个 动态代理类$proxy*.class

   2 该代理类是实现了目标类接口 并且代理类会实现接口所有的方法增强代码

   3 调用是 通过代理类先去调用处理类进行增强 在通过反射的方式进行调用目标方法 

如果代理类没有实现接口 那么spring aop会选择使用CGLIB来动态代理目标类

    1 CGLIB的底层是通过ASM在运行时动态的生成目标类的一个子类

    2 并且会重写父类所有的方法增强代码

    3 调用时先通过代理类进行增强 再直接调用父类对应的方法进行调用目标方法 

          CGLIB是通过继承的方式做的动态代理 因此如果被某个类标记为final 则无法使用代理

PS:jdk动态代理CGLIB 性能好20%左右

    jdk动态代理 生成类速度快 调用慢 

    CGLIB         生成类速度慢 调用快 

介绍aop有几种实现方式?

Spring 1.2 基于接口的配置

Spring 2.0 schema-based配置:使用XML方法类配置 使用 命名空间<aop></aop>

Spring 2.0 @AspectJ配置:注解方式

什么情况下AOP会失效 怎么解决?

失效原因: 内部调用不会触发Aop

解决方式:必须走代理 重新拿到代理对象再次执行方法才能进行增强

              1 在本类中自动注入当前的bean

              2 设置暴露当前代理对象到本地线程

Spring的AOP是在哪里创建的动态代理的?

1 正常的Bean会在Bean的生命周期的初始化后 通过 后置处理器创建aop的动态代理

2 当循环依赖的Bean会在Bean的生命周期的属性注入时候 创建aop

AOP的实现大致分为三步?

当@EnableAspectJAutoProxy会通过@Import注册一个BeanPostProcessor处理AOP

1 解析切面 :在Bean创建之前的第一个Bean后置处理器会去解析切面(解析切面中的通知、切点                        一个通知就会解析成一个advisor)

2 创建动态代理:正常的Bean初始化后调用Bean的后置处理器 拿到之前缓存的advisor 在通过                                  advisor中的切点 判断当前Bean是否被切点表达式匹配 如果匹配 就会为Bean创                              建动态代理

3 调用:拿到动态代理对象 调用方法 就会判断当前方法是都增强的方法 就会通过调用链的方式依                次去执行通知

spring事物四大特性

原子性

一致性

隔离性

持久性

Spring支持的事物管理类型 spring事物实现方式有哪些?

1 编程式事务管理:通过编程的方式管理事务 带来极大的灵活性 难维护

2 声明式事务管理:可以将业务代码和事务管理分离 只需要用注解和xml配置管理事务

 Spring事务的传播行为?

Spring事务实现原理?

使用:

@EnableTransactionManagement

1 解析切面 :在Bean创建之前的第一个Bean后置处理器会去解析切面(解析切面中的通知、切点                        一个通知就会解析成一个advisor)

2 创建动态代理:正常的Bean初始化后调用Bean的后置处理器 拿到之前缓存的advisor 在通过                                  advisor中的切点 判断当前Bean是否被切点表达式匹配 @Transacational(方法里                              面是不是有 类上面是不是有 接口或者父类是不是有) 匹配到就创建动态代理

3 调用:动态代理

try{

       4.创建一个数据库连接Connection 并且修改数据库连接的autoCommit属性为false 禁止            此链接自动提交 这是实现spring事物非常重要的一步

       5.然后执行目标方法 方法中会执行数据库操作

}

catch{

        6.如果出现了异常 并且这个异常是需要回滚的就会回滚事物 否则仍然提交事物

}

Spring事务传播行为实现原理?

spring的事物信息是存在ThreadLocal中的 所以一个线程永远只能有一个事物

   融入:当传播行为是融入 外部事物则拿到ThreadLocal中的Connection  共享一个数据库连接共同               提交、回滚

   创建新事物:当传播行为是创建新事物 回见嵌套新事物存入ThreadLocal 将外部事物暂存起                                 来当嵌套事物提交、回滚后  然后暂存的事物信息恢复到ThreadLocalzhogn中

 

 

Spring中运用的设计模式?

1 简单工厂  ----BeanFactory

2 工厂方法  ----FactoryBean

3 单例模式  ----Bean实例

4 适配器模式 ----springMvc中的HandlerAdatper

5 装饰器模式 ----BeanWrapper

6 代理模式  ----AOP底层

7 观察者模式----spring的时间监听

8 策略模式

spring是如何整合MyBatis将Mapper接口注册为Bean的原理?

springMvc的工作流程?

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值