目录
6、BeanFactory和ApplicationContext有什么区别?
1、IOC是什么
控制反转:将对象的控制权转移给Spring框架,由 Spring 来负责控制对象的生命周期(比如创建、销毁、注入依赖对象)和对象间的依赖关系。控制对象生命周期的不再是引用它的对象,而是Spring容器,而引用对象只是被动的接受依赖对象,所以这叫控制反转。
2、DI是什么
依赖注入:IoC 的一个重点就是在程序运行时,动态的向某个对象提供它所需要的其他对象,这一点是通过DI(Dependency Injection,依赖注入)来实现的,即应用程序在运行时依赖 IoC 容器来动态注入对象所需要的外部依赖。而 Spring 的 DI 具体就是通过反射实现注入的,反射允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性。
3、AOP
面向切面编程:作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块。
a、AOP实现的关键在于代理模式,AOP代理主要分为静态代理和动态代理。
静态代理的代表为AspectJ,也称为编译时增强,AOP框架会在编译阶段生成AOP代理类,并将AspectJ(切面) 织入到Java字节码中,运行的时候就是增强之后的AOP对象;
b、动态代理则以Spring AOP为代表,动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理
- JDK动态代理:只提供接口的代理,不支持类的代理,核心是InvocationHandler接口和Proxy类。在获取代理对象时,使用Proxy类来动态创建目标类的代理类。
- CGLIB动态代理:如果被代理类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象。
4、Spring Bean的生命周期
spring bean生命周期流程
代码解释
public class SpringTest implements BeanNameAware,BeanPostProcessor, InitializingBean, DisposableBean {
//1、实例化bean。调用createBean进行实例化
//2、设置对象属性。通过BeanWrapper提供的设置属性的接口完成属性设置与依赖注入
//3、处理Aware接口。可以让我们拿到Spring容器的一些资源。如:BeanNameAware、BeanFactoryAware、ApplicationContextAware
@Override
public void setBeanName(String beanName) {
}
//4、BeanPostProcessor前置处理
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
//5、InitializingBean.如果Bean实现了InitializingBean接口,执行afeterPropertiesSet()方法。
//init-method:如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法
@Override
public void afterPropertiesSet() throws Exception {
}
//6、BeanPostProcessor后置处理。这个方法是在Bean初始化结束时调用的,被应用于内存或缓存技术。
//到这里Bean就已经被正确创建了,之后可以使用这个Bean了
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
//7、bean不再被使用时,如果实现了DisposableBean接口,会调用destroy()方法
//destroy-method:最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法
@Override
public void destroy() throws Exception {
}
}
5、spring容器启动流程
6、BeanFactory和ApplicationContext有什么区别?
a、BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。
b、BeanFactory是IoC的核心,定义了IoC的基本功能,包含了Bean的生命周期管理。
c、ApplicationContext接口是BeanFactory的子类,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能
- 继承MessageSource,因此支持国际化。
- 资源文件访问,如URL和文件(ResourceLoader)。
- 载入多个(有继承关系)上下文(即同时加载多个配置文件) ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。
- 提供在监听器中注册bean的事件。
d、BeanFactroy采用的是延迟加载形式来注入Bean的,只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能提前发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。
e、ApplicationContext它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 不足是占用内存空间,当应用程序配置Bean较多时,程序启动较慢。
f、BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。
g、BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。
7、spring怎么解决循环依赖的问题
1、Spring是通过三级缓存来解决上述问题的
一级缓存: singletonObjects存储的是所有创建好了的单例Bean
二级缓存:earlySingletonObjects完成实例化,但是还未进行属性注入及初始化的对象
三级缓存:singletonFactories提前暴露的一个单例工厂,二级缓存中存储的就是从这个工厂中获取到的对象。
为什么要有三级缓存
- 先获取到三级缓存中的工厂;
- 调用对象工工厂的getObject方法来获取到对应的对象,得到这个对象后将其注入到B中。紧接着B会走完它的生命周期流程,包括初始化、后置处理器等。
- 当B创建完后,会将B再注入到A中,此时A再完成它的整个生命周期。至此,循环依赖结束!
8、spring mvc流程
- 用户发送请求至前端控制器DispatcherServlet;
- DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handler;
- 处理器映射器根据请求url找到具体的处理器Handler,生成处理器对象及处理器拦截器(如果有则生成),一并返回给DispatcherServlet;
- DispatcherServlet 调用 HandlerAdapter处理器适配器,请求执行Handler;
- HandlerAdapter 经过适配调用 具体处理器进行处理业务逻辑;
- Handler执行完成返回ModelAndView;
- HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
- DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
- ViewResolver解析后返回具体View;
- DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
- DispatcherServlet响应用户。
参考:
1、spring必读:Spring常见面试题总结(超详细回答)_张维鹏的博客-CSDN博客_spring面试题
2、spring mvc:SpringMVC常见面试题总结(超详细回答)_张维鹏的博客-CSDN博客_springmvc面试题
3、循环依赖解决: