前言
IOC:控制反转,是一种理论,概念,思想。把对象的创建,赋值,管理工作交给代码之外的容器实现,也就是对象的创建是由其他的外部资源完成。
控制反转
-
控制:创建对象,对象的属性赋值,对象之间的关系管理。
-
反转:把原来的开发人员管理,创建对象的权限转移给代码之外的容器实现。由容器代替开发人员管理对象,创建对象。
-
正转:由开发人员在代码中实现,使用new构造方法创建对象,开发人员主动管理对象。
-
容器:一个服务器软件,一个框架(spring)
Spring 容器是 Spring 框架的核心。容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁。Spring 容器使用依赖注入(DI)来管理组成一个应用程序的组件,这些对象被称为 Spring Beans。
通过阅读配置元数据提供的指令,容器知道对哪些对象进行实例化,配置和组装。配置元数据可以通过 XML,Java 注释或 Java 代码来表示。 Spring IoC 容器利用 Java 的 POJO 类和配置元数据来生成完全配置和可执行的系统或应用程序。
IOC 容器具有依赖注入功能的容器,它可以创建对象,IOC 容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。通常new一个实例,控制权由程序员控制,而"控制反转"是指new实例工作不由程序员来做而是交给Spring容器来做。在Spring中BeanFactory是IOC容器的实际代表者。
-
Java中创建对象的方式:
-
构造方法
-
反射
-
克隆
-
序列化
-
ioc创建对象
-
动态代理
使用IoC的目的:减少对代码的改动,也能实现不同功能。实现解耦合。
IoC容器:
IOC的技术实现 :
-
DI 是ioc的技术实现。
-
DI(Dependency Injection):依赖注入, 只需要在程序中提供要使用的对象名称就可以, 至于对象如何在容器中创建,赋值,查找都由容器内部实现。
-
spring是使用的di实现了ioc的功能, spring底层创建对象,使用的是反射机制。
-
spring是一个容器,管理对象,给属性赋值, 底层是反射创建对象。
-
spring-conetxt 和 spring-webmvc 是spring中的两个模块
-
spring-context:是ioc功能的,创建对象的。
-
spring-webmvc做web开发使用的, 是servlet的升级。
-
spring-webmvc中也会用到spring-context中创建对象的功能的。
Spring的第一个程序:
第一步:创建一个Maven工程
导入Spring和junit依赖到pom.xml中:
<!--junit单元测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--Spring依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.9</version>
</dependency>
第二步:创建一个接口
创建一个接口类,在通常业务中,我们通常使用接口来声明方法,通过接口实现类来完成方法,业务逻辑的具体实现!
package org.example;
public interface SomeService {
void doSome();
}
第三步:创建接口实现类
实现接口中声明的方法:
package org.example.imp;
import org.example.SomeService;
public class SomeServiceImpl implements SomeService {
//空参构造器:spring默认调用:
public SomeServiceImpl() {
System.out.println("spring调用了SomeServiceImpl的空参构造器!");
}
@Override
public void doSome() {
System.out.println("执行了SomeServiceImp的doSome方法!");
}
}
第四步:在resource资源文件目录下创建application.xml文件
把创建好的实现类交给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">
<!-- 约束文件路径——xml文件-->
<!--
告诉spring创建对象
声明bean,就是告诉spring要创建某个类的对象
id:对象的自定义名称,唯一值。spring通过这个名称找到对象
class:类的全限定名称(不能是接口,因为spring是反射机制创建对象,必须使用类)
-->
<bean id="someService" class="org.example.imp.SomeServiceImpl" />
<bean id="someService1" class="org.example.imp.SomeServiceImpl" />
<!-- spring底层完成:SomeService someService = new SomeServiceImp();
spring把创建好的对象放入map中,spring框架有一个map存放对象
springMap.put(id值,对象);
一个bean标签声明一个Java对象。
-->
<!--
spring能创建一个非自定义类的对象,创建一个存在的某个类的对象。
-->
<bean id="mydate" class="java.util.Date"/>
</beans>
<!--
spring的配置文件
1.beans:根标签,spring把Java对象称为bean
2.spring-beans.xsd 是约束文件,和mybatis指定 dtd 类似
-->
第五步:创建测试类
package org.example;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Date;
public class MyTest {
/*
spring默认创建对象的时间:在创建spring的容器时,会创建配置文件中所有的对象。
spring创建对象:默认调用的是无参构造方法
*/
@Test
public void test01(){
//使用spring容器创建对象:
//1.指定spring配置文件名称
String config = "application.xml";
//2.创建表示spring容器的对象,ApplicationContext
//ApplicationContext就是表示spring容器,通过容器对象获取对象
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
//从容其中获取某个对象,调用对象方法
//getBean("配置文件中bean的id值")
SomeService service = (SomeService) ac.getBean("someService");
//使用spring创建好的对象,调用方法:
service.doSome();
}
/**
* 获取spring容器中Java对象信息
*/
@Test
public void test02(){
String config = "application.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
//使用spring提供的方法,获取容器中定义的对象数量
int num = ac.getBeanDefinitionCount();
System.out.println("容器中所含对象数量:" + num);
//容器中每个定义对象的名称
String[] names = ac.getBeanDefinitionNames();
//增强for循环:
for (String name : names){
System.out.println(name);
}
}
/**
* 获取一个非自定义类的对象
*/
@Test
public void test03(){
String config = "application.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
//使用getBean();获取对象
Date md = (Date) ac.getBean("mydate");
System.out.println("系统时间:" + md);
}
}
基于XML文件的DI依赖注入:
Spring框架的核心功能之一就是通过依赖注入的方式来管理Bean之间的依赖关系。在spring的XML配置文件中,给java对象的属性赋值。DI注入:创建对象,给属性赋值。
setter设值注入:
当容器调用一个无参的构造函数或一个无参的静态 factory 方法来初始化你的 bean 后,通过容器在你的 bean 上调用设值函数,基于设值函数的 DI 就完成了。
第一步:创建一个实体类
package org.example.ba01;
public class Student {
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
第二步:在resource目录下编写application.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">
<!--声明student对象-->
<!--
注入:赋值
di:给属性赋值
简单类型:spring规定在Java的基本数据类型和String都是简单类型。
1.set注入(设置注入):spring调用类的set方法,你可以在set方法中完成属性赋值
1)简单类型注入
<bean id="XXX" class="YYY">
<property name="属性名字" value="此属性的值" />
一个property只能给一个属性赋值
<property ... >
</bean>
2) 引用类型的注入:spring调用类的set方法
<bean id="XXX" class="YYY">
<property name="属性名称" ref="bean的id(对象名称)"/>
</bean>
-->
<bean id="mystudent" class="org.example.ba01.Student">
<property name="name" value="TOM"/>
<property name="age" va