第1章Spring面试技巧
1-1 IOC与DI的理解
IOC 控制翻转,是一种设计理念,由第三方来管理与控制对象。
通常我们创建对象时都是通过new 关键字来实现的。这就带来一些问题。
1、每次我们需要使用 对象时,都要手动创建。
2、当我们需要对某一个类进行修改时,需要手动将所有通过new 关键字创建的对象,从新编写。工作量将会非常恐怖。
解决办法就是使用“对象容器”,动态生成JavaBean 对象。通过使用“容器”(applicationContext)我们可以程序中有效的依赖实现“解耦”(降低耦合接触耦合)。
控制翻转–传统情况下我们使用“new”关键字创建对象,也就是由我们编译的程序代码决定使用哪个对象,我们称之为“正向控制”。而“控制反转”则是将对象的控制权交给第三方的“对象容器”,由“对象容器”在运行时创建对应的对象,再赋值给对应的变量。
IOC–最大的优点就是,让 对象 和 对象之间的引用 实现了有效的解耦。因为是在运行时完成的,所以当我们系统底层的类发生变化的时候,只需要修改配置文件就可以了。(极大的方便了工程维护和代码管理)
这里的“对象容器”(applicationContext)我们通常称之为,“IOC”容器。
DI–依赖注入,是IOC控制翻转理念的具体技术实现,由对象容器在运行时动态注入对象。
DI-依赖注入是基于两种技术来实现的。
1,反射–在运行时,进行动态的创建、设置以及管理。
2,工厂模式
(java反射和工厂模式。。是什么鬼东西啊????)
Java反射机制–在运行状态下,对于任意一个类都,能知道他的属性和方法;对于任意一个对象都能调用它的任意一个属性和方法。这种动态获取的信息以及动态调用方法的功能称为Java的反射机制。
1-2 Spring实例化对象的三种形式
Spring 中Bean 实例化有几种方式呢?(3种)
1,使用类构造器实例化。(People people = new People(张三,26))
(第一种是最常用,最根本的)
2,使用静态工厂方法实例化
3,使用实例工厂实方法例化
(静态工厂和实例工厂类都是间接通过构造器实现的实例化)
三种实例化方式,分别如何配合呢?
实例;
1,构造器实例化
配置applicationContext.xml
执行代码和结果
2、静态工厂实例化
在配置文件找那个进行配置
运行代码和结果
3、实例工厂实例化
配置文件代码:
执行代码和结果
1-3 Spring四种注入方式
Spring Bean注入属性有哪几种方式呢?(Spring面试必问)
4种
1、setter注入;
2、构造器注入
3、注解注入
4、java Config注入
service()类用于处理业务逻辑,如果涉及到底层数据的增删改查,需要引用“UserDao”。在Spring的架构下,需要动态的将“UserDao”动态的注入“UserService”对象中
示例:
1、使用setter方法运行时注入:(使用频率最高)
2、通过构造函数动态注入userDao对象(注入:将IOC容器中生成的“userDao”对象,注入都程序中的“userDao”对象中)
调用构造器注入的配置代码(很少使用)
执行代码和结果:
3、使用注解注入
注解时JDK1.5以后的新特性,帮程序员简化配置过程。(如果采用配置文件方式配置,当需要配置的javaBean特别多时,工作量会巨大)
对需要使用注解的包,进行扫描配置
添加注解:
这样,当IOC初始化时(也就是Spring启动时),会将这两个添加注解的类进行实例话,并赋予响应的 bean id 。
注入:(@Resource --表示优先按照 bean id 加载对象)
执行结果:
4、使用java config 进行注入
java Config 注入是在Spring 4 以后,新推出的一种对象创建与注入的方式。它摒弃了以前的xml文件配置的方式,采用“注解”+“Java代码”方式,管理对象关系
IOC容器在初始化时,会执行“userDao()”方法,并将方法产生的对象命名为“userDAO”放入到IOC容器中。此过程完全是使用java代码完成。
将userService 和 userDao进行关联
执行结果:
相对于注解注入的优势:
1、不破坏原始代码,(不在原始代码中添加任何东西)
2、解决了 xml文件配置,编译器无法及时检查的问题。
1-4 Spring常见面试问题
默认情况下,使用IOC容器实例化,去创建多个对象时,这多个对象是同一个对象吗?
对IOC容器来说,默认情况下如果不做额外的设置,创建的多个userService对象是同一个对象
在Scope.xml配置文件中,配置了对应的“bean”以后,其会在IOC初始化时实例化,其“全局唯一”
设置Scope 属性:
默认情况下,scope=“singleton”–表示单例
如果将其设置为:scope=“prototype” 多例模式,对同一个对象多次实例化时,会创建不同的对象
另外,scope还有两个值需要了解一下,(不太常用)
1、request–请求
2、session–会话
如果在当前工程中,引入SpringMVC,这两个属性就是生效了,含义是:
1-request,如果在同一个“request”请求内,对象是同一个;不同的请求,IOC容器会创建不同的对象
2-session,同一个session内部,多次调用getBean()获取的是同一个对象;不同的session IOC会创建不同的对象。
Scope 属性决定了,我们在Spring工程中创建对象时单例还是多例。
lazy-init -->表示延迟初始化(懒加载)
lazy-init 会把对象实例化的过程,放在getBean()方法执行时。
1、设置为“true”–表示只有用到这个javaBean时,才会实例化。
2、设置为“false”时,表示不进行延迟初始化(不设置此属性的话,默认为“false”)
在 IOC 初始化时就创建对象
注意:当scope属性为“prototype”多例模式时,lazy-init就会失效
多例模式下,本身就是没调用一次getBean才进行实例化,效果同lazy-init的相关设置冲突了。
lazy-init 有自己的使用场景,因为其作用是,对象在第一次getBean()是被创建,所以可以起到减小服务器压力的作用。
(比如:当前有上千个类,但并不是所有的类都是目前需要的,有些是作为备用选项使用的。此时我们就可以使用lazy-init 来减轻服务器和内存的压力,有利于系统的快速启动)
Spring中有两个注解用于对象的注入:
1,@Autowired–Spring提供的注入注解,也就是由第三方提供的。
2,@Resource–>java 官方进行的定义(建议优先使用官方)
二者区别:
1,@Autowired–Spring提供的注入注解,也就是由第三方提供的。@Resource–>java 官方进行的定义(建议优先使用官方)
2,二者的机制不同,“@Autowired”只能按照类型在IOC容器中进行匹配。。而“@Rresource”可以通过设置“name”属性,指定Bean id,也就是可以按照“name”进行匹配。
当“@Resource”不设置“name”属性时,会将“属性名”作为默认的“Bean id”去IOC同期中查找,当有时属性名和IOC容器中的“bean id”不一样。这种情况下才会跟“@Autowired”一样采用类型进行匹配。其更加智能。(如果设置了“name”属性,则将设置的名称作为“bean id”进行精准匹配。如果没有设置“name”属性,优先使用属性名作为“bean id”到IOC容器中进行查找&#x