Spring快速入门

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: Spring快速入门

引言

最近几天一直在忙着学习数据结构和算法,关于JavaEE的框架也有一阵子没更新了。那么今天就来聊一聊Spring框架吧,针对该框架写一篇快速入门的文章。

Spring简介

Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。

  • 目的:解决企业应用开发的复杂性
  • 功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
  • 范围:任何Java应用

Spring是一个轻量级控制反转(IOC)和面向切面(AOP)的容器框架。

配置Bean

首先来说一说在Spring框架中如何去配置Bean。
通过一个简单案例感受一下:
首先得导入Spring框架的jar包,然后创建一个类:

package com.itcast.spring.bean;

public class HelloWorld {
   

    private String name;

    public void setName(String name) {
   
        this.name = name;
    }

    public String getName() {
   
        return name;
    }

    public void hello() {
   
        System.out.println("hello:" + name);
    }
}

在传统的写法中,我们要想调用HelloWorld类的hello()方法,我们需要手动创建HelloWorld的实例,然后调用setName()方法给name赋值,接着调用hello()方法。但是有了Spring框架之后,对于对象的创建和属性的赋值都不需要我们操心,框架能够帮助我们完成。所以接下来创建Spring框架的配置文件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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="helloWorld" class="com.itcast.spring.bean.HelloWorld">
        <property name="name" value="Spring"></property>
    </bean>

</beans>

对于这段简单的配置,可以解释一下。bean是beans下的一个子节点,配置的是一个bean类的信息,然后是bean节点下的属性:

  • id:标识容器中的bean,id是唯一的
  • class:bean的全类名,因为框架是通过反射的方式在IOC容器中创建bean的实例,所以你需要提供类的全路径,这在很多框架中都能得到体现

然后是property,该节点配置的是bean类中的属性信息,name即为属性名,但是需要注意的是,这个name值是根据setXXX()方法进行匹配的,如果没有setXXX()方法或者setXXX()方法和类中的属性名不一致,将会导致异常产生。而value就是属性的值。
配置好后,我们编写测试代码:

public static void main(String[] args) {
   
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");
        helloWorld.hello();
}

首先通过ClassPathXmlApplicationContext去构造ApplicationContext 对象,传入配置文件名,接着通过getBean()方法得到HelloWorld实例,传入的是在配置文件中bean的id属性值。
运行结果:

hello:Spring

需要注意的是,在bean类中你必须提供一个无参的构造方法,因为反射的实现需要无参构造。
到这里,一个入门的Spring案例就完成了。

Spring容器

接下来,我们细细地研究一下。
在SpringIOC容器读取bean配置创建bean实例之前,必须对它进行实例化,只有在容器实例化后,才可以从IOC容器中获取bean实例并使用。
在Spring中提供了两种类型的IOC容器实现:

  1. BeanFactory:IOC容器的基本实现
    BeanFactory是Spring框架的基础设施,面向Spring本身
  2. ApplicationContext:提供了更多的高级特性,是BeanFactory的子接口
    ApplicationContext面向使用Spring框架的开发者,几乎所有的应用场合都直接使用ApplicationContext而非底层的BeanFactory

但无论使用何种方式,配置文件的写法都是一样的。
ApplicationContext是BeanFactory的子接口,它有两个实现类:

  1. ClassPathXmlApplicationContext:从类路径下加载配置文件
  2. FileSystemXmlApplicationContext:从文件系统中加载配置文件

所以获得ApplicationContext的实例可以有两种方式,刚才的案例中使用的就是第一种方式。

获得了Spring容器后,我们是如何去获得bean实例的呢?
通过getBean()方法:
在这里插入图片描述
可以看到,ApplicationContext提供了多个getBean()方法的重载,所以对于bean实例的获取,除了通过id属性值获取以外,还可以通过bean的类型获取:

public static void main(String[] args) {
   
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        HelloWorld helloWorld = ctx.getBean(HelloWorld.class);
        helloWorld.hello();
}

这样也能获取到bean的实例,而且有一个好处就是不用强制类型转换了。

属性值的注入

在Spring框架中,有两种方式可以对bean类的属性进行赋值:

  1. 属性注入
    属性注入在开始的案例中已经使用到了,就是通过bean节点下的property节点进行注入,它通过setXXX()方法注入属性值,属性注入是实例应用开发中最常用的注入方式
  2. 构造方法注入
    构造方法注入顾名思义就是通过构造方法注入属性值,它通过bean节点下的constructor-arg节点进行注入

对于构造方法注入属性值,有必要单独提取出来讲解一下,我们来看一个案例。
创建一个bean类:

package com.itcast.spring.bean;

public class Car {
   

    private String brand;
    private String corp;
    private double price;
    private int maxSpeed;

    public Car(String brand, String corp, double price) {
   
        super();
        this.brand = brand;
        this.corp = corp;
        this.price = price;
    }

    @Override
    public String toString() {
   
        return "Car [brand=" + brand + ", corp=" + corp + ", price=" + price + ", maxSpeed=" + maxSpeed + "]";
    }
}

然后配置一下:

<?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="car" class="com.itcast.spring.bean.Car">
        <constructor-arg value="Audi"></constructor-arg>
        <constructor-arg value="ShangHai"></constructor-arg>
        <constructor-arg value="250000"></constructor-arg>
    </bean>
</beans>

接下来编写测试代码:

public static void main(String[] args) {
   
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    Car car = (Car) ctx.getBean("car");
    System.out.println(car);
}

运行结果:

Car [brand=Audi, corp=ShangHai, price=250000.0, maxSpeed=0]

因为是通过构造方法注入属性值,所以可以不需要setXXX()方法,从配置中可以知道,属性值是通过配置的顺序进行注入的,那么接下来我们修改一下Car类:

package com.itcast.spring.bean;

public class Car {
   

    private String brand;
    private String corp;
    private double price;
    private int maxSpeed;

    public Car(String brand, String corp, double price) {
   
        super();
        this.brand = brand;
        this.corp = corp;
        this.price = price;
    }

    public Car(String brand, String corp, int maxSpeed) {
   
        super();
        this.brand = brand;
        this.corp = corp;
        this.maxSpeed = maxSpeed;
    }

    @Override
    public String toString() {
   
        return "Car [brand=" + brand + ", corp=" + corp + ", price=" + price + ", maxSpeed=" + maxSpeed + "]";
    }
}

我们在Car类中新增了一个构造方法,然后我们重新配置一下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 id="car2" class="com.itcast.spring.bean.Car">
        <constructor-arg value="BMW"></constructor-arg>
        <constructor-arg value="BeiJing"></constructor-arg>
        <constructor-arg value="240"></constructor-arg>
    </bean>
</beans>

我们想通过这三个属性值来得到一个Car的实例,接下来编写测试代码:

public static void main(String[] args) {
   
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    Car car = (Car) ctx.getBean("car2");
    System.out.println(car);
}

运行结果:

Car [brand=BMW, corp=BeiJing, price=240.0, maxSpeed=0]

问题就出现了,我明明是想通过第二个构造方法构造对象,传入的240是maxSpeed的值,但它仍然使用了第一个构造方法,所以仅仅靠参数顺序来注入是不合理的。
不过不用担心,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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="car2" class="com.itcast.spring.bean.Car">
        <constructor-arg value="BMW" type="java.lang.String"></constructor-arg>
        <constructor-arg value="BeiJing"
            type="java.lang.String"></constructor-arg>
        <constructor-arg value="240" type="int"></constructor-arg>
    </bean>
</beans>

其它地方不用修改,重新运行一下测试代码,结果如下:

Car [brand=BMW, corp=BeiJing, price=0.0, maxSpeed=240]

这样就达到了我们想要的结果。
对于属性值的注入,还可以通过子节点下的value节点进行注入,效果是一样的。

引用类型属性值的注入

对字面值的注入有了一定的了解之后,我们单独看一下引用类型的属性值该如何注入:
先创建一个bean类:

package com.itcast.spring.bean;

public class Person {
   

    private String name;
    private int age;
    private Car car;

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public int getAge() {
   
        return age;
    }

    public void setAge(int age) {
   
        this.age = age;
    }

    public Car getCar() {
   
        return car;
    }

    public void setCar(Car car) {
   
        this.car = car;
    }

    @Override
    public String toString() {
   
        return "Person [name=" + name + ", age=" + age + ", car=" + car + "]";
    }
}

在配置文件中配置一下Person类:

<?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="car2" class="com.itcast.spring.bean.Car">
        <constructor-arg value="BMW" type="java.lang.String"></constructor-arg>
        <constructor-arg value="BeiJing"
            type="java.lang.String"></constructor-arg>
        <constructor-arg value="240" type="int"></constructor-arg>
    </bean>

    <bean id="person" class="com.itcast.spring.bean.Person">
        <property name="name" value="Tony"></property>
        <property name="age" value="18"></property>
        <property name="car" ref="car2"></property>
    </bean>
</beans>

对于引用类型Car,我们可以通过property节点的ref属性指向对car的引用,因为上面我配置了一个id为car2的bean,所以这里直接通过id引用指向它。
编写测试代码:

public static void main(String[] args) {
   
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    Person person = (Person) ctx.getBean("person");
    System.out.println(person);
}

运行效果:

Person [name=Tony, age=18, car=Car [brand=BMW, corp=BeiJing, price=0.0, maxSpeed=240]]

和上面类似,也可以使用子节点ref进行配置。

<bean id="person" class="com.itcast.spring.bean.Person">
        <property name="name" value="Tony"></property>
        <property name="age" value="18"></property>
        <property name="car">
            <ref bean="car2"/>
        </property>
</bean>

我们还可以在属性或构造器里包含一个bean的声明,这样的bean称为内部bean,无法被外部访问。

<bean id="person" class="com.itcast.spring.bean.Person">
        <property name="name" value="Tony"></property>
        <property name="age" value="18"></property>
        <property name="car">
            <bean class="com.itcast.spring.bean.Car">
                <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
                <constructor-arg value="ShangHai" type="java.lang.String"></constructor-arg>
                <constructor-arg value="250000" type="double"></constructor-arg>
            </bean>
        </property>
</bean>

Spring和Struts、Hibernate框架一样,也支持级联属性。所以我们还可以通过级联属性赋值。

<property name="car.price" value="150000"></property>

可以通过这样的方式给Car类的属性赋值。

集合属性值注入

在引用类型中,又有一个特殊的群体,集合。包括Set、List、Map。
修改Person类代码:

package com.itcast.spring.bean;

import java.util.List;

public class Person {
   

    private String name;
    private int age;
    private List<Car> cars;

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public int getAge() {
   
        return age;
    }

    public void setAge(int age) {
   
        this.age = age;
    }

    @Override
    public String toString() {
   
        return "Person [name=" + name + ", age=" + age + ", cars=" + cars + "]";
    }

    public List<Car> getCars() {
   
        return cars;
    }

    public void setCars(List<Car> cars) {
   
        this.cars = cars;
    }
}

其中有一个集合类型Car,该如何在配置文件中进行配置呢?

<?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="car" class="com.itcast.spring.bean.Car">
        <constructor-arg value="Audi"></constructor-arg>
        <constructor-arg value="ShangHai"></constructor-arg>
        <constructor-arg value="250000"></constructor-arg>
    </bean>

    <bean id="car2" class="com.itcast.spring.bean.Car">
        <constructor-arg value="BMW" type="java.lang.String"></constructor-arg>
        <constructor-arg value="BeiJing" type="java.lang.String"></constructor-arg>
        <constructor-arg value="240" type="int"></constructor-arg>
    </bean>

    <!-- 如何配置集合属性 -->
    <bean id="person2" class="com.itcast.spring.bean.Person">
        <property name="name" value="Jack"></property>
        <property name="age" value="20"></property>
        <property name="cars" >
            <list>
                <ref bean="car"/>
                <ref bean="car2"/>
            </list>
        </property>
    </bean>
</beans>

编写测试代码:

public static void main(String[] args) {
   
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = (Person) ctx.getBean("person2");
        System.out.println(person);
}

运行结果:

Person [name=Jack, age=20, cars=[Car [brand=Audi, corp=ShangHai, price=250000.0, maxSpeed=0], Car [brand=BMW, corp=BeiJing, price=150000.0, maxSpeed=240]]]

对于Set和Map集合,Spring提供了set标签和map标签进行配置,配置原理相同,不作重复介绍。Map集合会有点特殊,因为它是以键值对的方式存储的,所以它是通过Map节点下的子节点entry进行配置的,entry节点包含key和value-ref属性,也简单配置一下给大家看看吧。

<map>
    <entry key="aa" value-ref="car"></entry>
    <entry key="bb" value-ref="car2"></entry>
</map>

属性文件值注入

还有一种特殊类型,Properties,就是我们熟知的配置文件,在Spring中,同样可以通过配置直接将值注入到该属性中,看一个案例你们就会明白。
创建一个bane类:

package com.itcast.spring.bean;

import java.util.Properties;

public class DataSource {
   

    private Properties properties;

    public Properties getProperties() {
   
        return properties;
    }

    public void setProperties(Properties properties) {
   
        this.properties = properties;
    }

    @Override
    public String toString() {
   
        return "DataSource [properties=" + properties + "]";
    }
}

然后对该类进行配置:

<?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="dataSource" class="com.itcast.spring.bean.collection.DataSource">
        <property name="properties">
            <props>
                <prop key="user">root</prop>
                <prop key="password">123456</prop>
                <prop key="url">jdbc:mysql:///test</prop>
                <prop key="driver">com.mysql.jdbc.Driver</prop>
            </props>
        </property>
    </bean>
</beans>

配置完成后,编写测试代码:

public static void main(String[] args) {
   
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        DataSource dataSource = (DataSource) ctx.getBean("dataSource");
        System.out.println(dataSource);
}

运行结果:

DataSource [properties={user=root, url=jdbc:mysql:///test, password=123456, driver=com.mysql.jdbc.Driver}]

实现过程非常简单,这样就将对数据库的配置注入到Properties属性中,关于对数据库的操作就可以通过这样进行封装。

鉴于是对Spring的快速入门,所以也没有去深入地介绍Spring的一些内容,关于Spring的快速入门,就说到这里,接下来还会出几篇Spring高级或者Spring一些其它的知识点。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
存储 缓存 NoSQL
快速入门:Spring Cache
快速入门:Spring Cache
84 0
|
前端开发 Java 应用服务中间件
Spring Boot -01- 快速入门篇(详解图文教程)下
Spring Boot -01- 快速入门篇(详解图文教程)
|
开发框架 Java Maven
Spring Boot -01- 快速入门篇(详解图文教程)上
Spring Boot -01- 快速入门篇(详解图文教程)
|
1月前
|
开发框架 Java API
「SpringBrick快速入门指南」:一款基于Spring Boot的高级插件化开发框架
「SpringBrick快速入门指南」:一款基于Spring Boot的高级插件化开发框架
53 0
|
4月前
|
XML Java API
Spring Boot快速入门指南
Spring Boot快速入门指南
|
安全 Java 数据安全/隐私保护
Spring Security快速入门
Spring Security快速入门
149 0
|
JSON Java API
Spring Boot之Jackson快速入门,你必须得会!
在上一期《SpringBoot之Jackson配置全局时间日期格式》文中提到Jackson,了解到有很多小伙伴对它很感兴趣;顾这一期,我就重点带着大家以最基础的教学方式领大家入门,废话不多说,咱们这就开始。
|
Java API Spring
spring快速入门
spring快速入门
83 0
|
前端开发 安全 Java
Spring Boot介绍--快速入门--约定优于配置
Spring Boot介绍--快速入门--约定优于配置
118 0
|
SQL Java 程序员
Spring事务管理 -- Spring快速入门保姆级教程(五)(2)
Spring事务管理 -- Spring快速入门保姆级教程(五)
116 0