Spring 框架 简述(一)

什么是框架

框架(Framework):框(指约束性)架(指其支撑性),在软件设计中指为解决一个开放性问题而设计的具有一定约束性的支撑结构。在此结构上可以根据问题扩展、安插更多的组成部分,从而更迅速和方便地构建完整的解决问题的方案

框架天生就是为了扩展而设计的

Spring是什么

Spring 被称为J2EE的春天,是一个分层的Java SE/EE full-stack 开源轻量级的Java开发框架,是最受欢迎的企业级Java应用程序开发框架,数以百万的来自世界各地的开发人员使用Spring框架来创建性能好、易于测试、可重用的代码。

Spring具有控制反转(IoC)和面向切面(AOP)两大核心。Java Spring框架通过声明方式灵活地进行事务的管理,提高开发效率和质量。

Spring框架不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring框架还是一个超级粘合平台,除了自己提供的功能外,害提供耦合其他技术和框架的能力。

Spring的优势

1、方便解耦,简化开发
	Spring 就是一个大工厂,可以将所有对象的创建和以来关系的维护交给 Spring 管理
2、方便集成各种优秀框架
	Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架的直接支持(比如 MyBatis)
3、降低 Java EE API 的使用难度
	Spring 对 Java EE 开发中非常难用的一些 API (JDBC、JavaMail、远程调用等)都提供了封装,使这些 API 应用的难度大大降低。
4、方便程序的测试
	Spring 支持 JUnit4,可以通过注册方便地测试 Spring 程序
5、AOP 编程的支持
	Spring 提供面向切面编程,可以方便地实现对程序进行权限拦截和运行监控等功能。
6、声明式事务的支持
	只需要通过配置就可以完成对事务的管理,而无须手动编程

Spirng 的体系

Spring 为我们提供了一站式解决方案,但Spring是模块化的,允许使用者挑选适用于项目的模块,不需要把剩余部分也引入

核心容器

核心容器由 Spirng-core,Spring-beans,Spring-context,Spring-context-support和Spring-expression(SpEl,Spring 表达式语言,Spring Expression Language)等模块组成

Spirng-core 模块提供了框架的基本组成部分,包括 IoC 和依赖注入功能
Spirng-bean模块提供 BeanFactory,工厂模式的微妙实现,它移除了编码式单例的需要,并且可以把配置和依赖从实际编码逻辑中解耦
context 模块建立在由 core和 beans 模块的基础上建立起来的,它以一种类似于 JNDI 注册的方式访问对象。Context 模块继承自 Bean 模块,并且添加了国际化(比如,使用资源束)、事件传播、资源加载和透明地创建上下文(比如,通过 Servelet 容器)等功能Contex模块也支持 JavaEE 的功能,比如 EJB、JMX 和远程调用等。ApplicationContext 接口是 Context 模块的焦点。Spring-context-support 提供了对第三方集成到 Spring 上下文的支持比如缓存(EhCache,Guava, JCache)、邮件(JavaMail)、调度(CommonJ, Quartz)、模板引擎(FreeMarker,JasperReports, Velocity)等
Spring-expression 模块提供了强大的表达式语言,用于在运行时查询和操作对象图。它是 JSP2.1规范中定义的统一表达式语言的扩展,支持 set 和 get 属性值、属性赋值、方法调用、访问数组集合及索引的内容、逻辑算术运算、命名变量、通过名字从 Spring IoC 容器检索对象,还支持列表的投影、选择以及聚合等。

数据访问/集成

JDBC=Java Data Base Connectivity,ORM=Object Relational Mapping,OXM=Obeject XML Mapping,JMS=Java Message Service

JDBC 模块提供了 JDBC 抽象层,它消除了冗长的 JDBC 编码和对数据库供应商特定错误代码的解析
ORM 模块提供了对流行的对象关系映射 API 的集成,包括 JPA、JDO 和 Hibernate 等,通过此模块可以让这些 ORM 框架和 Spring 的其他功能整合,不然前面提及的事务管理
OXM 模块提供了对 OXM 实现的支持,比如 JAXB、Castor、XML Beans、JiBX、XStream等
JMS 模块包含生产(produce)和消费(consume)消息的功能,从 Spring 4.1 开始,集成了 Spring-messaging 模块 
事务模块为实现特殊接口类及所有的 POJO 支持编码式和声明式事务管理

Web

Web 模块提供面向 web 的基本功能和面向 web 的应用上下文,比如多部分(multipart)文件上传功能、使用 Servlet 监听器初始化 IoC 容器等。它还包括 HTTP 客户端以及 Spring 远程调用中与web 相关的部分
Web-MVC 模块为 web 应用提供了模型视图控制(MVC)和 REST Web服务的实现。Spring 的MVC 框架可以使领域模型代码和 web 表单完全地分离,且可以与 Spring 框架的其它所有功能进行集成
Web-Socket 模块为 WebSocket-based 提供了支持,而且在 web 应用程序中提供了客户端和服务器端之间通信的两种方式
Web-Portlet 模块提供了用于 Portlet 环境的 MVC 实现,并反映了 Spring-webmvc 模块的功能

其他

AOP 模块提供了面向方面(切面)的编程实现,允许你定义方法拦截器和切入点对代码进行干净地解耦,从而使实现功能的代码彻底的解耦出来
Aspects 模块提供了与 AspectJ 的集成,这是一个功能强大且成熟的面向切面编程(AOP)框架
Instrumentation 模块在一定的应用服务器中提供了类 instrumentation 的支持和类加载器的实现
Messaging 模块为 STOMP 提供了支持作为在应用程序中 WebSocket 子协议的使用。它也支持一个注解编程模型,它是为了选路和处理来自 WebSocket 客户端的 STOMP 信息
测试模块支持对具有 JUnit 或 TestNG 框架的 Spring 组件的测试

Spring 核心之IoC控制反转

概述说完了,该进入正题了,Ioc-Inversion of Control,即控制反转,不是一种技术,而是一种设计思想。
IoC 是指在程序开发中,实例的创建不再由调用者管理,而是由 Spring 容器创建,Spring 容器会负责控制程序之间的关系,而不是由程序代码直接控制,因此,控制权由程序代码转移到了 Spring 容器中,控制权发生了反转,这就是 Spring 的 IoC 思想。

Spring入门案例

注:本人使用的是 jdk 8 版本
1、创建 maven 项目,补齐目录结构
在这里插入图片描述
2、pom.xml 文件添加依赖和插件

<dependencies>
	<!--单元测试-->
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.12</version>
		<scope>test</scope>
	</dependency>
	<!--spring依赖-->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>5.2.13.RELEASE</version>
	</dependency>
</dependencies>
<build>
	<plugins>
		<plugin>
			<!--编译插件-->
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-compiler-plugin</artifactId>
			<version>3.8.0</version>
			<configuration>
				<source>1.8</source>
				<target>1.8</target>
			</configuration>
		</plugin>
	</plugins>
</build>

3、创建一个实体类

package com.imok.pojo;
/**
* 实体类 学生
*/	
public class Student{
	//学号
    private Integer id;
    //姓名
    private String name;
    //班级
    private String classRoom;

    //无参 (默认构造方法)
    public Student() {
        System.out.println("Student 的默认构造方法被调用: id="+id+",name="+name+",classRoom="+classRoom);
    }
}

4、创建 Spring 的配置文件 application.xml
在这里插入图片描述

5、使用 Spring 容器创建对象

在application.xml 文件中配置
<?xml version="1.0" encoding="UTF-8"?>
<!--spring 的配置文件
    1、beans:根标签,spring中java的对象称为bean
    2、spring-beans.xsd 是约束文件,(约束XML文件中能编写哪些标签)
-->
<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 http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!--创建对象:声明bean,通知spring要创建哪个类的对象
        一个bean标签声明一个对象:
            id="自定义的对象名称",唯一
            class="类的完全限定名" 包名+类名,spring底层是反射机制创建对象,所以必须使用类名
           
           以下配置相当于 Student student1 = new Student(); 创建好的对象放入到集合 Map 中
           即 springMap.put("student1",new Student());
    -->
    <bean id="student1" class="com.imok.pojo.Student"></bean>
    
</beans>

6、获取 Spring 容器

配置完毕后,就可以获取注册在Spring容器中的对象了,Spring 提供了两种 IoC 容器,分别为 BeanFactory 和 ApplicationContext

6.1、BeanFactory

BeanFactory 是基础类型的 IoC 容器,是一个管理 Bean 的工厂,它主要负责初始化各种 Bean,并调用它们的生命周期方法。

BeanFactory 接口有多个实现类其中最常见的是org.Springframework.beans.factory.xml.XmlBeanFactory,它是根据 XML 配置文件中的定义装配 Bean 的。

BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource(Spring配置文件名称));

6.2、ApplicationContext

ApplicationContext 是 BeanFactory 的子接口,也称为应用上下文,它不仅提供了 BeanFactory 的所有功能,还添加了对 i18n (国际化)、资源访问、事件传播等方面的良好支持。

ApplicationContext 接口有两个常用的实现类:

6.2.1、ClassPathXmlApplicationContext ----- 常用
该类从类路径 ClassPath 中寻找指定的 XML 配置文件,找到并装载完成 ApplicationContext 的实例化工作

ApplicationContext applicationContext = new ClassPathXmlApplicationContext(Spring配置文件的名称);

6.2.2、FileSystemXmlApplicationContext

ApplicationContext applicationContext = new FIleSystemXmlApplicationContext(String configLocation);

它与 ClassPathXmlApplicationContext 的区别是:

在读取 Spring 的配置文件时,FileSystemXmlApplicationContext不再从类路径中读取配置文件,而是通过参数指定配置文件的位置,它可以获取类路径以外的资源,如"D:\application.xml"

7、通过上下文对象获取容器中的对象 (注释掉的方法就不导包了…)

package com.imok.pojo;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test1 {
    @Test
    public void test01(){
        //使用 spring 容器创建对象
        //1、指定spring配置文件的名称
        String springConfig = "application.xml";
        
        //2、创建spring容器的对象
        
        //方式1:不推荐:
        //BeanFactory beanFactory = new XmlBeanFactory(new FileSystemmResource("D:/imtry/src/main/resources/application.xml"));
        //beanFactory.getBean("student1");//根据ID 从 IOC 容器中获取对象

        //方式2: 常用
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(springConfig);//这里执行完毕容器中的对象都已创建完成

        //方法3:不常用
        //ApplicationContext applicationContext2 = newFileSystemXmlApplicationContext("D:/imtry/src/main/resources/application.xml");
        
        //3、获取容器中的对象  //需要强转  如果xml文件中配置的类与该对象的类型一样则不会报错
        Student student1 = (Student) applicationContext.getBean("student1");
        
        //4、容器其他api
        int beanDefinitionCount = applicationContext.getBeanDefinitionCount();//获取容器中的对象个数

        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();//获取容器中所有对象的名称

        for (int i = 0; i < beanDefinitionCount; i++) {
            System.out.println("spring容器中第"+(i+1)+"个对象,该对象名称为:"+beanDefinitionNames[i]);
        }
    }
}

8、创建非自定义对象
除了自定义对象,例如上文的 Student 对象外,还可以创建非自定义对象,例如 date

在 applicationContext.xml 文件中补充

<!--创建非自定义对象-->
<bean id="date" class="java.util.Date"></bean>

上面的测试方法中添加如下内容:

//5、获取日期对象
Date date1 = (Date)applicationContext.getBean("date1");
System.out.println("日期:"+date1);

9、bean标签的属性

属性说明
class指定bean对应类的全路径
namename是bean对应对象的一个标识
scope执行bean对象创建模式和生命周期,scope="singleton"和scope=“prototype”
idid是bean对象的唯一标识不能添加特别字符
lazy-init是否延迟加载 默认值:false。true 延迟加载对象,当对象被调用的时候才会加载,测试的时候,通过getbean()方法获取对象。false则无论是否被使用,都会立刻创建对象,测试时只需要加载配置文件即可。ps:测试的时候值留下 id,class 属性
init-method只需要加载配置文件即可对象初始化
destroy-method对象销毁方法

示例演示:

Student 实体类补充如下方法:

public void init(){
	System.out.println("Student ---- init()");
}
public void destroy(){
	System.out.println("Student ---- destroy");
}

application.xml 配置文件中添加如下内容

<bean id="student2" class="com.imok.pojo.Student" scope="singleton" lazy-init="true" init-method="init" destroy-method="destroy"/>
<bean id="student3" class="com.imok.pojo.Student" scope="prototype" />

测试方法类中添加方法:

@Test
public void Test2(){
	String springConfig = "application.xml";
	ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(springConfig);

	Student student1 = (Student) applicationContext.getBean("student2");
	Student student11 = (Student) applicationContext.getBean("student2");
	
	System.out.println(student1);
	System.out.println(student11);

	Student student2 = (Student) applicationContext.getBean("student3");
	Student student22 = (Student) applicationContext.getBean("student3");
	
	System.out.println(student2);
	System.out.println(student22);
    applicationContext.close();//关闭容器
}

执行结果:

在这里插入图片描述
从图片中可以得出一些信息:

一:
在获取容器中的对象时,默认构造方法会自动执行
但是初始化方法是否紧随其后执行,还是在调用实体类(调用实体类的toString方法)时才会初始化?于是我修改了该测试方法:

applicationContext.getBean("student2");
System.out.println(1);
System.out.println(student1);
System.out.println(1);

即在获取对象后打印数字 1 ,并在调用实体类(调用实体类的toString方法)后又打印数字 1,执行结果是:
在这里插入图片描述
使用可以得出结论,初始化方法是紧随在构造方法之后执行的,而且从执行结果中可以看出,初始化方法与销毁方法只执行一次

二:
通过对比图中获取实体类的 toString 方法,student1 和 student11 的执行结果相同(内存地址?),而 student2 和 student22 的执行结果却不相同。
这是因为对应 student1 和 student11 的 bean 中定义了该语句:

scope="singleton"

而对应 student2 和 student22 的 bean 中定义的是

scope="prototype"

所以才会出现不同的结果。

结语

以上内容是我整合自己的笔记写出来的,如果有错请帮忙指出来谢谢,最后,希望对各位有所帮助

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值