Spring
1、什么是框架
框架是软件半成品!使用框架可以简化应用软件的开发,提高开发效率。
使用框架必须遵守框架的使用约定!
2、什么是Spring框架
由Spring开源社区开发维护的 “系列” 软件框架。
其核心组件:IOC/AOP
3、IOC容器
IOC,控制反转:由外部容器环境创建管理 “对象组件” ,交给 应用程序 使用。
主动控制:由应用程序控制管理 “对象组件” 。
Spring最基本的功能就是IOC容器,也称为Spring容器,Spring IOC 容器。
Spring IOC 容器:控制创建管理“对象组件”的容器。
4、Spring Hello World
1、导入 Spring IOC 组件包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
spring-context的applicationContext.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
</beans>
2、创建被 Spring IOC 管理的对象组件 类。
3、创建配置文件:通知 Spring 管理哪个对象组件。
4、创建应用程序
- 创建 Spring 容器,读取 Spring 配置文件
- 从 Spring 容器中获取,被 Spring 管理的对象(控制反转)
- 调用对象的方法(验证),输出 Hello World!
Hello World 示例:
代码实现:
applicationContext.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
<!-- class用于通知Spring,Spring会读取class的值,在Spring内部用反射创建对象 -->
<!-- id用于标识识别对象,id不能重复 -->
<bean id="demo" class="day01.Demo"></bean>
</beans>
Demo类:(由Spring管理的类)
package day01;
public class Demo {
public void test() {
System.out.println("Hello World!");
}
}
Demo01:(模拟应用程序)
package day01;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Spring IOC 容器基本功能演示
* @author DELL
*
*/
public class Demo01 {
public static void main(String[] args) {
//1.创建Spring容器对象,参数是Spring配置文件
// Spring会读取配置文件,根据配置文件 利用反射 创建被管理的对象组件。
ClassPathXmlApplicationContext ctx =
new ClassPathXmlApplicationContext("applicationContext.xml");
//2.从Spring容器中得到被管理的对象组件
Demo obj = (Demo)ctx.getBean("demo");
obj.test();
}
}
5、Java Bean (爪哇豆子)
Bean:豆子
JavaBean:符合一定规范的Java对象,JavaBean规范不是语法规范,违反不会有编译错误。
一般规范有:
1.需要定义包 package
2.有无参构造器
3.需要实现序列化接口
4.包含使用 getXxx、setXxx 声明的“Bean属性” xxx
- Bean属性(Bean Property)就是指 getXxx、setXxx 方法
- 对象属性(Object Field)是指对象的实例变量
例:
class Person{
private String name = "狄仁杰"; // 实例变量、对象属性 name
String getName(){ // Bean属性 name
return name;
}
void setName(String name){ // Bean属性 name
this.name = name;
}
String getLastName(){ //Bean属性 lastName
return name.substring(0,1);
}
}
Spring容器也称为JavaBean容器,Spring建议被IoC容器管理的对象符合JavaBean规范.(实际上可以不遵守!)
6、Bean标签别名
<?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:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
<!-- class用于通知Spring,Spring会读取class的值,在Spring内部用反射创建对象 -->
<!-- id用于标识识别对象,id不能重复 -->
<bean id="demo" class="day01.Demo"></bean>
<!-- alias:别名,曾用名 -->
<alias name="demo" alias="demo1"/>
<!-- Bean 标签的 id 属性和 name 属性的作用一样 -->
<!-- 大多数使用 id 属性 -->
<bean name="demo2" class="day01.Demo"></bean>
</beans>
测试:
package day01;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestCase {
ClassPathXmlApplicationContext ctx; //实例变量,Java没有全局变量
@Before // init() 会在测试案例之前执行,一般用来初始化测试案例的环境,如:初始化 Spring 容器。
public void init() {
ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@After // destroy() 会在测试案例之后执行,用户与回收系统资源,如:关闭 Spring 容器。
public void destroy() {
ctx.close();
}
@Test
public void testDemo() {
/*
* Spring Hello World
*/
Demo demo = (Demo)ctx.getBean("demo");
demo.test();
}
@Test
public void testAlias() {
/*
* 测试 在 Spring 中为JavaBean对象声明别名
*/
Demo demo = (Demo)ctx.getBean("demo1");
demo.test();
}
@Test
public void testName() {
/*
* 测试 Spring 中用 name 属性标识识别对象
*/
Demo demo = (Demo)ctx.getBean("demo2");
demo.test();
}
@Test
public void testGetBean() {
/*
* Spring 容器提供了重载的 getBean 方法,可以自动完成类型转换,不用写强制转型
*/
// 第一个参数是 id 属性值,第二个参数是 Bean 对象的类型
Demo demo = ctx.getBean("demo", Demo.class);
demo.test();
}
}
7、Bean的作用域(Scope)
1、Spring 容器默认情况下按照“单例”管理对象。
- 单例:在软件中对象是唯一的一个实例的现象。
- 多次调用 getBean 获得的是同一个对象的引用。
2、Spring 使用 bean 标签的 scope 属性可以指定多例。
3、Spring 默认情况下单例方式可以提高性能。
<!-- scope 属性声明“原型prototype”创建多个实例,每次调用 getBean 的时候都会创建一个新实例 -->
<bean id="myBean" class="day01.Demo" scope="prototype"></bean>
@Test
public void testMyBean() {
/*
* 使用“scope=prototype”创建多个对象实例
* 每次调用 getBean 方法都会创建一个对象实例
*/
Demo d1 = ctx.getBean("myBean", Demo.class);
Demo d2 = ctx.getBean("myBean", Demo.class);
System.out.println(d1==d2); // false
}
8、Bean的生命周期管理方法
1、指定初始化回调方法
<bean id="exampleBean" class="com.foo.ExampleBean "
init-method = "init" >
</bean>
2、指定销毁回调方法,仅适用于 singleton 模式的 bean
<bean id="exampleBean" class="com.foo.ExampleBean"
destroy-method = "destroy" >
</bean>
<!-- init-method 设置创建对象以后执行的方法 -->
<!-- destroy-method 设置关闭容器销毁对象时执行的方法 -->
<!-- 这两个方法会自动执行 -->
<!-- destroy-method:只对单例对象有效,多例对象上设置无效 -->
<bean id="logTool" class="day01.LogTool" init-method="open" destroy-method="close"></bean>
提示:指定 销毁回调方法,仅适用于singleton模式的bean。
代码演示:
LogTool:
package day01;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
public class LogTool {
String fileName = "demo.log";
PrintWriter out;
public void open() throws Exception {
// 打开文件
// 覆盖写
// out = new PrintWriter(fileName);
// 追加写
out = new PrintWriter(new FileOutputStream(fileName, true));
System.out.println("打开文件!");
}
public void write(String log) {
out.println(log);
out.flush();
}
public void close() {
out.close();
System.out.println("关闭文件!");
}
}
TestCase:
@Test
public void testLogTool() {
/*
* 测试对象声明周期管理方法,
* init-method 设置创建对象以后执行的方法
* destroy-method 设置关闭容器销毁对象时执行的方法
*/
LogTool tool = ctx.getBean("logTool", LogTool.class);
tool.write("这是一个测试!");
tool.write("再试试!");
}
反例: 测试 多个实例情况下不会执行 destroy-method 的方法
<!-- Spring作为多例管理的对象,不会执行 destroy-method -->
<bean id="demoBean" class="day01.DemoBean" scope="prototype"
init-method="init" destroy-method="destroy"></bean>
DemoBean类:
package day01;
/**
* 测试:多实例的时候,关闭容器时,不会执行 destroy-method 的方法
* @author DELL
*
*/
public class DemoBean {
public void init() {
System.out.println("Call init()");
}
public void destroy() {
System.out.println("Call destroy()");
}
}
测试:
@Test
public void testDestroy() {
/*
* scope="prorotype"
* 多个实例情况下不会执行 destroy-method 的方法
* 每次创建对象,都会执行对象的 init-method
*/
DemoBean bean = ctx.getBean("demoBean", DemoBean.class);
DemoBean bean2 = ctx.getBean("demoBean", DemoBean.class);
System.out.println(bean2);
}
测试结果为:
9、Bean延迟实例化
在 ApplicationContext 实现的默认行为就是在启动时将所有 singleton bean(单例对象) 提前进行实例化。
如果不想让一个 singleton bean(单例对象) 在ApplicationContext初始化时被提前实例化,可以使用<bean>
元素的lazy-init="true"
属性改变。
一个延迟初始化bean将在第一次被用到时实例化
<bean id="exampleBean" lazy-init="true" class="com.foo.ExampleBean"/>
在顶级的<beans/>
元素中的default-lazy-init属性,可以为容器所有<bean>
指定延迟实例化特性
对于很少使用的单例对象,可以设置懒初始化,这样可以最大化的节省内存。
案例:
<!-- 设置懒惰加载,Spring会在第一次使用对象时候创建对象,如果不使用对象,就不会创建对象。 -->
<bean id="demoBean1" class="day01.DemoBean" lazy-init="true" init-method="init"></bean>
@Test
public void testLazyInit() {
/*
* 测试单例对象的懒惰加载方式,在第一次调用 getBean 方法时候创建对象。
* 如果不调用 getBean 方法,就不会创建 Bean 对象。
*/
//DemoBean bean = ctx.getBean("demoBean1", DemoBean.class);
//DemoBean bean1 = ctx.getBean("demoBean1", DemoBean.class);
System.out.println("Lazy-init");
}
DI:依赖注入
IOC容器不仅可以管理对象,还可以利用DI功能为对象注入Bean属性。
对象的依赖:一个对象在执行功能期间需要使用另外一个对象,称为对象的依赖。
属性注入:将一个对象作为属性注入给另外对象。
案例图示:
代码实现:
Spring配置文件:
<!-- 利用 property 注入依赖的对象 -->
<bean id="qiang" class="day01.Worker">
<!-- 将 斧子Bean 对象注入到 Bean属性中 -->
<property name="axe" ref="axe1"></property>
</bean>
<bean id="axe1" class="day01.Axe"></bean>
Worker:
package day01;
public class Worker {
private String name = "光头强";
private Axe axe;
public void setAxe(Axe axe) {
this.axe = axe;
}
public void work() {
// 字符串连接的时候自动调用了 Axe 的 toString 方法
System.out.println(name+"使用"+axe+"砍树!");
}
}
Axe:
package day01;
public class Axe {
@Override
public String toString() {
return "金斧子";
}
}
测试:
@Test
public void testWork() {
/*
* 测试Spring提供的 DI 功能
*/
Worker qiang = ctx.getBean("qiang", Worker.class);
qiang.work();
}