一、请你谈谈Spring中自动装配的方式有哪些?

答:①no:不进行自动装配,手动设置Bean的依赖关系。

②byName:根据Bean的名字进行自动装配。

③byType:根据Bean的类型进行自动装配。

⑤constructor:类似于byType,不过是应用于构造器的参数,如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则会导致错误。

⑥autodetect:如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用byType的方式进行自动装配。

自动装配没有自定义装配方式那么精确,而且不能自动装配简单属性,在使用时应注意。

二、请问Spring中Bean的作用域有哪些?

答:在Spring的早期版本中,仅有两个作用域:singleton和prototype,前者表示Bean以单例的方式存在;后者表示每次从容器中调用Bean时,都会返回一个新的实例,prototype通常翻译为原型。设计模式中的创建型模式中也有一个原型模式,原型模式也是一个常用的模式,例如做一个室内设计软件,所有的素材都在工具箱中,而每次从工具箱中取出的都是素材对象的一个原型,可以通过对象克隆来实现原型模式。

Spring中WebApplicaitonContext新增了三个作用域,分别是:

request:每次http请求都会创建一个新的bean。

session:同一个HttpSession共享同一个Bean,不同的HttpSession使用不同的Bean。

globalSession:同一个全局Session共享一个Bean。

三、请问什么是Ioc和DI?并且简要说明一下DI是如何实现的?

答:控制反转是把传统上由程序代码直接操作的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的控制反转就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。

依赖注入的基本原则就是应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由容器负责,查找资源的逻辑应该从应用组件的代码中抽取出来,交给容器来完成。di是ioc更准确的描述,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。

一个类A需要用到接口B中的方法,那么就需要为类A和接口B建立关联或依赖关系,最原始的方法就是在类A中创建一个接口B的实现类C的实例,但这种方法需要开发人员自行维护二者的依赖关系,也就是说当依赖关系发生变动的时候需要修改代码并重新构建整个系统。如果通过一个容器来管理这些对象以及对象的依赖关系,则只需要在类A中定义好用于关联接口B的方法,将类A和接口B的实现类C放入容器中,通过对容器的配置来实现二者的关联。

依赖注入可以通过setter方法注入(设值注入)、构造器注入和接口注入三种方式来实现。

Spring支持setter注入和构造器注入,通常使用构造器注入来注入必须的依赖关系,对于可选的依赖关系,则setter注入是更好的选择,setter注入需要类提供无参构造器或者无参的静态工厂方法来创建对象。

四、请说明一下Spring中BeanFactory和ApplicationContext的区别?

答:BeanFactory是spring中比较原始,比较古老的factory。因为比较古老,所以beanFactory无法支持spring插件,例如AOP,web应用等功能。

ApplicationContext是BeanFactory的子类,因为古老的BeanFactory无法满足不断更新的spring的需求,于是ApplicationContext就基本上代替了BeanFactory的工作,以一种更面向框架的工作方式以及对上下文进行分层和实现继承,并在这个基础上对功能进行扩展:

(1)MessageSource,提供国际化的消息访问。

(2)资源访问(如URL和文件)

(3)事件传递

(4)Bean的自动装配

(5)各种不同应用层的Context实现

区别:

(1)如果使用ApplicationContext,如果配置的bean是singleton,那么不管你有没有或者想不想用它,它都会被实例化。好处是可以预先加载,坏处是浪费内存。

(2)BeanFactory,当使用BeanFactory实例化对象时,配置的bean不会马上被实例化,而是等到你使用该bean的时候才会被实例化。好处是节约内存,坏处是速度比较慢。多用于移动设备的开发。

(3)没有特殊要求的情况下,应该使用ApplicationContext完成。因为BeanFactory能完成的事情,ApplicationFactory都能完成,并且提供了更多接近现在开发的功能。

五、请说明一下springIOC原理是什么?如果你要实现IOC需要怎么做?请简单描述一下实现步骤?

答:IOC,这是spring的核心,贯穿始终。所谓IOC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。IOC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了spring我们就只需要告诉spring,A中需要一个Connection对象,至于这个connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖Connection才能正常运行,而这个connection是由spring注入到A中的,依赖注入的名字就是这么来的。那么DI是怎么实现的呐?java1.3之后一个重要特征是反射,它允许程序在运行的时候动态的生成对象,执行对象的方法,改变对象的属性,spring就是通过反射来实现注入的。

实现IOC的步骤:

①定义用来描述bean的配置的java类。

②解析bean的配置,将bean的配置信息转换为上面的beanDefinition对象保存在内存中,spring中采用hashmap进行对象存储,其中会用到一些xml解析技术。

③遍历存放BeanDefinition的HashMap对象,逐条取出BeanDefinition对象,获取bean的配置信息,利用java的反射机制实例化对象,将实例化后的对象保存在另外一个Map中即可。

六、请简单说明一下依赖注入的方式有哪几种?

答:①Set注入;②构造器注入;③接口注入。

七、请说明一下@Controller和@RestController的区别是什么?

答:@RestController注解相当于@ResponseBody+@Controller合在一起的作用。

八、请谈一下autowired和resouece的共同点和区别是什么?

答:共同点:两者都可以写在字段和setter方法上,两者如果都写在字段上,那么就不需要再写Setter方法。

不同点:@Autowired为Spring提供的注释,只按照byType注入。@Autowired注解是按照类型(byType)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false.如果我们想使用 按照名称(byName)来装配,可以结合@Qualifier注解一起使用。

@Resource默认按照byName自动注入。@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。

九、请问Spring支持的事务管理类型有哪些?

答:Spring支持编程式事务管理和声明式事务管理。许多spring框架的用户选择声明式事务管理,因为这种方式和应用程序的关联较少,因此更加符合轻量级容器的概念。声明式事务管理要优于编程式事务管理,尽管在灵活性方面它弱于编程式事务管理,因为编程式事务允许你通过代码控制业务。

事务分为全局事务和局部事务。全局事务由应用服务器管理,需要底层服务器JTA支持。局部事务和底层采用的持久化方案有关。

十、请问Struts拦截器和SpringAOP有什么区别?

答:拦截器是AOP的一种实现,struts2拦截器采用xwork2的interceptor1而spring的AOP基于IOC基础,其底层采用动态代理与CGLIB代理两种方式结合的实现方式。

十一、请问持久层设计要考虑的问题有哪些?请谈一下你用过的持久层框架都有哪些?

答:所谓“持久”就是将数据保存到可掉电式从存储设备中以便今后使用,简单的说,就是将内存中的数据保存到关系型数据库。文件系统、消息队列等提供持久化支持的设备中。持久层就是系统中专注于实现数据持久化的相对独立的层面。‘

持久层设计的目标包括:

①数据存储逻辑的分离,提供抽象化的数据访问接口。

②数据访问底层实现的分离,可以在不修改代码的情况下切换底层实现。

③资源管理和调度的分离,可以在不修改代码的情况下切换底层实现。

④资源管理和调度的分离,在数据访问层实现统一的资源调度(如缓存机制)。

⑤数据抽象,提供更面向对象的数据操作。

持久层框架有:Hibernate,Mybatis,Spring Data.