1、简介
Spring框架是一个开放源代码的 J2EE 应用程序框架,由 Rod Johnson 发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container)。
1.1 Spring框架主要由七部分组成:
- Spring Core
- Spring AOP
- Spring ORM
- Spring DAO
Spring Context - Spring Web
- Spring Web MVC
图片:
以下是Spring框架的指导原则:
- 提供各个级别的选择。Spring使您可以尽可能推迟设计决策。例如,您可以在不更改代码的情况下通过配置切换持久性提供程序。对于许多其他基础架构问题以及与第三方API的集成也是如此。
- 适应不同的观点。Spring拥有灵活性,并且对如何完成事情没有意见。它从不同的角度支持广泛的应用程序需求。
- 保持强大的向后兼容性。对Spring的演变进行了精心管理,以使各个版本之间几乎没有重大更改。Spring支持精心选择的JDK版本和第三方库,以方便维护依赖于Spring的应用程序和库。
- 关心API设计。Spring团队投入了大量的思想和时间来制作直观的API,并在许多版本和许多年中都得到了应用。
- 为代码质量设置高标准。Spring框架非常强调有意义,最新和准确的javadoc。它是极少数可以声明干净代码结构且程序包之间没有循环依赖关系的项目之一。
Spring的优点:
- Spring是一个开源免费的框架
- Spring是轻量级的、非入侵式的框架
- 控制反转(Ioc)、面向切面编程(AOP)
- 支持事物的处理,对框架整合的支持
- 可以下载所有版本源码地址:https://repo.spring.io/release/org/springframework/spring/
2、IoC
控制反转是一种设计思想,而依赖注入(DI)是实现IoC的一种方法。
本质上就是将获得依赖对象的控制权反转了,由程序交由第三方。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到零配置的目的。
2.1 HelloSpring示例:
//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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="hello" class="com.alinu.pojo.Hello">
<property name="str" value="Spring"/>
<!-- str是类变量,直接用value赋值,如果是对象,则用ref赋值 -->
</bean>
</beans>
//Hello.java
public class Hello {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
}
public class SpringTest {
public static void main(String[] args) {
//获取spring的上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//从spring中取出bean
Object hello = context.getBean("hello");
System.out.println(hello);
}
}
2.2 IoC创建对象方式
- 默认使用无参构造方法
- 通过index实现有参构造:
<constructor-arg value="index有参构造" index="0"/>
- (不建议使用)通过type实现有残构造:
<constructor-arg type="java.lang.String" value="type有参构造"/>
- 通过name实现有参构造:
<constructor-arg name="str" value="name有参构造"/>
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了。
3、Spring配置
3.1 别名
<alias name="hello" alias="helloNew"/>
3.2 bean配置
- id-bean的唯一标识符,也是对象名
- class-bean对象所对应的全限定类名
- name-也是别名,而且可以取多个别名
<bean id="hello" class="com.alinu.pojo.Hello" name="hello2,a;b c"></bean>
3.3 import
import一般用于团队开发使用,它可以将多个配置文件导入合并为一个。
<import resource="bean.xml"/>
<import resource="bean2.xml"/>
4、依赖注入
依赖注入(DI)是一个过程,通过该过程,对象只能通过构造函数参数,工厂方法的参数或在构造或创建对象实例后在对象实例上设置的属性来定义其依赖关系(即,与它们一起工作的其他对象)。
4.1 基于构造函数的依赖注入
基于构造函数的DI是通过容器调用具有多个参数(每个参数代表一个依赖项)的构造函数来完成的。调用static带有特定参数的工厂方法来构造Bean几乎是等效的,并且本次讨论也将构造函数和static工厂方法的参数视为类似。以下示例显示了只能通过构造函数注入进行依赖项注入的类:
public class SimpleMovieLister {
// the SimpleMovieLister has a dependency on a MovieFinder
private MovieFinder movieFinder;
// a constructor so that the Spring container can inject a MovieFinder
public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// business logic that actually uses the injected MovieFinder is omitted...
}
构造函数参数解析匹配通过使用参数的类型进行。如果Bean定义的构造函数参数中不存在潜在的歧义,则在实例化Bean时,在Bean定义中定义构造函数参数的顺序就是将这些参数提供给适当的构造函数的顺序。考虑以下类别:
package x.y;
public class ThingOne {
public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {
// ...
}
}
<beans>
<bean id="beanOne" class="x.y.ThingOne">
<constructor-arg ref="beanTwo"/>
<constructor-arg ref="beanThree"/>
</bean>
<bean id="beanTwo" class="x.y.ThingTwo"/>
<bean id="beanThree" class="x.y.ThingThree"/>
</beans>
当引用另一个bean时,类型是已知的,并且可以发生匹配(与前面的示例一样)。当使用诸如的简单类型时 true,Spring无法确定值的类型,因此在没有帮助的情况下无法按类型进行匹配。考虑以下类别:
package examples;
public class ExampleBean {
// Number of years to calculate the Ultimate Answer
private int years;
// The Answer to Life, the Universe, and Everything
private String ultimateAnswer;
public ExampleBean(int years, String ultimateAnswer) {
this.years = years;
this.ultimateAnswer = ultimateAnswer;
}
}
//构造函数参数类型匹配
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>
//构造函数参数索引
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg index="0" value="7500000"/>
<constructor-arg index="1" value="42"/>
</bean>
//构造函数参数名称
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg name="years" value="7500000"/>
<constructor-arg name="ultimateAnswer" value="42"/>
</bean>
4.2 基于setter的依赖注入(重点)
<bean id="address" class="com.alinu.pojo.Address">
<property name="address" value="河南郑州"/>
</bean>
<bean id="student" class="com.alinu.pojo.Student">
<!--普通属性注入-->
<property name="name" value="林新"/>
<!--bean注入-->
<property name="address" ref="address"/>
<!--数组注入-->
<property name="books">
<array>
<value>红楼梦</value>
<value>西游记</value>
<value>三国演义</value>
<value>水浒传</value>
</array>
</property>
<!--list集合注入-->