熟悉与考点
面试问题:
- IOC、Bean、DI概念
- IOC好处,与传统编程相比优势?
- ID和IOC理解使用?
- IOC和ID的实现原理?
- Bean对象的作用域
- Bean对象的生命周期
Spring是什么?
Spring是一个开发框架,其中包含了对web,SE,JDBC等开发的各种便捷使用框架,这里我们第一课学习Spring Framework。
Spring Framework是一个开源的轻量级的 Java 开发框架, 具有控制反转(IoC)和面向切面(AOP)两大核心。Java Spring 框架通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
Spring编程作用与优势
在传统编程中,第一,当一个方法需要创建对象使用时,并没有使用引用指向它,就会被回收,解决办法是使用静态方法,但静态方法可能不能满足所有的应用场景,调用静态方法时,其中有些属性不同,会导致该方法不能使用。
第二,当方法再次使用时,未使用引用的这个对象就会再次创建,使用多次,创建多次,当新生代空间不足后,会被放入老年代,这时full GC回收,这对回收机制来说是十分庞大的工程,如果过多,此时就需要暂停用户线程来回收,效率十分低下。
总结缺陷就是:
(1)很多资源类的对象在方法中new对象(例如懒汉模式):进入方法创建对象,退出方法,对象就不可达,需要回收。
缺点:1. 不停创建很快回收的对象,增加垃圾回收的负担,用户线程会暂停。2. 资源类对象创建如果比较耗时,整个程序性能下降很快。
(2)资源类对象互相有依赖关系时,例如:
public class A{
private B b;
}
public class B{
private C c;
}
缺陷:1. 每个方法创建资源对象时,需要手动绑定。2. 耦合性太大,如果需要调整某个属性类的具体实现,每个涉及部分都需要修改。
IOC是什么?
IOC : 控制反转 Inversion of Control
实例的创建不再由调用者管理,而是由 Spring 容器创建。Spring 容器会负责控制程序之间的关系,而不是由程序代码直接控制,因此,控制权由程序代码转移到了 Spring 容器中,控制权发生了反转。
DI是什么
依赖注入(Dependency Injection,DI)和控制反转含义相同,它们是从两个角度描述的同一个概念。
Spring 容器在创建被调用者的实例时,会自动将调用者需要的对象实例注入给调用者,这样,调用者通过 Spring 容器获得被调用者实例,这称为依赖注入。
依赖注入主要有两种实现方式,分别是属性 setter 注入和构造方法注入。
Bean对象
Bean是Spring IOC容器中的对象实例。
Spring 容器可以被看作一个大工厂,而 Spring 容器中的 Bean 就相当于该工厂的产品。如果希望这个大工厂能够生产和管理 Bean,这时则需要告诉容器需要哪些 Bean,以及需要以何种方式将这些 Bean 装配到一起。
Spring 配置文件支持两种不同的格式,分别是 XML 文件格式和 Properties 文件格式。
通常情况下,Spring 会以 XML 文件格式作为 Spring 的配置文件,这种配置方式通过 XML 文件注册并管理 Bean 之间的依赖关系。
Bean对象的作用域
Spring 容器在初始化一个 Bean 的实例时,同时会指定该实例的作用域。Spring3 为 Bean 定义了五种作用域,具体如下。
1)singleton
单例模式,使用 singleton 定义的 Bean 在 Spring 容器中只有一个实例,这也是 Bean 默认的作用域。
2)prototype
原型模式,每次通过 Spring 容器获取 prototype 定义的 Bean 时,容器都将创建一个新的 Bean 实例。
3)request
在一次 HTTP 请求中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Request 内有效。
4)session
在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Session 内有效。
5)global Session
在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例。该作用域仅在使用 portlet context 时有效。
主要使用:
singleton 作用域
prototype 作用域
singleton 作用域下对象是单例的,每次创建使用是同一个对象。
prototype 作用域下对象是新建的,每次使用都会创建一个新的对象。
使用时直接在Bean表单中写 scope=“prototype”
Bean对象的生命周期
传统编程,在方法中开始创建到方法调用完毕是一个对象正常的生命周期,并没有明确规定它的生命周期。
Spring 容器可以管理 singleton 作用域 Bean 的生命周期,在此作用域下,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成,以及何时被销毁。
对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。每次客户端请求 prototype 作用域的 Bean 时,Spring 容器都会创建一个新的实例,并且不会管那些被配置成 prototype 作用域的 Bean 的生命周期。
Bean 生命周期的整个执行过程描述如下。
1)根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean。
2)利用依赖注入完成 Bean 中所有属性值的配置注入。
3)如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。
4)如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用。
5)如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用。
6)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzation() 对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。
7)如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法。
8)如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。
9)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization()。此时,Bean 已经可以被应用系统使用了。
10)如果在 中指定了该 Bean 的作用范围为 scope=“singleton”,则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 中指定了该 Bean 的作用范围为 scope=“prototype”,则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。
11)如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁;如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁。