1.Spring简介
本篇文件基于尚硅谷雷神的视频所做笔记。
Spring是一个轻量级的、控制反转和面向切面编程的框架。
体系结构:
Test:Spring的单元测试模块
Core Container:核心容器(IOC),包括4部分:
spring-core:提供了框架的基本组成部分,包括 IoC 和依赖注入功能。
spring-beans:提供 BeanFactory,
spring-context:模块建立在由core和 beans 模块的基础上建立起来的,它以一种类似于JNDI注册的方式访问对象。Context模块继承自Bean模块,并且添加了国际化(比如,使用资源束)、事件传播、资源加载和透明地创建上下文(比如,通过Servelet容器)等功能
spring-expression:提供了强大的表达式语言,用于在运行时查询和操作对象图。它是JSP2.1规范中定义的统一表达式语言的扩展,支持set和get属性值、属性赋值、方法调用、访问数组集合及索引的内容、逻辑算术运算、命名变量、通过名字从Spring IoC容器检索对象,还支持列表的投影、选择以及聚合等
AOP+Aspects:面向切面编程模块
Data Access:数据访问模块
Web:Spring开发Web引用模块
导入依赖:spring-webmvc 包含的最广泛
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
2.HelloWorld案例
2.1 IOC和DI
**主动式:**自己需要什么自己创建
BookServlet{
BookService bs = new BookService();
}
被动式:
BookServlet{
BookService bs ;
public void test(){
bs.checkout();
}
}
控制,即资源的获取方式,包括:
1.主动式:要什么资源自己创建,对于复杂对象的创建时比较庞大的工程
2.被动式:资源的获取不是我们自己创建,而是交给容器创建。
所谓容器,是用来管理所有的组件的(即有功能的类);BookServlet,BookService都受容器管理,容器可以自动探查出哪些组件需要用到另一些组件;容器帮我们创建BookService 对象,并且把BookService 对象赋值过去;
**容器:**婚介所:主动获取变为被动接受
程序员只需要告诉容器在什么时候创建什么对象
**DI:Dependency Injection,依赖注入,**是IOC的一种实现形式。容器能知道哪个组件运行时需要另外一个类,容器通过反射的形式,将容器中准备好的BookService对象注入(用反射)到BookServlet中
只要是容器管理的组件,都能使用容器提供的强大功能。
2.2 入门案例
HelloWorld:所有的对象交给容器创建,给容器中注册组件
- 新建一个Person类,添加set方法
public class Person {
private String lastName;
private Integer age;
private String gender;
private String email;
public Person() {
}
public Person(String lastName, Integer age, String gender, String email) {
this.lastName = lastName;
this.age = age;
this.gender = gender;
this.email = email;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "Person{" +
"lastName='" + lastName + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", email='" + email + '\'' +
'}';
}
}
- 新建一个Spring配置文件ApplicationContext.xml,注册bean。
使用bean标签注册一个Person对象,Spring会自动创建这个Person对象
class:写要注册的组件的全类名
id:这个对象的唯一标识
使用property标签为Person对象的属性值,name:指定属性名;value:指定属性值。
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--注册一个Person对象,Spring会自动创建这个Person对象
class:写要注册的组件的全类名
id:这个对象的唯一标识
-->
<bean id="person01" class="com.xiao.bean.Person">
<!--使用property标签为Person对象的属性赋值
name:指定属性名
value:指定属性值
-->
<property name="lastName" value="zhangsan"/>
<property name="age" value="20"/>
<property name="email" value="zhangsan@163.com"/>
<property name="gender" value="0"/>
</bean>
</beans>
- 测试
public class IocTest {
@Test
public void test(){
//容器创建
ApplicationContext ioc = new ClassPathXmlApplicationContext("ApplicationContext.xml");
Person bean = (Person) ioc.getBean("person01");
System.out.println(bean);
}
}
【几个细节】:
ApplicationContext:IOC容器的接口
ClassPathXmlApplicationContext(“ioc.xml”):ioc容器的配置文件在类路径下,
FileSystemXmlApplicationContext(“d://ioc.xml”)ioc容器的配置文件在磁盘路径下
同一个组件在IOC容器中默认是单实例的
容器中的对象的创建在容器创建完成的时候就已经创建好了
容器中如果没有这个组件,获取组件时会报异常 NoSuchBeanDefinitionException
IOC容器用property标签创建这个组件对象的时候,会利用setter方法为其属性赋值,注意属性名是set方法后的那串的首字母小写
2.3 根据bean类型获取bean实例
ioc.getBean()方法中可以传入bean的id,也可以传入class对象,也可以同时传入。
如果一个类型指只注册了一个,则可以通过ioc.getBean(....class)
获得该对象
Person bean1 = ioc.getBean(Person.class);
但是如果IOC容器中这个类型的bean有多个,则会报异常 NoUniqueBeanDefinitionException
但是如果IOC容器中这个类型的bean有多个,则会报异常 NoUniqueBeanDefinitionException
也可以同时传入bean的id和class对象:
Person bean1 = ioc.getBean("person02",Person.class);
3. 属性的注入方式
- 依赖:bean对象的创建依赖于容器
- 注入:bean对象中所有的属性由容器来注入
3.1 setter注入
需要借助set方法,使用propetry
标签
<property name="lastName" value="zhangsan"/>
3.2 通过构造器注入
使用constructor-arg标签,则调用构造器进行属性注入,需要借助有参构造
通过构造函数中的参数名称注入
<bean id="person" class="com.xiao.bean.Person">
<constructor-arg name="lastName" value="wangwu"/>
<constructor-arg name="age" value="30"/>
</bean>
只写value属性,会默认按顺序寻找构造方法进行匹配
<bean id="person" class="com.xiao.bean.Person">
<constructor-arg value="wangwu"/>
<constructor-arg value="30"/>
</bean>
通过构造函数参数类型,默认按照顺序
<bean id="person" class="com.xiao.bean.Person">
<constructor-arg type="java.lang.String" value="wangwu"/>
<constructor-arg type="java.lang.Integer" value="30"/>
</bean>
通过构造函数参数索引,如果有多个重载的构造函数时也可以配合type一起使用
<bean id="person" class="com.xiao.bean.Person">
<constructor-arg index="0" value="wangwu"/>
<constructor-arg index="1" value="30"/>
</bean>
3.3 p名称空间注入
使用p:propertyName直接注入属性的值。本质上还是调用的set方法
导入头文件约束:
xmlns:p="http://www.springframework.org/schema/p"
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="person01" class="com.xiao.bean.Person">
<property name="lastName" value="zhangsan"/>
<property name="age" value="20"/>
<property name="email" value="zhangsan@163.com"/>
<property name="gender" value="0"/>
</bean>
<bean id="person04" class="com.xiao.bean.Person"
p:lastName="zhangsan" p:age="30" p:email="zhangsan@qq.com" p:gender="1">
</bean>
</beans>
3.4 c命名空间注入
c(构造: Constructor)命名空间注入,使用c:propertyName注入属性值,本质上使用的是构造器注入
导入头文件约束:
xmlns:c="http://www.springframework.org/schema/c"
<bean id="person05" class="com.xiao.bean.Person"
c:lastName="zhangsan" c:age="30" c:email="zhangsan@qq.com" c:gender="1">
</bean>