1.举例说明问题
1.1 例子1
以往我们需要一个对象的时候,我们通常都是自己去new一个。例如
我有个Person类,我需要一个对象时,我直接new一个对象然后去使用。
示例代码:
Person p = new Person();
p.setName("张三");
p.hello();
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void hello(){
System.out.println("hello:"+name);
}
结果打印:hello:张三
现在我们有了spring框架,当我再需要一个对象时,不用我们直接去new,而是向外部容器申请一个,直接拿来使用。
1.2 例子2
再举个例子,(习惯性的举例子)
现在我们需要一个房子,通常我们不会是自己画图纸、建房子、装修最后入驻,这个过程是非常复杂的,我们必须自己设计和面对每一个环节。
通常我们是找一个中介,中介给我们介绍房子,中介就会按照我们的要求给我们提供房子,
我们直接拎包入住(直接使用。)就行。简单明了,如果房子我们不符合我们的要求,我们就抛出异常。整个过程不再是我们自己控制,而是由中介来控制。
也就是说我们不负责对象本身的创建与维护,(对象由外部容器来创建)我们直接使用。
Spring开发方式就是这样: 所有的类都会在spring容器中登记,告诉spring你是什么东东,你需要什么东东,然后spring会在系统运行适当的时候,把你要的东西主动给你,同时也把你交给需要你的东东。 所有类的创建、维护、销毁都是由spring来控制。
我们结合找房子的例子与IOC容器对象起来。
我们想买房子,我们直接去找中介,中介给我们介绍房子,然后我们直接入住。
对于IOC,当我们想使用对象时,我们直接找IOC容器,容器给我们返回对象,我们直接使用对象。
那么我们一直在说spring的IOC 容器,ioc容器 管理并创建对象,在使用过程中,是从容器中拿出对象直接使用。
2. IOC是什么
总结一下:
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,
结合我们上述举的例子,可以得到如下答案:
- 谁控制谁:在传统的开发模式下,我们都是采用直接 new 一个对象的方式来创建对象,也就是说你依赖的对象直接由你自己控制,但是有了 IOC 容器后,则直接由 IoC 容器来控制。所以“谁控制谁”,当然是 IoC 容器控制对象。
- 控制什么:控制对象。
- 为何是反转:没有 IoC 的时候我们都是在自己对象中主动去创建被依赖的对象,这是正转。但是有了 IoC 后,所依赖的对象直接由 IoC 容器创建后注入到被注入的对象中,依赖的对象由原来的主动获取变成被动接受,所以是反转。
- 哪些方面反转了:所依赖对象的获取被反转了。
3.DI是什么
Dependency Injection “依赖注入”:是组件之间依赖关系由容器在运行期决定的。
依赖注入DI其实是IOC的实现方式,IOC容器在初始化的时候,会创建一系列对象,同时能够把这些对象之间的依赖关系通过注入的方式组织起来。
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:
● 谁依赖于谁:当然是应用程序依赖于IoC容器;
● 为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
● 谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
● 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。
扩展理解:
4.IOC容器中Bean的配置
spring IOC管理的对象都称为bean,
Bean的配置形式有两种,基于XML文件的方式;基于注解的方式。
本文是以XML文件的方式进行说明。
新建一个spring的applicationContext.xml配置文件,配置内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="person" class="com.diligentkong.bean.hello.Person">
<property name="name" value="张三"></property>
</bean>
</beans>
获取方式:
public static void main(String[] args) {
/*原始方式
// 创建 Person 的一个对象
Person p = new Person();
// 为name赋值
p.setName("张三");
// 调用hello方法
p.hello();
*/
//Spring的方式的调用
//创建spring的IOC容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
// 从IOC容器中获取Bean 实例
Person per = (Person) ac.getBean("person");
// 调用hello方法
per.hello();
}
先看配置文件
在xml文件中通过bean节点来配置bean,
<bean id="person" class="com.diligentkong.bean.hello.Person">
<property name="name" value="张三"></property>
</bean>
id:标识容器中的bean ,id唯一。
若 id 没有指定,Spring 自动将权限定性类名作为 Bean 的名字
id 可以指定多个名字,名字之间可用逗号、分号、或空格分隔
class: bean的全类名,通过反射的方式在IOC容器中创建bean,所以要求Bean中必须有无参的构造器
我们先看获取xml的这一步,
//创建spring的IOC容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
在Person中写一个无参构造函数,set方法中打印输出
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
// 新添加的
System.out.println("setName:" +name);
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void hello(){
System.out.println("hello:"+name);
}
//新添加的
public Person() {
System.out.println("Person Constructor...");
}
}
Test方法中
//创建spring的IOC容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
// 从IOC容器中获取Bean 实例
// Person per = (Person) ac.getBean("person");
// 调用hello方法
// per.hello();
输出的内容:
也就是说 spring创建IOC容器的时候,会调用构造器,并调用set方法为属性赋值
在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用.
借鉴的博客:https://www.cnblogs.com/xdp-gacl/p/4249939.html