目录

一、Spring概念

1.1 容器

1.2 IoC

1.3 理解SpringIoC

二、Spring框架的创建步骤

2.1 创建一个Maven项目

2.2 添加Spring框架支持(在pom.xml添加Spring依赖)

2.3 创建一个普通的类和main方法

三、将Bean存储到Spring容器中

3.1 创建一个bean

3.2 将bean存储在Spring中

3.2.1 现在maven项目中的resources底下创建一个spring.xml

3.2.2 xml中添加一个bean

四、获取并使用bean对象

4.1 获取Spring上下文对象,相当于获取spring容器了,指定spring的配置文件

4.1.1 通过ApplicationContext获取

4.1.2 通过BeanFactory获取

4.1.3 ApplicationContext和BeanFactory的区别:

4.2 根据上下文对象使用getBean方法获得某一个bean。

4.2.1 根据Id获取

 4.2.2 根据类名获取

4.2.3 根据Id+类名获取

4.3 使用bean

五、总结


一、Spring概念

我们通常所说的Spring是指Spring Framework(Spring框架)。他是一个开源框架,有着活跃而庞大的社区,这就是他之所以能长久不衰的原因。

Spring:是一个包含众多工具方法的IoC容器。

1.1 容器

容器是用来容纳某种物品的基本装置。以我们以前学的知识为例,List/Map是一个数据存储容器。Tomcat是一个Web容器。

1.2 IoC

Ioc:inversion of control,控制反转。所以,Spring是一个控制反转的容器。

控制反转的意思:Java对象的创建销毁等管理不由程序员控制,而是将控制权交给Spring,等需要的时候管spring要。

以创建一个小汽车的代码为例:

现在要构建一辆车,车需要依赖车身,车身需要依赖底盘,地盘需要依赖轮胎,我们的设计思路是:

spring特殊字符转义_xml

代码实现为:

public class CarDemo {
    public static void main(String[] args) {
        Car car = new Car();
        car.make();
    }
    /**
     * 创建一个汽车类
     */
    static class Car{
        // 制造汽车依赖于车身
        public void make(){
            CarFrame carFrame = new CarFrame();
            carFrame.make();
        }
    }
    static class CarFrame{
        // 车身的制造依赖地盘
        public void make(){
            Bottom bottom = new Bottom();
            bottom.make();
        }
    }
    static class Bottom{
        // 地盘地制造依赖轮胎
        public void make(){
            Tire tire = new Tire();
            tire.make();
        }
    }
    static class Tire{
        private int size = 15;
        public void make(){
            System.out.println("轮胎的尺寸是"+size);
        }
    }
}

以上程序中,轮胎的尺寸是固定的。由于对车的需求越来越多样化,车的轮胎的尺寸也多种多样,我们需要对上面的程序进行修改:

package try1;

public class CarDemo {
    public static void main(String[] args) {
        Car car = new Car(20);
        car.make();
    }
    /**
     * 创建一个汽车类
     */
    static class Car{
        private int size;
        public Car(int size){
            this.size = size;
        }
        // 制造汽车依赖于车身
        public void make(){
            CarFrame carFrame = new CarFrame(size);
            carFrame.make();
        }
    }
    static class CarFrame{
        private int size;
        public CarFrame(int size){
            this.size = size;
        }
        // 车身的制造依赖地盘
        public void make(){
            Bottom bottom = new Bottom(size);
            bottom.make();
        }
    }
    static class Bottom{
        private int size;
        public Bottom(int size){
            this.size = size;
        }
        // 地盘地制造依赖轮胎
        public void make(){
            Tire tire = new Tire(size);
            tire.make();
        }
    }
    static class Tire{
        private int size = 15;
        public Tire(int size){
            this.size = size;
        }
        public void make(){
            System.out.println("轮胎的尺寸是"+size);
        }
    }
}

在修改的过程中可以发现,当最底层的代码改动以后,整个调用链上的所有代码都需要修改。那我们应该怎样改进呢?

在上述代码中,将每一层自己创建的下级类(在Car类中new一个CarFrame),改为传递的方式,即注入的方式。我们不需要在当前类中创建下级类,所以当下级类发生变化,比如参数增多或者减少,当前类的代码无需修改任何代码,这就完成了程序的解耦。代码实现如下:

package try1;

public class CarDemo2 {
    public static void main(String[] args) {
        Tire tire = new Tire(20,"red");
        Bottom bottom = new Bottom(tire);
        CarFrame carFrame = new CarFrame(bottom);
        Car car = new Car(carFrame);
        car.make();
    }
    /**
     * 创建一个汽车类
     */
    static class Car{
        private CarFrame carFrame;
        public Car(CarFrame carFrame){
            this.carFrame = carFrame;
        }
        // 制造汽车依赖于车身
        public void make(){
            carFrame.make();
        }
    }
    static class CarFrame{
        private Bottom bottom;
        public CarFrame(Bottom bottom){
            this.bottom = bottom;
        }
        // 车身的制造依赖地盘
        public void make(){
            bottom.make();
        }
    }
    static class Bottom{
        private Tire tire;
        public Bottom(Tire tire){
            this.tire = tire;
        }
        // 地盘地制造依赖轮胎
        public void make(){
            tire.make();
        }
    }
    static class Tire{
        private int size = 15;
        private String color = "黑色";
        public Tire(int size,String color){
            this.size = size;
            this.color = color;
        }
        public void make(){
            System.out.println("轮胎的尺寸是"+size+"轮胎的颜色是"+color);
        }
    }
}

经过以上调整,无论底层如何改变,整个调用链是不用做任何改变的。

spring特殊字符转义_xml_02

总结:程序的实现代码和类的创建顺序是相反的。传统的代码是Car创建并控制了CarFrame,Car Frame创建并控制了Bottom,依次往下。而改进之后的控制权发生了反转。不再是上级对象创建并控制下级对象,而是将下级对象注入到上级对象中。下级对象不再由上级对象控制,这样即使下级对象发生任何改变,上级对象是不受任何影响的,这就是典型的控制反转,也就是LoC的实现思想。总结为: 类的创建顺序发生了改变、调用下属类的控制权发生了变化

1.3 理解SpringIoC

Spring是一个包含多了工具方法的IoC容器。去掉修饰词,Spring是一个容器,那么Spring就具备两个最基础的功能:

存:将对象存储在Spring容器中

取:将对象从Spring容器中取出

将对象存放到容器中,就相当于将以后可能用到的工具都放到仓库中,需要的时候直接取就行,用完之后再放回到仓库中。而new对象的方式相当于每次需要工具时现做,用完了也不会保存,下次需要还需要重新做。这就是IoC容器和普通程序的区别。

Spring是一个IoC容器,意思是对象的创建和销毁的权利都交给Spring来管理。同时Spring本身也具备了存储对象和获取对象的能力。

早期的Spring = IoC/DI。DI,Dependency Injection,依赖注入,就是指动态的将某种依赖关系注入到对象当中。

广义上来说,Ioc和DI从不同的角度描述同一件事情。

从微观上来说,IoC描述的是目标,DI是具体的可实现思路。

二、Spring框架的创建步骤

2.1 创建一个Maven项目

spring特殊字符转义_xml_03

2.2 添加Spring框架支持(在pom.xml添加Spring依赖)

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

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
    </dependencies>

Spring-context和Spring-beans(bean就是Java中的对象)

2.3 创建一个普通的类和main方法

spring特殊字符转义_后端_04

三、将Bean存储到Spring容器中

3.1 创建一个bean

bean:就是指Java中的对象

spring特殊字符转义_spring_05

3.2 将bean存储在Spring中

3.2.1 现在maven项目中的resources底下创建一个spring.xml

spring特殊字符转义_spring特殊字符转义_06

<?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">
</beans>

3.2.2 xml中添加一个bean

spring特殊字符转义_spring特殊字符转义_07

四、获取并使用bean对象

4.1 获取Spring上下文对象,相当于获取spring容器了,指定spring的配置文件

4.1.1 通过ApplicationContext获取

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");

4.1.2 通过BeanFactory获取

BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring.xml");

4.1.3 ApplicationContext和BeanFactory的区别:

归属关系:ApplicationContext是BeanFactory的子类。

功能方面:BeanFactory提供了基础的访问容器的能力,ApplicationContext继承了BeanFactory的所有功能以外,他还拥有独特的特性,添加了对国际化支持、资源访问支持、时间传播等方面的支持。

性能方面:ApplicationContext是一次性加载并初始化所有的Bean对象,而BeanFactory是按需加载,因此更轻量。ApplicationContext初始化慢,调用快。BeanFactory初始化快,调用慢。

4.2 根据上下文对象使用getBean方法获得某一个bean。

4.2.1 根据Id获取

User user =(User) beanFactory.getBean("user1");

注意:①需要类型强转②bean的id要对应

spring特殊字符转义_spring_08

 4.2.2 根据类名获取

User user = beanFactory.getBean(User.class);

特点:写法简单。无需强制类型转换。如果同一个类型被重复注册到spring.xml中,使用类型获取会导致程序异常。

spring特殊字符转义_xml_09

4.2.3 根据Id+类名获取

User user = beanFactory.getBean("user1",User.class);

注意:此时不再需要进行强制类型转换。推荐该方法。

4.3 使用bean

import beans.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Try1 {
    public static void main(String[] args) {
        // 1.得到Spring上下文对象
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        // 2.根据上下文对象获得某一个bean
        User user1 = (User) applicationContext.getBean("user1"); // 根据bean的id来获取
        // 3.使用bean
        user1.sayHello();
    }
}

五、总结

操作容器之前,要现有容器,所以需要先创建一个Spring(Spring就是指Spring框架)。

存对象:①先创建Bean。(创建一个普通类)② 将Bean注册(配置)到spring.xml当中。

取对象:①得到Spring上下文,并读取spring的配置文件②获取某一个bean对象

使用bean对象