2、IoC控制反转(四声)
学习资源:动力节点的2020最新Spring框架教程【IDEA版】-Spring框架从入门到精通
1、什么是 IoC控制反转
控制反转(IoC, Inversion of Control),是一个概念,是一种思想。指将传统上由程序代码直接操控的对象调用权交给容器,通过容器来实现对象的装配和管理。控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器。 通过容器实现对象的创建,属性赋值,依赖的管理。
当前比较流行的实现 IoC 的方式是依赖注入。
依赖: classA 类中含有 classB 的实例,在 classA 中调用 classB 的方法完成功能,即 class A 对 class B 有依赖。
依赖注入:DI(Dependency Injection),程序代码不做定位查询,这些工作由容器自行完成。
依赖注入 DI 是指程序运行过程中,若需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部容器,由外部容器创建后传递给程序。Spring 的依赖注入对调用者与被调用者几乎没有任何要求,完全支持对象之间依赖关系的管理。
Spring 框架使用依赖注入(DI)实现 IoC。
Spring 容器是一个超级大工厂,负责创建、管理所有的 Java 对象,这些 Java 对象被称为 Bean。 Spring 容器管理着容器中 Bean 之间的依赖关系, Spring 使用 DI 的方式来管理 Bean 之间的依赖关系,进而实现对象之间的解耦和。
2、DI 入门实例
2.1、创建 Maven 项目
2.2、引入 Maven 依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
2.3、定义接口与实体类
public interface SomeService {
void doSome();
}
// 无属性的实体类
public class SomeServiceImpl implements SomeService {
public SomeServiceImpl() {
super();
System.out.println("SomeServiceImpl无参数构造方法");
}
@Override
public void doSome() {
System.out.println("====业务方法doSome()===");
}
}
2.4、创建 Spring 配置文件
在 src/main/resources/ 目录下创建一个 xml 文件,applicationContext.xml
文件初始内容:
- <\beans> 是 Spring 配置文件的根标签
- spring-beans.xsd 是约束文件
<?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">
</beans>
2.5、注册 bean对象
<\bean> 标签用于在 Spring 容器中声明注册一个实体类的对象。
标签属性:
- id:该属性是 Bean 实例的唯一标识,自定义名称,程序通过 id 属性访问 Bean, Bean 与 Bean 间的依赖关系也是通过 id 属性关联的。
- class:指定该 Bean 所属的类,使用类的全限定名称。
注意:Spring 底层是由反射机制创建对象,所以必须使用实体类,不能是接口。
<?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="someService" class="com.bjpoewernode.service.impl.SomeServiceImpl" />
<!-- 其他Bean -->
<bean id="xxx" class="xxx.xxx.xxx" />
......
</beans>
Spring 完成 SomeService someService = new SomeServiceImpl();
的创建,并创建好的对象放入到一个框架内部的 map 中,springMap.put(beanId, 实例对象);
,例如:springMap.put("someService", newSomeServiceImpl());
。
2.6、测试
2.6.1、获取 Spring 容器中的对象
- 指定 Spring 配置文件的位置和名称,applicationContext.xml 通常都放置在 resources 目录下
- 创建 Spring 容器的对象,
ApplicationContext
对象,
(qaq,怎么还是需要 new 啊😅)
- 根据 id 从容器中"拿"对象
getBean
,类型强转,就可以使用该对象了
@Test
public void test01{
String resource="applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
SomeService ss = (SomeService) ac.getBean("someService");
ss.doSome();
}
2.6.2、获取容器中对象的数量 & 名称(bean id)
@Test
public void test02{
String resource="applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
int count = ac.getBeanDefinitionCount();
sout("容器中注册的对象数量:"+nums);
String[] names = ac.getBeanDefinitionNames();
for(String name : names){
sout(name);
}
}
2.7、容器创建非自定义类的对象
测试的 Java 类: java.util.Date
在 Spring 配置文件声明注册 java.util.Date
:
<bean id="utilDate" class"java.util.Date" />
测试:
@Test
public void test03{
String resource="applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
Date myDate = ac.getBean("utilDate");
}
3、容器的接口和实现类
applicationContext 容器
ApplicationContext 用于加载 Spring 的配置文件,在程序中充当“容器”的角色,其实现类有两个:
开发中一般使用 ClassPathXmlApplicationContext
的实例对象,它表示从类路径加载 Spring 的配置文件;而 FileSystemXmlApplicationContext
表示从磁盘中加载。
ApplicationContext 容器中对象的装配时机
前提是,bean 的属性是 singleton。
Spring 默认创建对象的时间:在创建 ApplicationContext 容器时,就会创建配置文件中的所有的对象,一次性全部装配好,默认调用类的无参构造器进行对象的创建。以后代码中若要使用到这些对象,只需从内存中直接获取即可,执行效率较高。