Spring IOC/bean/AOP

在这里插入图片描述
1.Spring启动时读取应用程序提供 Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表;

2.根据这张注册表实例化Bean;

3.通过配置文件装配好Bean之间的依赖关系,放到Bean缓存池,为上层应用提供准备就绪的运行环境。

Bean缓存池:通过hashMap实现

1.1 IOC容器介绍
Spring通过一个配置文件描述 Bean 及 Bean 之间的依赖关系(依赖注入通过反射功能)。Spring的IOC容器在完成这些底层工作的基础上,还提供了Bean实例缓存、生命周期管理、Bean实例代理、事件发布、资源装载等高级服务。

BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;
ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合我们都直接使用 ApplicationContext 而非底层的 BeanFactory。

XmlBeanFactory 通过 Resource 装载 Spring 配置信息并启动 IoC 容器,然后就可以通过 BeanFactory#getBean(beanName)方法从 IoC 容器中获取 Bean 了。通过 BeanFactory 启动IoC 容器时,并不会初始化配置文件中定义的 Bean,初始化动作发生在第一个调用时。

对于单实例( singleton)的 Bean 来说,BeanFactory会缓存 Bean 实例,所以第二次使用 getBean() 获取 Bean 时将直接从 IoC 容器的缓存中获取 Bean 实例。Spring 在 DefaultSingletonBeanRegistry 类中提供了一个用于缓存单实例 Bean 的缓存器,它是一个用HashMap 实现的缓存器,单实例的 Bean 以 beanName 为键保存在这个HashMap 中。

Bean生命周期

在这里插入图片描述

怎么获取bean信息

怎么在bean不同时期做点事
1.实现InitializingBean接口,重写afterPropertiesSet()
2.实现DisposableBean ,重写 destroy()
通过@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作

3.@PostConstruct该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。

创建bean过程

Spring Bean创建过程解析

bean懒加载

Java中的循环依赖分两种,一种是构造器的循环依赖,另一种是属性的循环依赖。
构造器的循环依赖就是在构造器中有属性循环依赖。
这种循环依赖没有什么解决办法,因为JVM虚拟机在对类进行实例化的时候,需先实例化构造器的参数,而由于循环引用这个参数无法提前实例化,故只能抛出错误。
Spring解决的循环依赖就是指属性的循环依赖

只有单例的bean会通过三级缓存提前暴露来解决循环依赖的问题,而非单例的bean,每次从容器中获取都是一个新的对象,都会重新创建,所以非单例的bean是没有缓存的,不会将其放到三级缓存中。多例时,不管是任何方式都是无法解决循环依赖的问题,最终都会报错,因为每次去获取依赖的bean都会重新创建。

为什么需要用3级缓存
如果只使用2级缓存,直接将刚实例化好的bean暴露给二级缓存出是否可以否?
不行
这样做是可以解决:早期暴露给其他依赖者的bean和最终暴露的bean不一致的问题。

若将刚刚实例化好的bean直接丢到二级缓存中暴露出去,如果后期这个bean对象被更改了,比如可能在上面加了一些拦截器,将其包装为一个代理了,那么暴露出去的bean和最终的这个bean就不一样的,将自己暴露出去的时候是一个原始对象,而自己最终却是一个代理对象,最终会导致被暴露出去的和最终的bean不是同一个bean的,将产生意向不到的效果,而三级缓存就可以发现这个问题,会报错。

Spring系列文章

面试题摘抄

BeanFactory和 Application contexts 有什么区别?

BeanFactory:是Spring里面最低层的接口,提供了最简单的容器的功能,而且只提供了实例化对象和拿对象的功能;ApplicationContext:是应用上下文,继承BeanFactory接口,它是Spring的一个更高级的容器,提供了更多的有用的功能,这些功能包括;国际化访问资源,如URL和文件载入多个有继承关系的上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层 消息发送和响应机制AOP两者的区别在于装载beans时的区别:BeanFactory在启动的时候不会去实例化Bean,当Spring应用中有从容器拿Bean的时候才会去实例化;ApplicationContext在启动的时候就把所有的Bean全部实例化了,它还可以通过配置来实现Bean的延迟实例化,所以实际开发中推荐使用Application contexts。

Spring 框架中的单例 bean是线程安全的吗?

Spring 框架中的单例 bean 不是线程安全的,spring 中的 bean 默认是单例模式,Spring框架并没有对单例 bean 进行多线程的封装处理。实际上大部分时候 spring bean 是无状态的(比如 dao类),某种程度上来说 bean 也是安全的,但如果 bean 有状态的话(比如 view model 对象),那就要开发者自己去保证线程安全了。最简单的就是改变 bean 的作用域,把“singleton”变更为“prototype”,这样请求 bean 相当于 new Bean()了,就可以保证线程安全了。

解释 Spring 框架中 bean 的生命周期

Spring 容器从XML 文件中读取 bean 的定义,并实例化 bean。Spring 根据 bean 的定义填充所有的属性。
如果 bean 实现了 BeanNameAware 接口.Spring 传递 bean 的ID到 setBeanName 方法。
如果 Bean 实现了 BeanFactoryAware 接口, Spring 传递 beanFactory 给 setBeanFactory 方法。
如果有任何与 bean 相关联的 BeanPostProcessors, Spring 会在 postProcesserBeforeInitialization() 方法内调用它们.
如果 bean 实现 IntializingBean 了,调用它的 afterPropertySet 方法,如果 bean 声明了初始化方法,调用此初始化方法。
如果有 BeanPostProcessors 和 bean 关联,这些 bean 的 postProcessAfterInitialization() 方法将被调用。
如果 bean 实现了 DisposableBean 它将调用 destroy() 方法。

解释不同方式的自动装配

1.no方式:是默认的方式,不进行自动装配,通过显式设置 ref 属性来进行装配。

2.byName方式:是通过参数名自动装配,Spring 容器在配置文件中发现 bean 的 autowire 属性被设置成 byname之后,容器试图匹配、装配和该 bean 的属性具有相同名字的 bean。

3.byType方式: 是通过参数类型自动装配,Spring 容器在配置文件中发现 bean 的 autowire 属性被设置成 byType之后,容器试图匹配、装配和该 bean 的属性具有相同类型的 bean。如果有多个 bean 符合条件,则抛出错误。

4.constructor方式:这个方式类似于 byType方式,但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。

5.autodetect方式:首先尝试使用 constructor 方式来自动装配,如果无法工作,则使用 byType 方式。

Spring AOP and AspectJ AOP 有什么区别?AOP 有哪些实现方式?

AOP实现的关键在于代理模式,AOP代理主要分为静态代理和动态代理。AspectJ是静态代理的增强,所谓静态代理就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强。它会在编译阶段将AspectJ切面织入到Java字节码中,运行的时候就是增强之后的AOP对象。Spring AOP使用的是动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象。这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。

Spring 框架中都用到了哪些设计模式?

工厂模式:BeanFactory是工厂模式的一个实现,用来创建对象的实例;
单例模式:Spring配置文件定义的Bean默认为单例模式。
代理模式:Spring的AOP功能的实现用到了代理模式;
模板方法模式:用来解决代码重复的问题。比如. RestTemplate模版类, JmsTemplate模版类,
JpaTemplate模版类。
观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。

@Component, @Controller, @Repository, @Service 有何区别?

@Component:是通用注解,其他三个注解是这个注解的拓展,并且各自具有特定的功能

@Controller:是spring-mvc的注解,具有将请求进行转发,重定向的功能

@Service:是业务逻辑层注解,用于标注该类处于业务逻辑层。

@Repository:在持久层中,具有将数据库操作抛出的原生异常翻译转化为Spring的持久层异常的功能

代理

使用JDK创建代理有一个限制,它只能为接口创建代理实例.这一点可以从Proxy的接口方法newProxyInstance(ClassLoader loader,Class [] interfaces,InvocarionHandler h)中看的很清楚,第二个入参 interfaces就是需要代理实例实现的接口列表.

GCLib采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用n并顺势织入横切逻辑.

简述一下Spring AOP的设计原理
在这里插入图片描述
1)代理的创建
创建代理工厂:拦截器数组,目标对象接口数组,目标对象。
创建代理工厂时,默认会在拦截器数组尾部再增加一个默认拦截器 —— 用于最终的调用目标方法。
当调用 getProxy 方法的时候,会根据接口数量大余 0 条件返回一个代理对象(JDK or Cglib)。
注意:创建代理对象时,同时会创建一个外层拦截器,这个拦截器就是 Spring 内核的拦截器,用于控制整个 AOP 的流程。
2)代理的调用
当对代理对象进行调用时,就会触发外层拦截器。
外层拦截器根据代理配置信息,创建内层拦截器链。创建的过程中,会根据表达式判断当前拦截是否匹配这个拦截器。而这个拦截器链设计模式就是职责链模式。
当整个链条执行到最后时,就会触发创建代理时那个尾部的默认拦截器,从而调用目标方法,最后返回。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
spring事务
在这里插入图片描述
在这里插入图片描述
1.融入 2.挂起 3.嵌套
在这里插入图片描述
在这里插入图片描述
挂起事务,是通过线程绑定的切换
在这里插入图片描述

在这里插入图片描述
required: A存在事务则融入,A不存在则B新开启一个事务
support: A存在事务则融入,A不存在则B以非事务方式运行
mandatory(强制有事务):A存在事务则融入,不存在则B抛异常
never:A存在事务则抛异常,不存在则以非事务运行
not_requires:A存在事务则挂起A事务,A不存在则B开启一个新事务

not_supports:A存在事务则挂起A事务,B以非事务方式运行,A不存在则B以非事务运行、

nested(嵌套)A存在事务则以嵌套方式运行,不存在则开启一个新事务

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值