目录
- 什么是Spring
- Spring框架两大核心机制(IoC和AOP)
- 如何使用IoC
- scope作用域
- Spring的继承
- Spring的依赖
- Spring的p命名空间
- Spring的工厂方法
- IoC自动装载(Autowire)
什么是Spring
- Spring是企业级开发框架,是软件设计层面的框架,优势在于可以将应用程序分层,开发者可以自助选择组件
- Spring已经成为Java领域行业标准
- Spring提供了各个层面的解决方案:
MVC:struts2、Spring MVC
ORMapping:Hibernate、MyBatis、Spring Date - Spring两大核心机制:IoC(控制反转)和AOP(面向切面)
Spring框架两大核心机制(IoC和AOP)
- Ioc(控制反转)/DI(依赖注入)
- AOP(面向切面编程)
什么是IoC(控制反转)
传统程序开发中,需要调用对象时,通常由调用者来创建被调用者的实例,即对象是由嗲用着主动new出来的
但在Spring框架中,创建对象的工作不再是由调用者来完成,而是交给IoC容器创建,再推送给调用者,整个流程完成反转,所以说控制反转
如何使用IoC
新建一个maven工程
在pom.xml中添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>aispringioc</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.11.RELEASE</version>
</dependency>
</dependencies>
</project>
创建实体类
此时可以在xml文件中添加lombok依赖,这样实体类可以不用写get/set方法
实体类中添加此注解
传统开发方式是手动new对象,并且对其进行操作
通过IoC创建对象,在配置文件中添加需要管理的对象,XML格式的配置文件,文件名可以自定义
新建xml文件于resources目录下
其会自动生成这些配置信息
给对象写如下内容,id就是类的别名,class关联的是创建对象所对应的类地址
<bean id="student" class="com.makerjack.entity.Student">
<property name="id" value="1"></property>
<property name="name" value="张三"></property>
<property name="age" value="22"></property>
</bean>
这也称为属性注入
然后在测试中如下获取对象信息
配置文件
通过配置bean标签来完成对象的管理
- id:对象名
- class:对象的模板类。(所有交给IoC容器来管理的类,必须有无参构造函数,因为Spring底层通过反射机制来创建对象,调用的是无参构造)
对象的成员变量通过property标签完成赋值
- name:成员变量名
- value:成员变量值(基本数据类型,String可以直接赋值,如果是其它引用类型,不能通过value赋值)
- ref:将IoC的另一个bean赋给当前的成员变量(DI)
例如给Student对象加一个对象成员变量score
通过有参构造创建bean
以上是通过无参构造来创建对象,其本质是先创建后赋值
以下为通过有参构造函数创建对象,本质是一边创建一边赋值
-
在实体类中创建对应有参构造
在对象前加这个注解即可 -
配置文件中写入相关信息
<bean id="student1" class="com.makerjack.entity.Student">
<constructor-arg name="id" value="2"></constructor-arg>
<constructor-arg name="name" value="李四"></constructor-arg>
<constructor-arg name="age" value="25"></constructor-arg>
<constructor-arg name="score" ref="score"></constructor-arg>
</bean>
其中的name可以省略,其就是按照先后顺序赋值
当省略时,确保传递值的顺序不能错
name也可以换成index,其取值就是0~传递值的个数-1
<bean id="student1" class="com.makerjack.entity.Student">
<constructor-arg index="0" value="2"></constructor-arg>
<constructor-arg index="1" value="李四"></constructor-arg>
<constructor-arg index="2" value="25"></constructor-arg>
<constructor-arg index="3" ref="score"></constructor-arg>
</bean>
结果
给bean注入集合
如果有对象的属性为集合性质,需要存储多个同种数据
那么此处就不能直接引用对象
需要些成如下形式
<property name="scores">
<list>
<ref bean="score-1"></ref>
<ref bean="score-2"></ref>
</list>
</property>
效果如下
scope作用域
Spring管理的bean是根据scope来生成的,表示bean的作用域,共4种,默认是单例模式
- singleton:单例,表示通过IoC容器获取的bean是唯一的
- prototype:原型,表示通过IoC容器获取的bean是不同的
- request:请求,表示在一次HTTP请求内有效
- session:会话,表示在一个用户会话内有效
request和session只适用于Web项目,大多数情况下,使用单例和原型比较多。
在这里插入图片描述
测试比如我们在无参构造函数中进行截断观察
可以观察到
prototype模式当业务代码获取IoC容器中的bean时,Spring才去调用无参构造创建对应的bean每次获取都会重新调用(创建一个新的)
可以看到
signleton模式物理业务代码是否获取IoC容器中的bean,Spring在加载sprig.xml时就会创建对象而且每次调用不会创建新的
Spring的继承
与java的继承不同,java是类层面的继承,子类可以继承父类的内部结构信息,Spring是对象层面的继承,子对象可以继承父对象的属性值
比如stu想继承student的所有属性值
只需要在后面添加属性“parent”即可
<bean id="stu" class="com.makerjack.entity.Student" parent="student"></bean>
效果就是可以完全继承其全部属性
若想要覆盖某些属性,直接在内部重写属性即可
<property name="name" value="李四"></property>
效果如下
即便是不同的对象,如果属性/成员变量一样或 子类属性完全包含父类属性也是可以继承的(继承属性的数值)
Spring的依赖
与继承类似,依赖也是描述bean和bean之间的一种关系,配置依赖之后,被依赖的bean一定先创建,再创建依赖的bean:A依赖于B,则先创建B,后创建A
Spring的p命名空间
p命名空间是对IoC / DI的简化操作,使用p命名空间可以更方便地完成bean的配置以及bean之间的依赖注入
需要在xml文件中添加标签库
xmlns:p="http://www.springframework.org/schema/p"
在xml中直接在对象内部追加p,即可完成属性赋值,本质是对对象配置的简化
<bean id="student" class="com.makerjack.entity.Student" p:id="1" p:name="盖亚" p:age="23" p:scores-ref="score"></bean>
<bean id="score" class="com.makerjack.entity.Score" p:english="87" p:math="79"></bean>
Spring的工厂方法
IoC通过工厂模式创建bean的方式有两种
- 静态工厂方法
- 实例工厂方法
静态工厂方法
不需要实例化工厂,程序启动就会加载到内存当中,只要关注bean即可
首先建立实体类
package com.makerjack.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Car {
private String brand;
private long id;
private String color;
private double price;
private Date date;
}
然后创建静态工厂方法
package com.makerjack.factory;
import com.makerjack.entity.Car;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class StaticCarFactory {
private static Map<Long, Car> carMap;
static {
carMap = new HashMap<Long, Car>();
carMap.put(1L,new Car("benz",1L,"red",17.3,new Date()));
carMap.put(2L,new Car("beck",2L,"white",11.7,new Date()));
}
public static Car getCar(long id){
return carMap.get(id);
}
}
再编写配置文件
<!-- 配置静态工厂创建car -->
<bean id="car" class="com.makerjack.factory.StaticCarFactory" factory-method="getCar">
<constructor-arg value="2"/>
</bean>
测试
实例工厂方法
实例对象依旧如上,实例工厂换成实际的对象,以便后续创建
package com.makerjack.factory;
import com.makerjack.entity.Car;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class InstanceCarFactory {
private Map<Long, Car> carMap;
public InstanceCarFactory() {
carMap = new HashMap<Long, Car>();
carMap.put(1L,new Car("benz",1L,"red",17.3,new Date()));
carMap.put(2L,new Car("beck",2L,"white",11.7,new Date()));
carMap.put(3L,new Car("lenor",3L,"blue",19.5,new Date()));
}
public Car getCar(long id){
return carMap.get(id);
}
}
xml文件中需要写入2个bean:工厂bean和car bean
<!-- 配置实例工厂 bean -->
<bean id="carFactory" class="com.makerjack.factory.InstanceCarFactory"></bean>
<!-- 配置实例工厂创建car -->
<bean id="car" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="3"/>
</bean>
测试
IoC自动装载(Autowire)
IoC负责创建对象,DI负责完成对象的依赖注入,通过配置property标签的ref属性来完成,同时Spring提供了另外一种更加简便的依赖注入方式:自动装载,不需要手动配置property,IoC容器会自动选择完成注入
自动装载有2种方式:
- byName:通过属性名自动装载
- byType:通过属性的数据类型自动装载
比如有个person对象
以往是在此处引用先前创建的对象
自动装载就可以自动匹配现有的
byName是匹配同名对象,当有同名就会匹配不到(不会报错)
byType是匹配同类的,当有同种就会抛出异常