Spring入门

这篇博客介绍了Spring框架的基础知识,包括Spring的概述、体系结构、核心功能及其优势。讲解了Spring的控制反转(IoC)和面向切面编程(AOP)的概念。接着,通过创建Web工程、配置依赖和编写测试代码,详细展示了Spring工程的搭建步骤,帮助读者理解Spring如何简化项目开发和提高代码的可扩展性。

1 Spring 简介

1.1 Spring 概述

官网定义:
Spring 框架为任何类型的部署平台上的基于 Java 的现代企业应用程序提供了全面的编程和配置模型。

Spring 的一个关键元素是在应用程序级别的基础架构支持:Spring 专注于企业应用程序的 “管道”,以便团队可以专注于应用程序级别的业务逻辑,而不必与特定的部署环境建立不必要的联系。

慕课解释:
简单来说:Spring 是一个免费开源框架,为了简化企业级项目开发,提供全面的开发部署解决方案。

1.2 Spring 的体系结构

在这里插入图片描述

结构图解析:

  • 左上角为负责持久层的部分,是 Spring 对数据持久化,事务管理,支持的功能框架。大家听过的 SpringDataJpa 就是其中的一种;
  • 右上角为负责表现层的部分,是 Spring 对于表现层数据的处理部分的支持,比如:大家听说过的 SpirngMVC 就是其中的一种;
  • 最底部的负责测试的部分,Spring 对于项目的测试提供了完整的一个测试环境支持;
  • 中间的两部分就是俗称的 Spring 框架。

1.3 Spring 的核心功能

  • 控制反转(IoC): 简单理解 IoC 是一种设计模式,将实例化对象的控制权 由手动的 new 变成了 Spring 框架通过反射机制实例化;
  • 依赖注入(DI): 首先理解依赖,程序运行的需要可以称之为依赖。由于 Spring 框架通过反射技术实例化了对象,并将对象的实例存入在容器进行管理。那么如果一个类中的属性为某个其余的类,属性无需手动赋值,通过 spring 的配置文件,或者 Spring 提供的注解,通过 spring 框架可以实现直接注入属性;
  • 面向切面编程 (AOP): 何谓切面,切面是数学中的一个概念,表示只有一个点接触到球体的一个平面称呼为切面,而接触点称呼为切点。那么在 Spring 中,切面编程指的就是在程序运行某个方法的时候,不修改原始执行代码逻辑,由程序动态地执行某些额外的功能,对原有的方法做增强,这就叫做面向切面编程,那个被监测的执行方法,称呼为切入点。

知识小结:
Spring 是分层的 Java SE/EE 应用 轻量级开源框架,以 IoC(Inverse of Control:控制反转)和 AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 Spring MVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多 著名的第三方框架和类库, 是使用最多的 Java EE 企业应用开源框架。

使用 Spring 的意义在于:对于 bean 对象的实例管理更加方便,代码编写更加优雅,降低代码的耦合性,提升代码的扩展性。

1.4 Spring 的优势

  • 简化项目开发 : Spring 灵活全面的扩展功能,使我们开发项目如鱼得水 。通过 Spring 提供的 IoC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用;
  • 面向切面编程 :Spirng 框架的 AOP 面向切面编程,极大地提高了程序的扩展性,支持开发人员实现对程序的自定义增强。同时可以方便地使用 Spring 提供的事务管理;
  • 面向接口编程: 面向接口编程 降低代码的耦合性,同时也提高了代码的扩展性;
  • 测试方便:对于测试的支持 有很多的组件实现;
  • 方便集成第三方框架:Spring 可以降低各种框架的使用难度,提供了对各种优秀框架(Struts、Hibernate、Hessian、Quartz 等)的直接支持。

2 Spring 工程的搭建

2.1 Spring 框架源码下载

下载方式:
a.下载源码文件
Spring 的源码下载地址 :
https://github.com/spring-projects/spring-framework/releases

b.第二种是使用 maven 的坐标方式
在实际开发中,通常使用这种方式引入spring框架,maven 的 pom 文件坐标如下。

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>5.2.2.RELEASE</version>
</dependency>

2.2 使用 IDEA 创建 Web 工程

开发工具选择 idea ,创建 Maven 的 jar 工程即可。因为涉及不到浏览器的请求,所以无需创建 web 工程。
创建 Maven 工程 :
在这里插入图片描述
补全坐标信息:
在这里插入图片描述
继续下一步 finish 完成创建即可

2.3 引入项目使用的坐标依赖

将准备好的坐标信息粘贴到工程下的 pom 文件中,也就是下面的dependencies部分 。
在这里插入图片描述

2.4 编写 Spring 框架使用的配置文件

坐标有了之后,我们的工程中就已经引入了 Spring 框架的依赖,可以点开左侧的 External Libraries 验证一下 。
在这里插入图片描述

看到上面的 jar 包列表,说明 Spring 框架中的基本依赖我们已经成功引入。接下来:既然我们使用的是框架,已经封装好了很多功能提供我们使用,而我们如何让他们工作呢? 这里需要一个和 Spirng 框架通信的桥梁 —Spring 框架的核心配置文件。

Tips:
文件的名称可以随便起,我习惯使用 applicationContext.xml。

文件的位置放在哪里呢? maven 工程需要放在 src 的 resources 下面,如下图:
在这里插入图片描述
配置文件是空的,不要着急,如果你下载了源码,那么打开 docs\spring-framework-reference 目录,打开 core.html 查看官方文档可以看到如下配置内容:

 <?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">
       <!-- beans definitions here-->
</beans>

将上面的实例配置信息拷贝到我们的配置文件中,它只是给了最基本的配置头信息,内容部分、针对 bean 做初始化的部分需要我们自行填充。

3 编写代码测试

3.1 编写接口和接口的实现类

代码如下:

//接口的代码
public interface UserService {
    public void saveUser();
}
//实现类的代码
public class UserServiceImpl implements UserService {
    public void saveUser() {
        System.out.println("UserService的保存方法已执行");
    }
}

3.2 补充 Spring 的配置文件

配置文件的目的是将我们自定义的实现类交给 Spring 的容器管理。因为 Spring 框架核心功能之一就是 IoC 控制反转,目的是将对象实例化的动作交给容器。最终 Spring 的配置文件如下:

<?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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">

    <!-- 此标签的作用 是实例化UserServiceImpl类的实例 交给 Spring 容器 -->
    <bean id="userService" class="com.wyan.service.impl.UserServiceImpl"></bean>
</beans>

3.3 测试结果

从容器中获取对象实例,调用提供的方法

public class DemoTest {
    public static void main(String[] args) {
        ApplicationContext context = 
                new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserService service = (UserService) context.getBean("userService");
        service.saveUser();
    }
}

代码解析:
ApplicationContext 是 Spring 框架提供的一个接口,目前只需要知道它是作为存储实例化 bean 对象的容器即可。

context.getBean () 方法是通过配置文件中声明的 bean 标签 id 属性获取容器内的实例。

最终结果:
在这里插入图片描述
结果证明确实从容器中获取到了 userService 的实例。

3 Spring 工程执行过程

3.1 容器初始化

回顾代码:

public static void main(String[] args) {
    ApplicationContext context =
            new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    UserService service = (UserService) context.getBean("userService");
    service.saveUser();
}

由上面的代码中可知 Spring 的容器是 ApplicationContext,那么它到底是什么东西呢?先跟我一起追踪一下它的角色。

官方文档:
在这里插入图片描述
慕课解释:
简单翻译过来就是 ApplicationContext 是一个接口,是 BeanFactory 这个接口的子接口,它扩展了 BeanFactory 这个接口,提供了额外附加的功能。

而 BeanFactory 是管理 bean 对象的容器的根接口,大家了解下就好,我们是针对它的子接口 ClassPathXmlApplicationContext 做的实例化,目的是加载项目中的 Spring 的配置文件,使 Spring 来管理我们定义的 bean 对象。

疑问导出
那么ClassPathXmlApplicationContext 对象实例化之后,干了哪些事情呢?

3.2 容器初始化执行动作

applicationContext 实例化执行代码逻辑 。
我们追踪下源码,发现 ClassPathXmlApplicationContext 初始化的时候,它做了一系列的事情。源码如下:
在这里插入图片描述
代码解析:

  • 位置1初始化 ClassPathXmlApplicationContext 对象执行的有参构造;
  • 位置2加载项目下的 xml 配置文件;
  • 位置3调用 refresh 刷新容器的方法,bean 的实例化就在这个方法中。

继续跟踪:

3.3 容器初始化 bean 对象动作

下面是从源码中粘贴的部分代码
在这里插入图片描述
步骤阐述:

  • 位置1:准备刷新, Spring 只是设置刷新的标记,加载了外部的 properties 属性文件;
  • 位置2:准备 bean 工厂对象;
  • 位置3:加载配置文件中的所有 bean 标签,但是并没有对他们进行实例化;
  • 位置4:完成此上下文的 bean 工厂的初始化,初始化所有剩余的单例 bean。(Spring 中默认加载的 bean 就是单例模式)
  • 最后的位置:完成容器的刷新,也就是所有的 bean 初始化完成。

以上就是加载配置文件后 Spring 框架做的所有事情,当然实际底层涉及的东西更多,但是我们没有必要深究,毕竟我们是理解过程,不是追求实现。

疑问导出:
我们整理了 Spring 初始化 bean 对象的过程,那么如果容器中确实存在了 bean 的实例,我们是如何获取得到的呢?

3.4 容器中获取对象的过程

还是先看下我们获取容器对象的代码:

public static void main(String[] args) {
    ApplicationContext context =
            new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    UserService service = (UserService) context.getBean("userService");
    service.saveUser();
}

代码分析:
context.getBean 的方法是通过 bean 标签里的 id 来从容器中获取,那么我们看下源码 :
在父类 AbstractApplicationContext 中有对 getBean 方法的实现。

@Override
public Object getBean(String name) throws BeansException {
	assertBeanFactoryActive();
	return getBeanFactory().getBean(name);
}

追踪父类方法
最终通过我们层层追踪,我们在 AbstractAutowireCapableBeanFactory 中发现这样的一段代码:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {
		//...
		//省略大量方法内部代码
        //...
		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
            //给实例中的属性赋值
			populateBean(beanName, mbd, instanceWrapper);
            //真实实例化对象
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		//...
        //继续省略大量方法
        //...
		// Register bean as disposable.
		try {
            //将实例化后的对象放入容器中
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}
		//返回实例化后的对象实例
		return exposedObject;
	}

上面源码中: 对象实例的获取好像是在获取的时候执行的 doCreateBean,那么之前记载的 xml 文件不是实例过了吗?稍微解释下:加载文件时候的实例化操作,其实是实例化了一个 Spring 框架提供的对象,作用是对于我们 bean 对象做描述,这里才是真实的实例化动作。我们再看看 registerDisposableBeanIfNecessary 这个方法做的是什么。

public void registerDisposableBean(String beanName, DisposableBean bean) {
		synchronized (this.disposableBeans) {
			this.disposableBeans.put(beanName, bean);
		}
	}

结论
一切真相大白。它其实就是一个 map 集合 ,这个 map 集合的 key 就是我们定义的 bean 的 id 或者 bean 的 name ,那么值就是对象的实例。

3.5 小结

  • Spring 框架通过 ResourceLoader 加载项目的 xml 配置文件;
  • 读取 xml 的配置信息 变成对象存储,但未实例化;
  • 通过 bean 工厂处理器对 bean 做实例化,存储到一个 map 集合中,默认是单例;
  • 实例对象通过 xml 文件中 bean 的 id 从 map 集合中通过 get (key) 获取。

ps:以上内容来自对慕课教程的学习与总结。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值