跟面试官刚聊几句,被发现连这几道都不会,便被请了出去

简介: 跟面试官刚聊几句,被发现连这几道都不会,便被请了出去

IoC会怎么面试

Spring面试中,我们会经常被问到一个问题,那就是 什么是IoC?,说实话,我一直认为这个问题很容易回答,但又很难答的好。因为每个使用过的人对IOC都会有不同的看法,你同样的回答可以让这个面试官满意,但不一定就能让另一个面试官满意。

简单回答

IoC是一种控制反转的思想,主要有依赖查找和依赖注入实现。他们之间的关系就类似于好莱坞原则“你不要给我打电话,我们需要的时候会给你打电话”,即低层只需要管理好自己的具体实现,而高层有自己的一套做事逻辑,需要你的时候会去找你,不需要的时候就不会去调用你。

进一步回答

但是进一步也可以这么细讲,按照IoC的定义,那么有很多方面都可以是IoC,我们经常用的JavaBeans就是Ioc的一个实现,在基于Spring框架的项目开发中,Bean的存在是极为重要的,也因此很多面试都会专门挑Bean的生命周期来问。Servlet也是IoC的一种实现,因为他可以去依赖或者反向地通过JNDI(Java Naming and Directory Interface)的形式得到一些外部的资源,比如DataSource或者EJB的组件。这些都是比较常见的IoC实现。

然后讲讲反转控制,这里简单举个例子,比如消息机制,它就是其中的一种,使用过消息事件的程序员都知道,相比我们传统的调用方式,消息机制是一种被动的、推送的方式。这其实也属于Ioc中的一种实现。

拓展回答

再往深处说,就涉及到另一个我司经常问的一个问题:依赖查找和依赖注入的区别?

一般我会这样回答,依赖查找是手动或者主动的依赖查找方式,一般通过名称、通过类型、通过路径的方式来查找。是需要依赖于容器标准的API来实现,比如Servlet的API,这是一种显现的调用API的方式去获取你想要的资源。Spring-beans的BeanFactory里的getBean方法。

而依赖注入则是手动或者自动的绑定的方式,它不需要依赖特定的容器和API。最为常见的一种使用就是@Autowired的使用了。

一般如果只是面试初级程序员,那么面试官问完依赖查找和依赖注入后一般都会停止,如果你工作过2-3年,那么当你回答的问题涉及到Bean时,面试官可能会往更深层去提问你,考察你关于源码的了解情况。因为Bean本身就是IoC的一种实现,很多面试官问完IoC就会让你讲讲Bean,小面曾经就遇过“你知道几种方法去注册一个Spring Bean?

一般回答 通过BeanDefinition和外部单体对象来注册 即可得分。

运气比较差的就会被接着细问接下来的实现。

没错!那个运气比较差的就是我!!

BeanDefinition方式做法有很多,比如

1、XML配置元信息<bean name="..." .../>

2、使用注解来配置元信息@Bean,@Component,@Import,以及使用Java API来配置元信息

看看下面怎么使用JAVA 注解和标准API来怎么注册Bean

JAVA 注解和BeanDefinition对象:

//3.通过@Import方式注册
@Import(BeanRegistrationDemo.Config.class)
public class BeanRegistrationDemo {
    public static void main(String[] args)
    {
        //创建一个BeanFactory容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        //注册Configuration Class(配置类)
        applicationContext.register(BeanRegistrationDemo.class);
        applicationContext.refresh();
        User user = applicationContext.getBean("user", User.class);
        User user1 = applicationContext.getBean("user1", User.class);
        System.out.println("user对象是否一致:"+(user==user1));
        //关闭Spring应用上下文
        applicationContext.close();
    }
 //2.通过@Component方式注册
    @Component
    public static class Config
    {
        //1.通过@Bean方式注册
        @Bean(name = {"user","user1"})
        public User user()
        {
            User user = new User();
            return user;
        }
    }
}
//通过BeanDefinition注册
public static void main(String[] args)
{
        //创建一个BeanFactory容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        //通过BeanDefinition注册API实现
        registerBeanDefinition(applicationContext,"user");
     //启动上下文
        applicationContext.refresh();
        User user = applicationContext.getBean("user", User.class);
        System.out.println("user对象:" + user);
        //关闭Spring应用上下文
        applicationContext.close();
}
public static void registerBeanDefinition(AnnotationConfigApplicationContext applicationContext,String beanName)
{
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
        beanDefinitionBuilder.addPropertyValue("id", 1L);
        beanDefinitionBuilder.addPropertyValue("nickName", "xxxx");
     //注册bean
        applicationContext.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
}

@Bean,@Component,@Import都可以注册Bean,且一起用也不会出现Bean注册重复的问题。不过一般项目开发中,使用@Bean就足够了。

BeanDefinition则是把一个类手动的设置成一个Bean,不想注解那般方便,但是也是一种实现方式。

外部单体对象注册:

public static void main(String[] args)
    {
        //创建一个BeanFactory容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        //将当前类作为配置类(随便一个具体的实现类来替换即可)
        EchartServiceImpl echartServic = new EchartServiceImpl();
        //注册方法一
        //注册Configuration Class(配置类)
        ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
        beanFactory.registerSingleton("echartService", echartServic);
        //注册方法二
        //注册Configuration Class(配置类) -> Spring Bean
        applicationContext.registerBean("echartService", EchartServicImpl.class, () -> echartServic);
        //注册方法一和方法二只能二选一,否则会报bean名称相同的异常
        //启动Spring应用上下文
        applicationContext.refresh();
        //获取bean方法一
        EchartServicImpl service1 = applicationContext.getBean("echartService",EchartServicImpl.class);
        System.out.println("是否相等:"+(service1 == echartServic));
        //获取bean方法二
        EchartServicImpl servic2 = beanFactory.getBean("echartService", EchartServicImpl.class);
        System.out.println("是否相等:"+(servic2 == echartServic));
        //关闭Spring应用上下文
        applicationContext.close();
    }

简单讲解一下外部单体对象

1.我们需要创建一个BeanFactory工厂,new AnnotationConfigApplicationContext(),用它来存放我们的业务bean,存放可以直接使用applicationContext对象的registerBean()方法,也可以使用applicationContext.getBeanFactory()皆可。

2.注册完bean后使用applicationContext.refresh()启动Spring上下文后就可以使用依赖查找去获取bean了,然后判断完是否是同一个bean后,调用close()方法关闭掉Spring上下文销毁bean。

3.一个简单的Bean注册与依赖查找就完成了。

结束

这次的介绍到此为止,IOC的运用实在多种多样,因为在Spring框架的开发中,与它有关的东西实在太多太多,接下来的内容,我会在后续文章中对IOC进行介绍。关注我,不要让自己错过任何一点知识点。

相关文章
|
6月前
|
SQL 关系型数据库 MySQL
几道常见面试问题总结(二)
几道常见面试问题总结(二)
|
4月前
|
关系型数据库 MySQL 测试技术
|
3月前
|
算法
分享几道大厂面试算法题
分享几道大厂面试算法题
|
6月前
|
存储 Go 调度
听说90%的人都没搞定手撕协程池这道面试题!
听说90%的人都没搞定手撕协程池这道面试题!
|
6月前
|
算法 前端开发 JavaScript
面试必会的几道算法
面试必会的几道算法
|
算法 程序员
程序员可能越来越排斥面试时做题的原因
程序员可能越来越排斥面试时做题的原因
73 1
|
SQL 缓存 网络协议
面试官问你MySQL优化,这么说完,面试官听完都哭了QAQ
面试官问你MySQL优化,这么说完,面试官听完都哭了QAQ
103 1
|
算法 C++ Python
【每日算法Day 107】面试必考:良心推荐,一题三解,不看后悔一辈子
【每日算法Day 107】面试必考:良心推荐,一题三解,不看后悔一辈子
123 0