当前位置: 首页 > 科技观察

春季IOC后辈面试题(上)

时间:2023-03-23 12:09:17 科技观察

前段时间是校招的高峰期。很多大三小三出去面试的时候都会被问到一个问题。说说你对Spring的理解?很多同学可以讲IOC,AOP等等,但是讲到IOC的一些细节的时候,就不知道怎么和面试官继续聊下去了。那么今天就和大家详细聊聊SpringIOC!!!什么是春天?首先,它是一个框架。在我们的开发工作环境中,其他框架基本都依赖于Spring,spring作为一个容器。角色,用来承载我们整体的bean对象。它帮助我们组织管理整个bean从创建到销毁。什么是IOC控制反转?类的创建和销毁都由Spring来控制,也就是说,控制对象生命周期的不再是引用它的对象,而是Spring控制了整个过程。对于一个具体的对象,以前是它去控制其他的对象,现在所有的对象都被Spring控制了。看到这里,其实这些都是一些简单的理解和一些官方的说法。为了真正理解什么是SpringIoc,上面的东西是远远不够的,所以我给大家画了一张流程图,按照这张流程图,我们一步步来分析IOC。只有分析完流程,才能对架构有个大概的了解。后面会讲到DI(DependencyInjection)以及如何处理缓存依赖。这里有个知识点分享给大家。在看一些架构的源码的时候,首先要理清整体架构的脉络,这样我们才能很容易的理解整个架构。不然你会一头雾水,不知道自己在写什么!!!话不多说,直接看整体流程图!!!从这张图开始,我们从上到下,从左到右进行解释。publicstaticvoidmain(String[]args){ApplicationContextcontext=newClassPathXmlApplicationContext("classpath:applicationContext.xml");}我们首先启动spring容器。常见的配置bean有XML配置文件形式或注解形式,也有其他一些方式。无论哪种方式,考虑到可扩展性问题,spring都会通过BeanDefinitionReader加载bean的配置信息,然后生成一个BeanDefinition(bean的定义信息,用于存放bean的所有属性方法定义)。BeanDefinitionReader只是一个接口,用来约束一些定义信息,常用的实现类XmlBeanDefinitionReader(xml形式)、PropertiesBeanDefinitionReader(属性配置文件)、AbstractBeanDefinitionReader(与一些环境信息相关)等,BeanFactoryPostProcesser讲完了BeanDefinition,那么下一步就是转到BeanFactoryPostProcessor。BeanFactoryPostProcessor接口是Spring初始化BeanFactory时暴露的扩展点。其实在bean被实例化之前,可以获取bean的定义信息,修改相关信息。比如我们常见的加载bean信息的注解方法,其实就是由BeanFactoryPostProcessor的子类实现的。我们常见的@Service、@Controller、@Repository等注解其实都是组合注解,通过Component注解来实现,如下GIF动图所示:ps:过大可能会导致加载时出现问题。从这个动画可以发现BeanFactoryPostProcessor有一堆实现子类,所以当我们有自己的业务逻辑实现时,只需要实现BeanFactoryPostProcessor,然后加上@Component注解即可。BeanFactoryBeanFactory,从名字也很好理解,是一个生产bean的工厂,它负责生产和管理每一个bean实例。同时也是暴露的Spring容器获取bean的入口。BeanFactory的生产过程实际上是利用反射机制实现的。接下来我们看一下BeanFactory的继承关系。这个关系图中我们只需要了解几个关键点:HierarchicalBeanFactory:提供父容器的访问功能ListableBeanFactory:提供批量获取bean的方法AutowireCapableBeanFactory:在BeanFactory的基础上实现现有实例的管理ConfigurableBeanFactory:注册单例bean的生成实例,单例bean的统计等信息ConfigurableListableBeanFactory:增加了一些其他的功能:类加载器,类型转换,属性编辑器,BeanPostProcessor,bean定义,处理bean依赖,如何销毁bean等还有其他功能DefaultListableBeanFactory:实现BeanFactory的所有功能,注册BeanDefinition。有人会问,ApplicationContext和BeanFactory只是一种继承关系吗?ApplicationContextapplicationContext=newClassPathXmlApplicationContext("classpath:applicationContext.xml");BeanFactoryfactory=newClassPathXmlApplicationContext("classpath:applicationContext.xml");BeanFactory是一个底层的IOC容器,ApplicationContext在它的基础上增加了它的一些特性,同时增加了一些其他的集成特性比如:更好的集成SpringAOP,消息的国际化,事务的发布,这些新特性如资源访问。所以BeanFactory和ApplicationContext不是一回事,而是两个不同的对象。如果想获取BeanFactory,可以通过applicationContext.getParentBeanFactory()获取。所以在通过XML配置bean信息的时候,我们可以使用BeanFactory作为容器,因为我们不需要那么多其他的附加功能。当我们以注解的形式注册bean信息时,我们就可以使用ApplicationContext作为容器。当然,这只是为了理解。基本上,我们不需要在业务代码中关心这个。Bean生命周期SpringBean的生命周期其实是Spring面试题中非常常见的一道面试题。其实没必要背那么多流程。其实在Spring的源码中已经写好了bean完整的生命过程。上面的BeanFactory中已经展示过了。BeanNameAware#setBeanName:在创建这个bean的bean工厂中设置bean的名称,在普通属性设置之后,InitializinngBean.afterPropertiesSet()方法之前调用setBeanFactory:回调提供了它自己的bean实例工厂。设置公共属性后,调用org.springframework.context.ResourceLoaderAware#setResourceLoaderbeforeInitializingBean.afterPropertiesSet()或自定义初始化方法:Callaftercommonbeanobjects,afterPropertiesSetorcustom在ApplicationContextAware的init-method之前调用。org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher:在普通bean属性之后调用,在初始化调用afterPropertiesSet或自定义初始化方法之前调用。在ApplicationContextAware之前调用。org.springframework.context.MessageSourceAware#setMessageSource:在普通bean属性之后、初始化调用afterPropertiesSet或自定义初始化方法之前以及ApplicationContextAware之前调用。org.springframework.context.ApplicationContextAware#setApplicationContext:在普通Bean对象生成之后,InitializingBean.afterPropertiesSet之前或者用户自定义的初始化方法之前调用。ResourceLoaderAware.setResourceLoader、ApplicationEventPublisherAware.setApplicationEventPublisher、MessageSourceAware后调用org.springframework.web.context.ServletContextAware#setServletContext:运行时设置ServletContext,普通bean初始化后调用org.springframework.beans.factory.config.BeanPostProcessial:InpostBostProcessial这个BeanPostProcessor应用于给定的新bean实例InitializingBean#afterPropertiesSet:在设置所有bean属性后由包含BeanFactory调用#getDestroyMethodName:返回被销毁的bean的名称你可以自己查看。每个方法都有详细的注解,我只是凭着眼光简单翻译了一下。整个过程中bean的生命周期可以缩短理解为:但是要完全理解Spring,必须是Spring中一个非常重要的方法**ApplicationContext.refresh()**,它包含13个子方法:publicvoidrefresh()throwsBeansException,IllegalStateException{//添加一个synchronized防止其他操作(启动,或销毁)在刷新完成前发生。同步(this.startupShutdownMonitor){//1。Preparations//记录容器的启动时间,//标记“started”状态,关闭状态为false,//将当前系统属性加载到环境对象中//准备一系列的监听器和事件收集对象prepareRefresh();//2。创建容器对象:DefaultListableBeanFactory,加载XML配置文件的属性在当前工厂中(默认使用命名空间解析),也就是上面提到的BeanDefinition(bean定义信息)这里还没有初始化,但是配置信息已经提取出来了,(包括里面的值其实只是占位符)ConfigurableListableBeanFactorybeanFactory=obtainFreshBeanFactory();//3.BeanFactory准备,设置BeanFactory类加载器,添加几个BeanPostProcessor,手动注册几个特殊bean等。prepareBeanFactory(beanFactory);try{//4.子类的重写方法做了额外的处理,就是我们刚开始提到的BeanFactoryPostProcessor。具体的子类可以在这一步添加一些特殊的BeanFactoryPostProcessor来完成对beanFactory的修改或扩展。//当我们到达这里时,所有的bean都被加载并注册了,但是postProcessBeanFactory(beanFactory);//5.调用BeanFactoryPostProcessor的各个实现类的postProcessBeanFactory(factory)方法invokeBeanFactoryPostProcessors(beanFactory);//6.RegisterBeanPostProcessor处理器这里只是注册函数,真正调用的是getBean方法registerBeanPostProcessors(beanFactory);//7.初始化当前ApplicationContext的MessageSource,即国际化处理initMessageSource();//8.初始化当前ApplicationContextDevice的事件广播,initApplicationEventMulticaster();//9.从方法名就可以知道,一个典型的模板方法(hook方法),有兴趣的同学也可以回顾一下之前写的设计模式中的-template方法模式//具体子类可以在这里初始化一些特殊的bean(在初始化singletonbeans之前)onRefresh();//10。注册事件监听器,监听器需要实现ApplicationListener接口。这不是我们的重点,通过registerListeners();//11。初始化所有singletonbeans(lazy-init除外),关注finishBeanFactoryInitialization(beanFactory);//12.广播事件,ApplicationContext初始化完成finishRefresh();}catch(BeansExceptionex){if(logger.isWarnEnabled()){logger.warn("上下文初始化时遇到异常-"+"取消刷新尝试:"+ex);}//13。销毁初始化的单例Bean,这样一些bean就不会一直被占用ResourcedestroyBeans();cancelRefresh(ex);//抛出异常throwex;}finally{//ResetcommonintrospectioncachesinSpring'score,sincewe//mightnoteverneedmetadataforsingletonbeansanymore.....你可以自己试试这个断点。或者以后在这里单独写一篇文章详细的过程。没有必要通过破解源代码来查看每个方法。先了解一个大概的思路,然后分几次断点。每一个断点都比上一个入口深一点,完全可以看懂。.这是一个漫长的过程。总结一下SpringIOC的整个启动过程,这里先说一下。由于篇幅问题,恐怕会显得有些不适应。给大家分享一下如何处理循环依赖问题,以及DI依赖注入等源码分析。看到这里我整理了几个比较常见的面试给大家加深巩固:BeanFactory和ApplicationContext的区别?BeanFactory是一个低级的IOC容器,ApplicationContext同时增加了它的一些特性和一些其他的特性集成特性如:更好的集成SpringAOP、国际化消息、事务发布、资源访问等新特性.BeanFactory和FactoryBean有什么区别?BeanFactory是IoC的底层容器,而FactoryBean是一种创建bean的方式,帮助实现复杂的SpringIoC容器启动过程的初始化逻辑?只要理解了第一个流程图和最终ApplicationContext.refresh()方法中的13个内部子方法,回答这个问题应该问题不大。面试官应该Willshine,ho,something!!!

最新推荐
猜你喜欢