spring常见面试题

1.Spring

Spring 框架现在是 Java 后端框架家族里面最强大的一个,其拥有 IOC 和 AOP 两大利器,大大简化了软件开发复杂性。并且,Spring 现在能与所有主流开发框架集成,可谓是一个万能框架,Spring 让 JAVA 开发变得更多简单。
面试真题:
(1)什么是控制反转(IOC)?什么是依赖注入?
(2)请解释下Spring中的IOC?
(3)将Spring配置到你的应用中共有几种方法?
(4)怎样用注解的方式配置Spring?
(5)描述Spring Bean的生命周期?
(6)描述Spring中各种Bean的范围?
(7)什么是Spring的嵌入beans?
(8)Spring框架中的单例bean是否是线程安全的?
(9)请举例说明如何用Spring注入一个Java的集合类?
(10)请举例说明如何在Spring的Bean中注入一个java.util.Properties?
(11)请解释Spring的Bean的自动生成原理?
(12)请辨析自动生成Bean之间模块的区别?
(13)如何开启基于基于注解的自动写入?
(14)请举例说明@Required注解?
(15)请举例说明@Autowired注解?
(16)请举例说明@Qualifier注解?
(17)请说明构造器注入和setter方法注入之间的区别?
(18)Spring框架中不同类型event有什么区别?
(19)FileSystemResource和ClassPathResource有何区别?
(20)请列举Spring框架中用了哪些设计模式?

 

(1)什么是控制反转(IOC)?什么是依赖注入?

Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。

●谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

●为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

  理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

  ●谁依赖于谁:当然是应用程序依赖于IoC容器;

  ●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;

  ●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;

  ●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

 

(2)将Spring依赖注入的三种实现方式?

     ●构造器注入 
     ●Setter方法注入 
     ●接口注入

(3)将Spring配置到你的应用中共有几种方法?

     ●基于xml的配置

     ●基于注解的配置

     ●基于java的配置

(4)怎样用注解的方式配置Spring?

  使用注解的方式使我们无需在XML中配置一个Bean引用,更加简单和方便。

  注解配置默认情况下在Spring中是关闭的,我们需要在配置文件中使用<context:annotation-config/>激活它。

  • @Required注解应用于bean属性的setter方法
  • @Autowired注解可以应用到bean属性的setter方法,非setter方法,构造函数和属性
  • @Qualifier,通过指定确切的将被引用的bean,@Autowired@Qualifier注解可以用来删除混乱
  • JSR-250 Annotations,Spring支持JSR-250的基础的注解,其中包括了@Resource@PostContruct@PreDestory注解

@Required注解

@Required注解应用于bean属性的setter方法,它表示受影响的bean属性在配置时必须放在XML配置文件中,否则容器就会抛出一个BeanInitializationException异常。

@Required注解用于注解属性的setter方法,如果一个属性的setter方法被@Required注解,则表示在XML配置中,该属性一定要注入值,否则会报异常。

 setter方法中的@Autowired

当Spring遇到一个在setter方法中使用的@Autowired注解,它会通过byType的方法自动为该属性注入值。

属性中的@Autowired注解

我们可以直接在属性上运用@Autowired注解,这样我们可以无需为该属性写setter方法,Spring会自动为该属性注入值。

构造方法中的@Autowired注解

默认情况下,@Autowired注解意味着依赖是必须的,它类似于@Required注释,然而,你可以使用@Autowired(required=false) 选项关闭默认行为。

@Qualifier注解

当我们创建多个具有相同类型的bean时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,我们可以结合使用@Qualifier@Autowired注解通过指定哪一个真正的bean将会被装配来消除混乱。

@Resource注解

我们可以在字段中或者setter方法中使用@Resource注解,它使用一个name属性,该属性以一个bean名称的形式被注入,也就是说,它遵循byName形式的自动装配。

@Resource@Autowired注解的用法很类似,它们的区别如下:

    • @Autowired注解为Spring提供的注解,只按照byType方式注入,默认情况下,它要求依赖对象必须存在,如果允许为null,可以设置它的required属性为false,如果我们想按照byName方式来装配,可以结合@Qualifier注解一起使用;
    • @Resource为J2EE提供的注解,它有两个重要的属性:nametype。而默认情况下,@Resource注解按照byName的方式来装配。@Resource的装配顺序是这样的: 
      • 如果同时指定了nametype,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
      • 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
      • 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
      • 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。

(5)怎样基于java配置的方式配置Spring?

  • Spring对Java配置的支持是由@Configuration注解和@Bean注解来实现的。由@Bean注解的方法将会实例化、配置和初始化一个新对象,这个对象将由Spring的IoC容器来管理。@Bean声明所起到的作用与<bean/> 元素类似。被@Configuration所注解的类则表示这个类的主要目的是作为bean定义的资源。被@Configuration声明的类可以通过在同一个类的内部调用@Bean方法来设置嵌入bean的依赖关系。

(8)Spring框架中的单例bean是否是线程安全的?

这取决于你的bean是否是有状态的;如果单例Bean,是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Spring mvc 的 Controller、Service、Dao等,这些Bean大多是无状态的,只关注于方法本身。

默认情况下Spring的bean都是单例的,所以就一般业务开发中bean都是无状态的(比如DAO层),所以是线程安全的。

但你的bean是有状态的话(比如你要在bean中存储某些数据),就需要将bean的scope改成prototype,让每次请求都相当于重新new一个bean,这样就是线程安全的了。

Spring作用域(scope)的配置区别:

  • 非线程安全:Singleton(默认): Spring容器只存在一个共享的bean实例。对于单例Bean,所有线程都共享一个单例实例Bean,因此是存在资源的竞争。
  • 线程安全:    Prototype: 每次对bean的请求都会创建一个新的bean实例。对于原型Bean,每次创建一个新对象,也就是线程之间并不存在Bean共享,自然是不会有线程安全的问题。   

使用实例:

  • DAO层的实现类推荐设置scope="singleton",这些类没有状态,只需用singleton只需维护一个实例,可提高性能。
  • Struts2的action类推荐设置scope="prototype",action显然是有状态的,需要每次创建一个新的实例,保证线程安全。

拓展:

有状态对象(Stateful Bean) :就是有实例变量的对象,可以保存数据,是非线程安全的。每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每个用户最初都会得到一个初始的bean。

无状态对象(Stateless Bean):就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean 的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的。

27. 解释Spring框架中bean的生命周期。

  • Spring容器 从XML 文件中读取bean的定义,并实例化bean。
  • Spring根据bean的定义填充所有的属性。
  • 如果bean实现了BeanNameAware 接口,Spring 传递bean 的ID 到 setBeanName方法。
  • 如果Bean 实现了 BeanFactoryAware 接口, Spring传递beanfactory 给setBeanFactory 方法。
  • 如果有任何与bean相关联的BeanPostProcessors,Spring会在postProcesserBeforeInitialization()方法内调用它们。
  • 如果bean实现IntializingBean了,调用它的afterPropertySet方法,如果bean声明了初始化方法,调用此初始化方法。
  • 如果有BeanPostProcessors 和bean 关联,这些bean的postProcessAfterInitialization() 方法将被调用。
  • 如果bean实现了 DisposableBean,它将调用destroy()方法。

 

posted @ 2020-09-04 17:53  小菜bxb  阅读(289)  评论(0编辑  收藏  举报