面试记录 2019-06-21 下午 (过)

华为外包
无笔试,两场,共6轮面试。
基础问题,基本和之前一致,在复试会问一些“应用题”,考察思维。我觉得自己答得都不是很好,但最后都过了,也许是归结为前一场面试下来后有总结。

  • 数据库:B+ 索引、SQL 优化思路、是否有优化经验。
  • 容器:一般都会问 HashMap
  • Spring:谈 Spring 有什么用途,谈对 Spring 的理解、解决什么问题。
  • Spring MVC:谈原理或者执行过程,谈对 Spring MVC 的理解、解决什么问题。
  • 并发:线程实现的方法、线程池、是否在项目中使用过。
  • 简介项目:谈负责哪些模块、用了哪些技术、其中有没有什么难点或者个人认为比较牛皮的地方。
  • 运行时数据区域

以上为基本都会问到的问题,以下为一些其他的问题:

1、Spring 如何设置为多例?设置多例需要注意什么?

在以前项目中还真没设置过多例,都是单例完事。

使用 scope 设置 Spring Bean 的类型,可以在 xml 中使用 scope 属性、含有 @Component 注解的普通 Java 类中或者含有 @Bean注解的配置类中使用 @Scope 注解,配置类的注解要放在工厂方法上。

@Scope annotations are only introspected on the concrete bean class (for annotated components) or the factory method (for @Bean methods). In contrast to XML bean definitions, there is no notion of bean definition inheritance, and inheritance hierarchies at the class level are irrelevant for metadata purposes.

@Scope注解只在具体的 bean 类(带注释的组件)或工厂方法(带@bean注解方法)上进行内省(be introspected 这什么意思?省略的意思么?或者生效的意思?我觉得应该是生效),相比于 xml 定义的 bean,没有 bean 定义继承的概念(xml 中的 bean 使用 parent 属性,指定父类,父类配置、默认属性都会继承,那么父类是多例的,子类也会是多例的)。

配置:

<bean id="animal" class="com.xuxx.bean.Animal" scope="prototype"/>
<bean id="dog" class="com.xuxx.bean.Dog" parent="animal"/>

测试:

com.xuxx.bean.Animal@61009542
com.xuxx.bean.Animal@77e9807f
com.xuxx.bean.Animal@448ff1a8
com.xuxx.bean.Dog@1a38c59b
com.xuxx.bean.Dog@7f77e91b
com.xuxx.bean.Dog@44a664f2

那么,Spring 为啥默认是单例、什么情况需要设置多例以及设置多例需要注意啥呢?

默认单例,只创建依一次,不会产生额外的对象,提高性能,不会频繁的创建、销毁、回收对象。 单例模式应该保证无状态、幂等性。

单例的话,如果有非静态成员变量,如果可以共享、并发度低,就没问题;在业务上不应该共享、并发度高,就应该设置为多例。

Struts2默认的实现是Prototype模式。也就是每个请求都新生成一个Action实例,所以不存在线程安全问题。

Bean 创建方式
  • 构造器(一般都用这个)
  • 静态工厂方法
  • 实例工厂方法(结合工厂类、实体类/产品类)

2、Spring 有哪几种注入方式?

从配置方式来讲有三种方式:注解、配置类、xml 配置。
从注入方式来讲分属性注入、构造器参数注入、配置类工厂方法注入。

  • @Autowired 是 Spring 的注解,默认 byType,根据类全部加载出来,如果一个类有多个实现类,需要配合 @Qualifier 指定具体类的 bean name。
  • @Inject 是 JSR330 规范,默认 byType,也可配合 @Qualifier 使用。
  • @Resource 是 JSR250 规范,默认 byName,bean name 默认为属性名。如果相同 bean name 的类有多个,可以使用type指定具体类。

3、Spring 如何注入集合

从来没做过注入集合,没有遇到这样需求。
注入集合的需求,可能为把一个类所有的实现类注入过来,放入一个 List?或者注入一些配置文件中的字符串?

  • xml xml 中的话会有各种标签,<list>、<set>、<map>,标签内部制定要注入的 <value>,map 内部为 <entry> 标签,需要制定 id 与 value。如果是注入 bean,则是 <ref> 标签, map 中 <entry> 标签使用value-ref属性。

注入普通属性:

<bean id="javaCollection" class="com.tutorialspoint.JavaCollection">

      <!-- results in a setAddressList(java.util.List) call -->
      <property name="addressList">
         <list>
            <value>INDIA</value>
            <value>Pakistan</value>
            <value>USA</value>
            <value>USA</value>
         </list>
      </property>

      <!-- results in a setAddressSet(java.util.Set) call -->
      <property name="addressSet">
         <set>
            <value>INDIA</value>
            <value>Pakistan</value>
            <value>USA</value>
            <value>USA</value>
        </set>
      </property>

      <!-- results in a setAddressMap(java.util.Map) call -->
      <property name="addressMap">
         <map>
            <entry key="1" value="INDIA"/>
            <entry key="2" value="Pakistan"/>
            <entry key="3" value="USA"/>
            <entry key="4" value="USA"/>
         </map>
      </property>
   </bean>

注入 bean:

<bean id="..." class="...">

      <!-- Passing bean reference  for java.util.List -->
      <property name="addressList">
         <list>
            <ref bean="address1"/>
            <ref bean="address2"/>
            <value>Pakistan</value>
         </list>
      </property>

      <!-- Passing bean reference  for java.util.Set -->
      <property name="addressSet">
         <set>
            <ref bean="address1"/>
            <ref bean="address2"/>
            <value>Pakistan</value>
         </set>
      </property>

      <!-- Passing bean reference  for java.util.Map -->
      <property name="addressMap">
         <map>
            <entry key="one" value="INDIA"/>
            <entry key ="two" value-ref="address1"/>
            <entry key ="three" value-ref="address2"/>
         </map>
      </property>

   </bean>

如果要注入一个 null,使用 <null/> 标签:
<property name="email"><null/></property>

如果使用注解,就采用第二个问题中的注解即可。比如,使用 @Autowired 把有用共同类的实现类都注入到集合,或者使用 @Resource 把具有相同 bean name 的类注入集合。

普通类型的属性可以使用 @value 注解从配置文件中读取。但是集合怎么操作呢?

4、Mybatis 动态标签

if,choose (when, otherwise),trim (where, set),foreach
一下子我懵了,完全想不起动态标签是这些。
动态标签

5、找出两个 List<Item> 内重复的元素放入一个新的 List 中

如果 Item 是同一地址,肯定同一元素,如果所有属性相同,也被判定为同一元素。
所以要重写 equals 和 hashCode 方法,使用一个 Set ,把第一个 List 装进去,遍历第二个 List,判断是否存在于 Set 中,存在则加入到新的 List 中。
当然做法不止这一个,当时我只想到这一个。

6、以下代码会有什么问题:

if(a == "1") {
  // 第一次登录的逻辑
} else if(a == "2") {
  // 第二次登录的逻辑
  if(b == "3") {
    // 一些提示信息
  }
} else {
  // 其他业务
}

不要管这个 a == "1" 是否会报错,这段代码约定不会报语法错误,能正常运行。
出这个题目考察什么呢?这里展示了一个逻辑控制,不要求去探究语法问题。还是没有思路啊。

可能是想表达第一次与第二次登录的逻辑只会执行一次,后续不会再执行了,而 else 中其他业务逻辑会经常执行,应该放在最前面?

7、应用题:任务调度

把一个15分钟调用一次的任务,改为15秒调用一次,需要注意哪些点?这个任务用于监控数据的获取。

这种题呢,只能根据自己的经验或者想法答了,如果有幸正好做好类似的,那肯定有得聊了。

  • 15分钟变为 15秒,为啥要这么变?以前为啥要 15分钟获取一次?是数据量太大,还是实时性不需要太高?
  • 那么15秒执行一次,获取数据的条件肯定得修改,不是调用端修改就是提供方修改了。如果能增量获取监控数据,也许不需要去重,为了保证监控数据的完整性,还是需要冗余获取比对去重。
  • 考虑数据量的问题,15秒执行一次,如果数据量比较大,要做一些IO操作或者其他固化操作,得考虑使用缓存或者消息队列或者异步执行。
  • 每次执行记录日志中。
  • 熔断操作,多次请求获取不到数据,就得熔断报错提醒。这一点可以参考 Hystrix Dashboard,看它是怎么做的。

8、应用题:设计接口给别人使用,需要考虑什么?

明确是 http 接口,不是 程序接口

  • 提供文档。比如使用 Swagger,就会包含接口说明、字段说明、测试用例。swagger 多用于内部使用,外部使用的话,得专门写。
  • 考虑可用性、并发性、限流、降级。得从系统架构上解决这个问题。
  • 考虑恶意调用。比如做单位时间内调用次数限制,操作次数后禁止调用,一定时间内自动解除或者手动解除。
  • 考虑安全性。比如使用 token 验证、https。
  • 报错信息完善。接口返回内容包括错误代码、错误信息、错误详情解决办法链接等。
  • 参考 RESTful 接口风格。
  • 接口拆分。提供一个大而全的接口,要针对相应场景拆分为小而专一的接口。
  • 考虑单一性。一个接口做一件事。
  • 考虑扩展性。比如,预留字段。
  • 是否使用缓存。使用缓存就要解决缓存穿透、缓存雪崩等问题。

想到啥就说啊,不管是自己之前有过的设计经验还是调用别人的接口的感受。
接口设计的16个原则

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。