java spring框架入门基础教程

对java来说,spring框架一直是不可或缺的一项技术,今天我们就来了解了解它吧。

1. Spring简介

Spring是由Rod Johnson创建的目前java中最流行的开源框架。它的基本功能较为复杂,很难用一句话来概括。Spring家族几乎可以解决我们在开发JavaEE项目中所有的问题,但Spring创建的初衷其实是为了解决企业级应用开发的复杂性,并致力于全方位简化java开发

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

- 基于POJO的轻量级和最小侵入性编程;

- 通过依赖注入和面向接口实现松耦合;

- 基于切面和惯例进行声明式编程;

- 通过切面和模板减少样板式代码。

Spring框架通过依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)2项核心技术,来贯彻和执行上述4项策略。

2. Spring模块和Spring家族

2.1 Spring模块

在spring4.0版本中,共包含20个不同的模块,可以划分为6类不同的功能

1. Spring核心容器:容器是spring框架最核心的部分,管理着Spring应用中bean的创建、配置和管理。

2. Spring的AOP模块:在AOP模块中,Spring对面向切面编程提供了丰富的支持。这个模块是Spring应用系统中开发切面的基础。

3. 数据访问与集成:Spring的JDBC和DAO(Data Access Object)模块抽象了JDBC的样板式代码,使数据库代码更加简单明了。除了JDBC,Spring还提供了对于ORM(Object-Relational Mapping)的支持,可以集成众多流行的ORM框架,包括MyBatis、Hibernate、JPA等。

4. Web与远程调用:可与多种流程的MVC框架集成,同时Spring也自带了一个强大的MVC框架。

5. Instrumentation:该模块提供了为JVM添加代理的功能(较少使用)

6. 测试:致力于Spring应用的测试。

在后续的项目开发中,我们没必要一开始就添加所有的模块,而是根据项目本身功能的需要,来逐步添加所需的Spring模块。

2.2 Spring家族项目

概括地讲,整个Spring家族几乎为每一个领域的Java开发都提供了Spring编程模型,在Spring官网上可以看到除开核心框架之外的一些项目:

Spring Boot 可以使得我们更简便和快速的构建Spring应用

Spring Cloud Spring微服务

Spring Data 方便在Spring中使用任何数据库

Spring Security 安全框架

3. Helloworld

3.1 现有Java程序容易产生的诟病

在使用Spring之前,让我们先来看一份简单的Java程序清单:

//用来封装针孔打印机类型
public class PinPrinter
{
    public void print()
    {
        System.out.println("使用针孔打印机进行打印");
    }
}
//用来封装激光打印机类型
public class LaserPrinter
{
    public void print()
    {
        System.out.println("使用激光打印机进行打印");
    }
}
//用来封装打印店,提供打印服务
public class PrintHouse
{
    private PinPrinter printer; // 1-依赖
    public void service()
    {
        printer = new PinPrinter(); // 2-硬编码造成高耦合
        printer.print();
    }
}

如上代码所述,任何一个有意义的应用,都会由两个或者更多的类组成,这些类相互之间进行协作来完成特定的业务逻辑。按照传统的做法,每个对象负责管理与自己相互协作的对象的引用(即它所依赖的对象),这将会导致高度耦合和难以测试的代码。

从以上代码,我们来理解一下耦合(代码关联)的两面性:

- 一方面,一定程度的耦合是必须的,完全没有耦合的代码什么都做不了。在代码1处,PrintHouse如果不借助PinPrinter类,就无法提供打印功能。

- 另一方面,紧密耦合的代码难以测试、难以复用。为何这么说呢?在代码2处,由于自行创建了PinPrinter实例,导致PrintHouse和PinPrinter紧密的耦合在了一起,这虽然满足了用户的需求,但在一定程度上也限制了PrintHouse提供更为丰富灵活的功能,比如,万一用户要使用激光打印的话,那么现在PrintHouse如果不修改代码是满足不了需求的。

3.2 使用Spring简化

首先,创建maven项目,并引入Spring类库。

pom.xml

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

打开pom的依赖树状结构图我们可以看到如下关系:

java spring框架 入门

==spring-context==这个模块,依赖了spring-aop,spring-beans,spring-core,spring-expression这样一些模块,借助maven的类库依赖管理,这些jar都会一并导入到项目中来,而其中前三个模块,就包含和提供了我们在开篇所提到的spring所具备的两项核心技术:依赖注入DI和面向切面编程AOP。在普通的非web应用中,我们一般只需要引入spring-context这个模块就可以满足基本需求了。

然后,根据之前的功能描述,我们可以从针孔打印机和激光打印机中,把print这个方法单独抽取出来封装为一个接口(抽象类也可以)

public interface Printer {
void print();
}
public class LaserPrinter implements Printer {
public void print() {
System.out.println("使用激光打印机进行打印");
}
}
public class PinPrinter implements Printer {
public void print() {
System.out.println("使用针孔打印机进行打印");
}
}
public class PrintHouse {
private Printer printer;
//声明setter,放遍spring进行属性注入
public void setPrinter(Printer printer) {
this.printer = printer;
}
public void service() {
printer.print();
}
}

最后,以xml配置的方式来声明和装配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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--声明要使用的bean-->
<bean id="house" class="com.turing.context.PrintHouse">
        <!--属性注入-->
<property name="printer" ref="pinPrinter"></property>
</bean>
    
<bean id="pinPrinter" class="com.turing.context.PinPrinter"></bean>
<bean id="laserPrinter" class="com.turing.context.LaserPrinter"></bean>
</beans>

测试代码:

public static void main(String[] args) {
// 创建spring容器
ClassPathXmlApplicationContext ctx = new 
ClassPathXmlApplicationContext("com/turing/context/spring.xml");
// 根据id从spring中获取对应的bean的实例
PrintHouse house = (PrintHouse) ctx.getBean("house");
house.service();
// 关闭容器
ctx.close();
}

从上述代码中,我们一起来看看这个一个spring应用中到底发生了什么:

1. 通过读取配置文件信息,我们首先创建了spring容器,容器是spring框架一个非常重要的组件,它不光创建各个不同的bean(通过bean节点声明)还会创建相互协作的bean之间的关联(通过property节点进行属性的装配)

2. 我们可以从容器中根据bean的id来获取bean的实例,调用bean的方法

3. 最后使用完毕后,通过close方法进行容器销毁。

在基于spring的应用中,对象都是生存于容器(`container`)中,spring容器负责创建对象、装配它们,配置它们并管理它们的整个生命周期,从生存到死亡(从`new`到`finalize()`)。

上述配置中,我们只需要稍稍修改配置文件,就可以让PrintHouse使用激光打印服务了:

<bean id="house" class="com.turing.context.PrintHouse">
    <property name="printer" ref="laserPrinter"></property>
</bean>

而使用spring的最大好处在于,虽然切换了打印机的实现,但是对于java代码而言是无需修改的。

4. 装配Bean

spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系,但是,我们还是需要告诉spring要创建哪些bean并且如何将其装配在一起。spring具有非常大的灵活性,它提供了三种主要的装配机制:

- 基于Xml的显式配置

- 基于Java的显式配置

- 自动化配置

 4.1 基于Xml的显式配置

在上述Helloworld中,我们就是使用了xml配置文件进行装配,具体使用了属性的setter方法,接下来我们再补充另一种构造器注入的方式

<bean id="house" class="com.turing.wire1.PrintHouse">
    <constructor-arg index="0" ref="pinPrinter"></constructor-arg>
</bean>
public class PrintHouse
{
    private Printer printer;
    public PrintHouse(Printer printer)
    {
        this.printer = printer;
    }
    public void service()
    {
        printer.print();
    }
}

4.2 基于Java的显式配置

在使用Java代码进行配置的时候,实际上是使用一个Java类来代替原先的spring.xml

@Configuration //代表这是一个spring配置类
public class BeanConfig
{
    @Bean
    // 默认bean的id就是方法名
    // 可以通过name进行修改
    public PinPrinter pinPrinter()
    {
        return new PinPrinter();
    }
    @Bean
    public LaserPrinter laserPrinter()
    {
        return new LaserPrinter();
    }
    @Bean
    public PrintHouse printHouse(LaserPrinter printer)
    {
        return new PrintHouse(printer);
    }
    @Bean
    public PrintHouse printHouseOther(PinPrinter printer)
    {
        return new PrintHouse(printer);
    }
    public static void main(String[] args)
    {
        AnnotationConfigApplicationContext ctx = new
        AnnotationConfigApplicationContext(BeanConfig.class);
        PrintHouse house = (PrintHouse) ctx.getBean("printHouse");
        house.service();
        ctx.close();
    }
}

 4.3 自动化配置

使用@Component、@ComponentScan、@Autowired进行自动装配:

@Component
public class LaserPrinter implements Printer
{
    public void print()
    {
        System.out.println("使用激光打印机进行打印");
    }
}
@Component
public class PinPrinter implements Printer
{
    public void print()
    {
        System.out.println("使用针孔打印机进行打印");
    }
}
@Component
public class PrintHouse
{
    @Autowired //自动装配
    @Qualifier("laserPrinter") //当有两个以上的bean满足时,通过该注解进行区分
    private Printer printer;
    public void service()
    {
        printer.print();
    }
}
@Configuration
@ComponentScan
public class Test
{
    public static void main(String[] args)
    {
        AnnotationConfigApplicationContext ctx = new
        AnnotationConfigApplicationContext(Test.class);
        PrintHouse house = (PrintHouse) ctx.getBean("printHouse");
        house.service();
        ctx.close();
    }
}

- @Component用来声明哪些bean需要由spring容器进行管理

- @ComponentScan用来对声明了@Component的类启用组件扫描,spring将会扫描==这个包以及这个包下的所有子包==

- @Autowired实现自动装配

在上述用例中,我们看到了Spring中装配Bean的三种主要方式:自动化配置、基于Java的显式配置以及基于Xml的显式配置。不管采用什么方式,这些技术都描述了Spring应用中的组件以及这些组件之间的关系。同时,建议尽可能使用自动化配置,以避免显式配置所带来的维护成本。从选择配置方式的优先级来看,建议按照以下顺序:==自动化配置-->基于Java的显式配置-->基于Xml的显式配置==。

以上就是关于Spring入门教程的所有内容,更多java基础教程内容请一定记得关注本站了解详情。

推荐阅读:

spring实现session共享,如何进行Session共享?

spring ioc注解,常用注解大全

spring ioc注入方式有几种?该怎么实现?