Spring核心-1基础

简介

Spring是为了解决企业级应用开发的复杂性而创建的,Spring不仅仅局限于服务器端开发,任何Java应用都能在简单性、可测试性和松耦合等方面从Spring中获益。

为了降低Java开发的复杂性,Spring采取了以下4种关键策略:

  1. 基于POJO的轻量级和最小侵入性编程;
  2. 通过依赖注入和面向接口实现松耦合;
  3. 基于切面和惯例进行声明式编程;
  4. 通过切面和模板减少样板式代码;

依赖注入DI

依赖注入DI 由 Spring核心容器 模块的 bean 工厂提供。
耦合的两面性:

  • 紧密耦合的代码难以测试、难以复用、难以理解,并且容易出现“打地鼠”式的BUG;
  • 为了完成有实际意义的功能,代码的耦合又难以避免;

DI所带来的最大收益——松耦合

如果一个对象只通过接口(而不是具体实现或初始化过程)来表明依赖关系,那么这种依赖就能够在对象本身毫不知情的情况下,用不同的具体实现进行替换。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.y</groupId>
	<artifactId>gui</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>gui</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.83-jdsec.rc1</version>
		</dependency>

		<dependency>
			<groupId>com.google.guava</groupId>
			<artifactId>guava</artifactId>
			<version>19.0</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.14</version>
			<scope>compile</scope>
		</dependency>
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
    </dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>


package com.y.gui.spring.util;

public class StringUtil {
    /**
     * @param color  颜色代号:背景颜色代号(41-46);前景色代号(31-36)
     * @param type    样式代号:0无;1加粗;3斜体;4下划线
     * @param content 要打印的内容
     */
    public static String getFormatLogString(String content, int color, int type) {
        boolean hasType = type != 1 && type != 3 && type != 4;
        if (hasType) {
            return String.format("\033[%dm%s\033[0m", color, content);
        } else {
            return String.format("\033[%d;%dm%s\033[0m", color, type, content);
        }
    }
}
package com.y.gui.spring;

/**
 * 探险
 */
public interface Quest {
    /**
     * 探险方法
     */
    void embark();
}
package com.y.gui.spring.impl;

import com.y.gui.spring.Quest;
import com.y.gui.spring.util.StringUtil;

import java.io.PrintStream;

/**
 * 探险实现类
 */
public class SlayDragonQuest implements Quest {
    private PrintStream stream;

    public SlayDragonQuest(PrintStream stream) {
        this.stream = stream;
    }

    @Override
    public void embark() {
        String content = "SlayDragonQuest.emark";
        stream.println(StringUtil.getFormatLogString(content, 31, 1));
    }
}
package com.y.gui.spring;

/**
 * 骑士
 */
public interface Knight {
    void embarkOnQuest();
}
package com.y.gui.spring.impl;

import com.y.gui.spring.Knight;
import com.y.gui.spring.Quest;

/**
 * 骑士实现类
 */
public class BraveKnight implements Knight {
    private Quest quest;

    public BraveKnight(Quest quest) {
        this.quest = quest;
    }

    @Override
    public void embarkOnQuest() {
        quest.embark();
    }
}

基于XML配置的DI实现

#{}:Spring表达式语言(Spring Expression Language)

<?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
                           http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="knight" class="com.y.gui.spring.impl.BraveKnight">
        <constructor-arg ref="quest"/>
    </bean>

    <bean id="quest" class="com.y.gui.spring.impl.SlayDragonQuest">
        <constructor-arg value="#{T(System).out}"/>
    </bean>
    
</beans>

基于Java配置的DI实现

package com.y.gui.spring.config;

import com.y.gui.spring.Knight;
import com.y.gui.spring.Quest;
import com.y.gui.spring.impl.BraveKnight;
import com.y.gui.spring.impl.SlayDragonQuest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class KnightConfig {
    @Bean
    public Knight knight() {
        return new BraveKnight(quest());
    }
    
    @Bean
    public Quest quest() {
        return new SlayDragonQuest(System.out);
    }
}

基于XML配置的运行

spring.xml在项目中的路径:resources/static/spring.xml

package com.y.gui.spring.run;

import com.y.gui.spring.Knight;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class KnightXmlMain {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("static/spring.xml");
        Knight knight = context.getBean(Knight.class);
        knight.embarkOnQuest();
        context.close();
    }
}

运行结果

18:07:42.633 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7c53a9eb
18:07:43.061 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 2 bean definitions from class path resource [static/spring.xml]
18:07:43.249 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'knight'
18:07:43.293 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'quest'
SlayDragonQuest.emark
18:07:43.475 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@7c53a9eb, started on Tue Oct 10 18:07:42 CST 2023

基于Java配置的运行

package com.y.gui.spring.run;

import com.y.gui.spring.Knight;
import com.y.gui.spring.config.KnightConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class KnightJavaMain {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(KnightConfig.class);
        Knight knight = context.getBean(Knight.class);
        knight.embarkOnQuest();
        context.close();
    }
}

运行结果

18:25:51.456 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@77556fd
18:25:51.483 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
18:25:51.689 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
18:25:51.690 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
18:25:51.694 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
18:25:51.695 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
18:25:51.697 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'knightConfig'
18:25:51.712 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'knight'
18:25:51.732 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'quest'
SlayDragonQuest.emark
18:25:51.782 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@77556fd, started on Tue Oct 10 18:25:51 CST 2023

切面

DI能够让相互协作的软件组件保持松散耦合,而面向切面编程(aspect-oriented programming, AOP)允许把遍布应用各处的功能分离出来形成可重用的组件。

package com.y.gui.spring.aop;

import com.y.gui.spring.util.StringUtil;

import java.io.PrintStream;

public class Minstrel {
    private PrintStream stream;

    public Minstrel(PrintStream stream) {
        this.stream = stream;
    }

    public void singBeforeQuest() {
        stream.println(StringUtil.getFormatLogString("Minstrel.singBeforeQuest", 32, 1));
    }

    public void singAfterQuest() {
        stream.println(StringUtil.getFormatLogString("Minstrel.singAfterQuest", 33, 1));
    }
}
<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

    <bean id="knight" class="com.y.gui.spring.impl.BraveKnight">
        <constructor-arg ref="quest"/>
    </bean>

    <bean id="quest" class="com.y.gui.spring.impl.SlayDragonQuest">
        <constructor-arg value="#{T(System).out}"/>
    </bean>

    <bean id="minstrel" class="com.y.gui.spring.aop.Minstrel">
        <constructor-arg value="#{T(System).out}"/>
    </bean>

    <aop:config>
        <aop:aspect ref="minstrel">
            <aop:pointcut id="embark" expression="execution(* *.embarkOnQuest(..))"/>
            <aop:before method="singBeforeQuest" pointcut-ref="embark"/>
            <aop:after method="singAfterQuest" pointcut-ref="embark"/>
        </aop:aspect>
    </aop:config>
</beans>

运行结果

15:50:19.304 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@ed17bee
15:50:19.654 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 7 bean definitions from class path resource [static/spring.xml]
15:50:19.780 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.aop.config.internalAutoProxyCreator'
15:50:19.927 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'knight'
15:50:19.927 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.aop.aspectj.AspectJPointcutAdvisor#0'
15:50:20.126 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.aop.aspectj.AspectJPointcutAdvisor#1'
15:50:20.142 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'quest'
15:50:20.225 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'minstrel'
Minstrel.singBeforeQuest
SlayDragonQuest.emark
Minstrel.singAfterQuest
15:50:20.258 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@ed17bee, started on Wed Oct 11 15:50:19 CST 2023

Bean

容器是Spring框架的核心。Spring容器使用DI管理构成应用的组件,它会创建相互协作的组件之间的关联。

Spring容器不止有一个。Spring自带了多个容器实现,可以归为两种不同的类型:

  • bean工厂(由org.springframework.beans.factory.BeanFactory接口定义)是最简单的窗口,提供基本的DI支持;
  • 应用上下文(由org.springframework.context.ApplicationContext接口定义)基于BeanFactory构建,并提供应用框架级别的服务,例如从属性文件解析文本信息以及发布应用事件给感兴趣的事件监听者;

虽然我们可以在bean工厂和应用上下文之间任选一种,但bean工厂对大多数应用来说往往太低级了,因此,应用上下文要比bean工厂更受欢迎。

应用上下文

AnnotationConfigApplicationContext

从一个或多个基于Java的配置类中加载Spring应用上下文

ApplicationContext context = new AnnotationConfigApplicationContext(KnightConfig.class);

AnnotationConfigWebApplicationContext

从一个或多个基于Java的配置类中加载SpringWeb应用上下文

ClassPathXmlApplicationContext

从类路径下(包含JAR文件)的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类资源

ApplicationContext context = new ClassPathXmlApplicationContext(“static/spring.xml”);

FileSystemXmlApplicationContext

从文件系统下的一个或多个XML配置文件中加载上下文定义

ApplicationContext context = new FileSystemXmlApplicationContext(“d:/spring.xml”);

XmlWebApplicationContext

从Web应用下的一个或多个XML配置文件中加载上下文定义

bean的生命周期

bean生命周期

Spring模块

Spring框架的六个模块分类
Spring框架的6个模块分类

Spring 核心容器

容器是 Spring 框架最核心的部分,它管理着 Spring 应用中 bean 的创建、配置和管理。在该模块中,包括了 Spring bean 工厂,它为 Spring 提供了 DI 的功能。基于 bean 工厂,我们还会发现多种Spring 应用上下文的实现,每种都提供了配置 Spring 的不同方式。

Spring 的 AOP 模块

在 AOP 模块中,Spring 对面向切面编程提供了丰富的支持。这个模块是 Spring 应用系统中开发切面的基础。与 DI 一样,AOP 可以帮助应用对象解耦。借助于 AOP,可以将遍布系统的关注点从它们所应用的对象中解耦出来。

数据访问与集成

使用JDBC编写代码通常会导致大量的样板式代码,如获得数据库连接、创建语句、处理结果集、关闭数据库连接。
Spring 的 JDBC 和 DAO(Data Access Object) 模块抽象了这些样板式代码。该模块在多种数据库服务的错误信息之上构建了一个语义丰富的异常层,使得我们不必再解释那些隐晦专有的 SQL 错误信息了。
本模块同样包含了在 JMS(Java Message Service) 之上构建的 Spring 抽象层,它会使用消息以异步的方式与其他应用集成。本模块还包含对象到 XML 映射的特性,它最初是 Spring Web Service 项目的一部分。
除此之外,本模块会使用 SpringAOP 模块为 Spring 应用中的对象提供事务管理服务。

Web 与远程调用

MVC(Model-View-Controller) 模式是一种普遍被接受的构建 Web 应用的方法,它可以帮助用户将界面逻辑与应用逻辑分离。
虽然 Spring 能够与多种流行的 MVC 框架进行集成,但它的 Web 和远程调用模块自带了一个强大的 MVC 框架,有助于在 Web 层提升应用的松耦合水平。
除了面向用户的 Web 应用,该模块还提供了多种构建与其他应用交互的远程调用方案。Spring 远程调用功能集成了 RMI(Renite Netgid Ubvicatuib)、Hessian、Burlap、JAX-WS,同时 Spring 还自带了一个远程调用框架:HTTP invoker。Spring 还提供了暴露和使用 REST API 的良好支持。

Instrumentation

Spring 的 Instrumentation 模块提供了为 JVM 添加代理(agent)的功能。具体来讲,它为 Tomcat 提供了一个织入代理,能够为 Tomcat 传递类文件,就像这些文件是被类加载器加载的一样。

测试

Spring 提供了测试模块以致力于 Spring 应用的测试。Spring 为使用 JNDI、Servlet 和 Portlet 编写单元测试提供了一系列的 mock 对象实现。
对于集成测试,该模块为加载 Spring 应用上下文中的 bean 集合以及与 Spring 上下文中的 bean 进行交互提供了支持。

Spring Portfolio

整个 Spring Portfolio 包括多个构建于核心 Spring 框架之上的框架和类库。概括地讲,整个 Spring Portfolio 几乎为每一个领域的 Java 开发都提供了 Spring 编程模型。

Spring Web Flow

Spring Web Flow 建立于 Spring MVC 框架之上,它为基于流程的会话式 Web 应用(购物车或者向导功能)提供了支持。
Spring Web Flow 的主页

Spring Web Service

虽然核心的 Spring 框架提供了将 Spring bean 以声明的方式发布为 Web Service 的功能,但是这些服务是基于一个具有争议性的架构(拙劣的契约后置模型)之上而构建的。这些服务的契约由 bean 的接口来决定。Spring Web Service 提供了契约优先的 Web Service 模型,服务的实现都是为了满足服务的契约而编写的。
Spring Web Service 站点

Spring Security

安全对于许多应用都是一个非常关键的切面。利用 Spring AOP,Spring Security 为 Spring 应用提供了声明式的安全机制。
Spring Security 的主页

Spring Integration

许多企业级应用都需要与其他应用进行交互。Spring Integration 提供了多种通用应用集成模式的 Spring 声明式风格实现。
Spring Integration 的主页
相关书籍:《Spring Integration in Action》(Manning, 2012, www.manning.com/fisher/)
Mark FisherJonas PartnerMarius BogoeviciIwein Fuld

Spring Batch

当需要对数据进行大量操作时,没有任何技术可以比批处理更胜任这种场景。
如果需要开发一个批处理应用,可以通过 Spring Batch ,使用 Spring 强大的面向 POJO 的编程模型。
Spring Batch 的主页
相关书籍:《Spring Batch in Action》(Manning, 2012, www.manning.com/templier/)
Arnaud CogoluegnesThierry TemplierGary GregoryOlivier Bazoud

Spring Data

Spring Data 使得在 Spring 中使用任何数据库都变得非常容易。
甚至包括NoSQL数据库,如文档数据库 MongoDB,图数据库 Neo4j 等。
Spring Data 为持久化提供了一种简单的编程模型,这包括为多种数据库类型提供了一种自动化的 Repository 机制,它负责为你创建 Repository 的实现。

Spring Social

Spring Social 是 Spring 的一个社交网络扩展模块。
Spring Social 更多的是关注连接(connect),而不是社交(social)。
它能够帮助你通过 REST API 连接 Spring 应用,其中有些 Spring 应用可能原本并没有任何社交方面的功能目标。
Spring Social 如果帮助你链接 Facebook
Spring Social 如果帮助你链接 Twitter

Spring Mobile

Spring Mobile 是 Spring MVC 新的扩展模块,用于支持移动 Web 应用开发。

Spring for Android

与 Spring Mobile 相关的是 Spring Android 项目。旨在通过 Spring 框架为开发基于 Android 设备的本地应用提供某些简单的支持。最初这个项目提供了 Spring RestTemplate 的一个可以用于 Android 应用之中的版本。它还能与 Spring Social 协作,使得原生应用可以通过 REST API 进行社交网络的连接。
相关资料

Spring Boot

Spring Boog 大量依赖于自动配置技术,它能够消除大部分 Spring 配置。它还提供了多个 Starter 项目,不管你使用 Maven 还是 Gradle,这都能减少 Spring 工程构建 文件的大小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值