Spring
Spring: 是一套 Java 开源框架家族,以 Ioc 和 AOP 最为核心。
SpringWebMVC: Spring 家族中基于 Servlet 构建的一套 Web 开发框架。
SpringBoot: Spring 家族中简化 Spring 开发配置的开发框架。
IoC: IOC是Inversion of Control的缩写,多数书籍翻译成“控制反转”。简单来讲,就是对象界的淘宝,把对象的生 产和使用分离。买家只需要关心使用对象,不关心对象具体怎么来的。
DI: Dependency Injection 依赖注入,可以简单认为就是 IoC,指的是使用对象的时候会有快递小哥把对象送上。 至于对象哪来的,快递小哥哪来的,我们都不需要关心。
AOP: Aspect Oriented Programming的缩写,面向切面编程的意思。把程序的运行过程想象成一段一段的环节组 成,可以通过不修改代码的方式,方便的在这些段落前后加入新的功能。
MVC: Model/View/Controller 模型/视图/控制器 是一种常见的设计层级关系。
Service: 一种设计层级,一般用来组织业务模型。
DAO: Database Access Object,一种设计层级,一般指访问数据库的这层模型。
Freemarker: 一种 View 的技术,除此之外,可以直接使用 JSP 或者 Thymeleaf。
Mybatis: 一种 DAO 的技术。
POJO: POJO(Plain Ordinary Java Object)简单的Java对象,不需要实现、继承任何的接口或者类的对象。
Spring的核心机制
管理Bean
程序主要是通过Spring容器来访问容器中的Bean,ApplicationContext是Spring容器最常用的接口,该接口有如下两个实现类:
-
ClassPathXmlApplicationContext: 从类加载路径下搜索配置文件,并根据配置文件来创建Spring容器。
-
FileSystemXmlApplicationContext: 从文件系统的相对路径或绝对路径下去搜索配置文件,并根据配置文件来创建Spring容器
public class BeanTest{ public static void main(String args[]) throws Exception{ ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); Person p = ctx.getBean("person", Person.class); p.say(); } }
Spring框架的核心功能有两个:
- Spring容器作为超级大工厂,负责创建、管理所有的Java对象,这些Java对象被称为Bean。
- Spring容器管理容器中Bean之间的依赖关系,Spring使用一种被称为"依赖注入"的方式来管理Bean之间的依赖关系。
使用依赖注入,不仅可以为Bean注入普通的属性值,还可以注入其他Bean的引用。依赖注入是一种优秀的解耦方式,其可以让Bean以配置文件组织在一起,而不是以硬编码的方式耦合在一起。
IOC和DI
ioc:控制反转,将对象创建权交给spring内部,我们程序员只需要到spring容器里面去取,将对象得创建和使用解耦。
DI:动态注入,ioc是一种思想理念,DI是他得具体实现。实质就是再程序运行时,依赖ioc容器,动态得从ioc容器中去获取我们所需要得对象,
DI得实现得方式有三种:
- set方法注入
- 构造方法注入
- 接口注入
bean容器
bean:通过容器统一 管理对象的生命周期
- 减少对象创建、销毁的步骤,提高了效率:不用每次都在方法中创建对象,退出方法后对象又很快变为可回收状态
- 可以统一管理对象之间的依赖关系
环境准备:
-
准备 maven 项目,加入依赖
<dependencies> <!-- Spring 需要的依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.3.RELEASE</version> </dependency> <!-- 日志需要的依赖 --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> </dependencies>
-
实际导入的 jar 包如图
代码
-
需要让属性有 public 权限或者 setter 有 public 权限
-
基本数据类型 + String 用 value,其他引用类型用 ref
-
如果要使用集合,有 map、list、set 等直接使用
Scope的使用
Duck类:
package model;
public class Duck {
private String name;
private Integer age;
public Duck() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Duck(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Duck{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
修改 applications.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对象:默认通过无参构造方法定义-->
<bean id="duck1" class="model.Duck">
<property name="name" value="LadyGaga"/>
<property name="age" value="10"/>
</bean>
<!-- 通过有参的构造方法定义bean对象-->
<bean id="duck2" class="model.Duck" scope="prototype">
<constructor-arg name="name" value="烤鸭"/>
<constructor-arg name="age" value="2"/>
</bean>
</beans>
Main类:
singleton :(默认)单例方式,每个容器中只有一份 bean defifination
prototype :平时 new 的方式,每次调用 getBean() 都会得到一份新的 bean
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applications.xml");
//从容器中获取bean对象
Duck duck1=(Duck) context .getBean("duck1");
System.out.println(duck1);
Duck duck1_1=(Duck) context .getBean("duck1");
System.out.println(duck1==duck1_1);//true:duck1默认scope为单例
Duck duck2=(Duck) context.getBean("duck2");
System.out.println(duck2);
Duck duck2_2=(Duck) context.getBean("duck2");
System.out.println(duck2==duck2_2);//false:duck2设置的scope为prototype,geybean生产新的对象
}
}
集合的使用
如果要使用集合,有 map、list、set 等直接使用
package model;
import java.util.List;
public class DuckShop {
private List<Duck> ducks;
@Override
public String toString() {
return "DuckShop{" +
"ducks=" + ducks +
'}';
}
public List<Duck> getDucks() {
return ducks;
}
public void setDucks(List<Duck> ducks) {
this.ducks = ducks;
}
}
<bean id="duckshop" class="model.DuckShop">
<property name="ducks">
<list>
<ref bean="duck1"/>
<ref bean="duck2"/>
</list>
</property>
</bean>
引用已有的类型
package model;
public class Person {
private Duck duck;
public Duck getDuck() {
return duck;
}
public void setDuck(Duck duck) {
this.duck = duck;
}
@Override
public String toString() {
return "Person{" +
"duck=" + duck +
'}';
}
}
<!--引用已有的bean对象,ref-->
<bean id="p1" class="model.Person">
<property name="duck" ref="duck1"/>
</bean>
静态工厂方法、实例工厂方法
静态工厂方法: factory-method
实例工厂方法: factory-bean+factory-method
- factory-bean: 该属性的值为工厂Bean的id。
- factory-method: 该属性指定实例工厂的工厂方法。
package model;
public class DuckFactory {
public static Duck create(){
Duck d=new Duck();
d.setName("秀才");
d.setAge(3);
return d;
}
public Duck create1(){
Duck d=new Duck();
d.setName("秀才1");
d.setAge(3);
return d;
}
}
<!-- 通过静态方法实例化对象-->
<bean id="duck3" class="model.DuckFactory" factory-method="create"></bean>
<bean id="duckFactory" class="model.DuckFactory"/>
<!-- 通过实例方法实例化对象-->
<bean id="duck4" factory-bean="duckFactory" factory-method="create1"/>
生命周期
Spring Bean的完整生命周期从创建Spring容器开始,直到最终Spring容器销毁Bean,这其中包含了一系列关键点。
- 实例化对象;
- 填充属性值及引用;
- 调用
BeanNameAware
的setBeanName(String name)
设置 bean 的 id; - 调用
BeanFactoryAware
的setBeanFactory(BeanFactory beanFactory)
设置BeanFactory
Bean工厂; - 同上:
ApplicationContextAware
setApplicationContext(ApplicationContext applicationContext)
; - 如果实现
BeanPostProcessor
,则 调用 postProcessBeforeInitialization() 初始化前的后置处理方法 - 如果实现了
InitializingBean
接口,则使用afterPropertiesSet()
来初始化属性 - 如果实现
BeanPostProcessor
,则 调用 postProcessAfterInitialization() 初始化后的后置处理方法 - 此时,bean 就可以使用了
DisposableBean
接口destroy()
销毁bean。不过在Spring5.0开始,DisposableBean.destroy() 已经是过时的方法了,可直接使用 close()。