Spring快速入门

2019-08-26 06:52:38来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

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一些其它的知识点。


原文链接:https://www.cnblogs.com/blizzawang/p/11411528.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:深入Java源码剖析之Set集合

下一篇:Android探索之百度地图开发