如何假装精通spring ioc

本文仅研究(吹哔)面试可能会问道的问题

spring ioc是一个hr经常会问的东西,有些是概念性的东西,我个人不太喜欢背概念,所以我经常会换一种表达方式

首先来说spring ioc是什么东西,百度一下,就会有一大堆概率,比如控制反转,依赖注入之类,那么我的目标是不说源码,不说概念,让别人觉得我也很懂这个东西,那我选择暂时偷换下概念,我不讲原理,那我选择讲故事

假设小明上班,需要用到一个叫做bean的东西,这个东西是每次使用都需要重新制作,使用完之后需要扔到垃圾场的。现在小明公司和一家工厂展开合作了,小明发现,他只需要在一开始告诉工厂的员工,如何制作这个bean,那么这个工厂就会在小明需要bean的时候把bean送到小明手上,并且在小明使用玩之后,工厂派人讲bean丢到垃圾场,这个工厂就是spring ioc

如果hr问spring ioc的原理或者实现,可以拿以上故事糊弄一下

另外大概率会问道bean的创建过程和生命周期,创建过程大致可以推论一下:工厂拿到小明的订单(xml),通过订单上信息(配置)创建bean,再通过订单号(xml上的id属性),将创建的bean存放在对应的地方(注册到beanMap)。生命周期:工厂拿到订单产生订单号准备生产(创建实例),送到车间完成生产(初始化),再送到小明手中(使用),回收小明丢弃的bean(销毁)

还有一些经常会被问到的问题,我在下面列一下:

ApplicationContext与BeanFactory的区别:BeanFactory就像是乡村小作坊,ApplicationContext就是控股BeanFactory的都市大公司,ApplicationContext作为高级容器,兼有BeanFactory(低级容器)的所有功能,而且支持访问文件资源,支持事件发布通知,支持接口回调等等,不过ioc的话,BeanFactory本身的功能已经足够实现

依赖注入:工厂生产的A产品包含B产品,在生产A产品的时候工厂自己给A配置了B产品,这样的方式就是依赖注入,也就是构建A的时候注入了A需要的B的bean。依赖注入可以是通过构造函数,也可以通过属性的set,还可以通过自动装配。

spring ioc如何构建容器:spring ioc容器初始化其实就是ClassPathXmlApplicationContext的初始化过程,我们可以从代码中看到

 public ClassPathXmlApplicationContext(String[] paths, Class clazz, @Nullable ApplicationContext parent) throws BeansException {
        super(parent);
        Assert.notNull(paths, "Path array must not be null");
        Assert.notNull(clazz, "Class argument must not be null");
        this.configResources = new Resource[paths.length];

        for(int i = 0; i < paths.length; ++i) {
            this.configResources[i] = new ClassPathResource(paths[i], clazz);
        }

        this.refresh();
    }
public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.setBeanClassLoader(this.getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
        if (beanFactory.containsBean("loadTimeWeaver")) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        if (!beanFactory.containsLocalBean("environment")) {
            beanFactory.registerSingleton("environment", this.getEnvironment());
        }

        if (!beanFactory.containsLocalBean("systemProperties")) {
            beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
        }

        if (!beanFactory.containsLocalBean("systemEnvironment")) {
            beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
        }

    }

可以看到这里调用了一个高级容器的refresh方法,在这里refresh里面,首先读取配置初始化了 低级容器beanFactory,然后再处理一些高级容器的功能,比如监听等

spring ioc的面试问题一般不会有太多花样,如果大家有遇到其他花样的面试题,欢迎留言分享

你可能感兴趣的:(java面试吹哔大全)