Spring-IOC(Inversion Of Contral) :控制反转
概念:实例的创建不需要我们自己来设置,通过 Spring 来帮助我们管理,它主要负责控制对象之间的关系以及它们的生命周期,以前的程序控制是通过程序员写代码来实现,现在通过代码来控制代码,程序的控制权由程序员转变为 Spring ,也就是控制发生了反转
举个例子:好比如说 Spring 是一家婚介所,它的主要工作就是帮助前来的单身男性和女性按照他们的要求进行配对谈恋爱,以前如果男生要追一个女生,就自己想方设法的去要人家电话,去认识人家,而现在男方和女方都来到婚介所,先把自身的情况告诉婚介所,自己多高多重工资多少,然后告诉婚介所自己想要找生命类型的对象,有什么学历工资要求等,婚介所就根据他们各自的要求进行匹配
Spring 就是这样类似于婚介所一般,而前来的男女青年就是其中的资源对象,这些资源对象在Spring中都是可以互相调用,共享资源,既然想要获取到其他对象的资源,那么自己的资源也要能让其他对象获取到
Spring 提供了两种 IoC 容器,分别为 BeanFactory 和 ApplicationContext,
Bean 容器:
BeanFactory 最基础的 ioc 容器
功能:主要负责初始化各种 Bean ,并且调用它们的生命周期方法,里面详细的配置信息通过 xml 文件管理
BeanFactory beanFactory = new XmlBeanFactory
(new FileSystemResource("D://applicationContext.xml"));
该实现类是通过参数配置指定的 xml 文件路径
例如:
BeanFactory beanFactory = new XmlBeanFactory
(new FileSystemResource("E:\\idea\\Spring-study\\src\\main\\resources\\applications.xml"));
ApplicationContext:称为上下文
是BeanFactory的子接口,不仅实现了Bean里面的所有功能,还添加了对 i18n(国际化)、资源访问、事件传播等
两种常用的实现类:
(1)ClassPathXmlApplicationContext
从类路劲 ClassPath 中寻找指定的 xml 文件,并完成 ApplicationContext 实例化工作,例如以下图片:
就可以在 classes 路径里面找到 applications.xml 文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext
(String configLocation)(String configLocation);
(2)FileSystemXmlApplicationContext
类似于 BeanFactory 的读取 xml 做法,从给定参数中获取 xml 文件
例如:
ApplicationContext context = new
FileSystemXmlApplicationContext("E:\\\\idea\\\\Spring-study\\\\src\\\\main\\\\resources\\\\applications.xml");
可以实例化 xml 文件中的任何一个类作为 Spring 的 AppliccationContext 容器,通常在 Java 项目中,会采用通过 ClassPathXmlApplicationContext 类实例化 ApplicationContext 容器的方式
DI(Dependency Injection) :依赖注入
概念:由 Spring 容器来将资源对象(也就是依赖)注入到其他需要它的对象里面,被注入的对象就是注入对象所需要的依赖
就好比如婚介所的例子里讲的:男女青年将自己的条件以及想要找的对象要求发送给婚介所,那么此时整个婚介所的资源对象都是共享的,也就是这些男女青年的信息都是可以在婚介所里面使用的,那么男方想要一个漂亮又年轻的小姑娘,这个小姑娘就是男方的依赖,婚介所就是来帮助他把这样的小姑娘介绍给男方,至于怎么找到的小姑娘,男方就不用管了
对象依赖/属性的设置:
(1)setter 注入:
指 IoC 容器使用 setter 方法注入被依赖的实例,通过调用无参构造器或无参 static 工厂方法实例化 bean 后,调用该 bean 的 setter 方法,即可实现基于 setter 的 DI
(2)构造方法注入:
指 IoC 容器使用构造方法注入被依赖的实例,基于构造器的 DI 通过调用带参数的构造方法实现,每个参数代表一个依赖
Bean 作用域
Spring 初始化一个 Bean 的实例时,同时会指定该实例的作用域
改变作用域:scope
1.singleton
单例模式,使用 singleton 定义的 Bean 作用域,那么每次会从 Spring 中创建一个共享的 Bean 实例(也就是某一个类的实例化对象),对于所有的创建 Bean 实例请求,如果他们的 id 和 Bean 定义匹配,就会返回同一个 Bean 实例,这也是 Bean 的默认作用域
2.prototype
该方式定义的 Bean 作用,每次都会从 Spring 中创建一个新的 Bean 实例
3.request
在同一次 http 请求中,只会从 Spring 中创建一个 Bean 实例,可以重复使用,而在不同的 http 请求中,会创建多个 Bean 实例,也就是说 Bean 的作用域只在当前 http 请求中有效
4.session
和request一样,该 Bean 作用域只在当前 http 请求中有效
Bean 生命周期
Bean 生命周期的整个执行过程描述如下
1)根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean。
2)利用依赖注入完成 Bean 中所有属性值的配置注入。
3)如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。
4)如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前BeanFactory实例的引用。
只会进行一步
5)如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用。
6)如果 Bean 实现了 BeanPostProcessor 接口,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzation() 对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。
7)如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法。
8)如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。
9)如果 Bean 实现了 BeanPostProcessor 接口,则 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 进行销毁。
BeanFactory 和 ApplicationContext的区别:
(1)相同点:都是通过加载 xml 文件来加载 Bean 容器
(2)不同点:BeanFactory 在启动的时候不会调用所有的 Bean 容器,只有在调用到 Bean 容器的时候,才会在 Spring 中去实例化类对象,而 ApplicationContext 不一样,它在一启动的时候就把所有的 Bean 容器实例化
Spring使用的优点
(1)对象和对象之间的依赖关系以及他们的生命周期都交由 Spring 来帮助我们管理配置,我们只需要负责使用就好
(2)不会出现类于类之间属性依赖调用的时候遗漏的情况,提前在 xml 资源配置文件中设置好,这样后序的代码调整和优化也更加方便
(3)方便进行功能测试