Spring 环境搭建和样例解析

654 阅读6分钟

主要内容

对于Java开发者来说,Spring就是。。

  • 对于没有研究过Spring源码的选手,就算Spring Boot和Cloud用到飞起也只是漂亮的空中阁楼。
  • 遂对Spring主要组件的源码进行学习,在使用Spring的相关框架时,对自己的写的代码要心知肚明,毕竟根基不牢地动山摇。

关于Spring Framework

它是做什么的

  • 就是方便Java EE(企业级开发)的,具体看(Spring Framework)中的Features条目
  • 凡是一些常用和繁琐的功能都加一层封装好,就给个接口供开发者调用。
  • 还有一些抽象的概念比如:IoC,DI,容器,AOP等概念,之后有遇到再细说。
  • 还有什么发展历史,比如EJB哪些,感兴趣自行了解。

环境搭建

导入如下依赖,以方便进行Spring技术的研究

"org.springframework:spring-core:5.3.14.RELEASE",
"org.springframework:spring-aop:5.3.14.RELEASE",
"org.springframework:spring-beans:5.3.14.RELEASE",
"org.springframework:spring-context:5.3.14.RELEASE" ,
"org.springframework:spring-context-support:5.3.14.RELEASE",
"org.springframework:spring-web:5.3.14.RELEASE",
"org.springframework:spring-orm:5.3.14.RELEASE",
"org.springframework:spring-aspects:5.3.14.RELEASE",
"org.springframework:spring-webmvc:5.3.14.RELEASE"
"org.springframework :spring-jdbc:5.3.14.RELEASE",
"org.springframework:spring-instrument:5.3.14.RELEASE",
"org.springframework:spring-tx:5.3.14.RELEASE",

Spring是一个容器

  • 在Spring中,对象一般称之为Bean,Spring可以管理和实例化对象。
  • 总的来说,在企业级开发中有蛮蛮多类需要被实例化,单靠人为的去new,由于数量庞大,八成是会错乱的。所以Spring帮你new,你只需要取你想要的对象进行使用即可
  • 即你只要担心你需要的,而其它的就可以忽略了。

样例

  • 以下为本次目录结构

image.png

先从最基础的xml模式开始

先把类定义好

  • bean
/*
POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans,也可以说是没有功能的对象
*/
public class Student {
    private String name;
    private int age;

    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;
    }
}
  • xml文件

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="student" class="com.spring.bean.Student">
        <property name="name" value="法外狂徒" />
        <property name="age" value="23" />
    </bean>
</beans>
  • 在xml中给Student类中的属性赋值了,即将Student数据存在了xml文件中

image.png

  • main方法所在的类
public class SpringClient {
    public static void main(String[] args) {
        Resource resource = new ClassPathResource("applicationContext.xml");
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        BeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(factory);
        beanDefinitionReader.loadBeanDefinitions(resource);

        Student student = (Student) factory.getBean("student");

        System.out.println(student.getName() +"\n" + student.getAge() );
    }
}

image.png

Spring所涉及的思想

所有信息都称之为资源(Resource)

  • 资源包含很多内容:类路径下面的资源,文件系统中的文件,xml文件,HTTP,url。。。

image.png

  • 所以 Resource resource = new ClassPathResource("applicationContext.xml"); 这行代码的出现就是理所应当了。要将资源准备好。
  • 对于ClassPath是什么,简单说就是java文件编译成class文件后,class文件所在的目录就是,
String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
System.out.println("path = " + path);//得到的就是classpath

image.png

Spring之所以叫容器是因为它帮我们管理(实例化)了Bean对象

  • 如何实例化?当然是经典的工厂模式
  • 工厂模式简单说就是对外隐藏new关键字,调用工厂方法获取实例化对象。
  • 只要告诉工厂正确的配方(Resource),它就能帮你造出对象来。
  • 当需要对象时,直接管工厂要就行了
  • 所以 DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); 这行代码的出现就是理所应当了。

如何将工厂和资源关联起来?

  • 首先,工厂是存放和创建对象的地方,对于资源解析和读取的功能工厂肯定是没有的。
  • 所以对资源的解析就由Bean的定义读取器(BeanDefinitionReader)来完成,当然还要让它和工厂发生关系。
  • 所以 BeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(factory); 这行代码的出现就理所应当了。因为资源是xml的格式,所以用 XmlBeanDefinitionReader
  • BeanDefinitionReader 还有解析资源的功能,将解析到的bean信息告诉工厂,工厂就会将一个个bean存起来,之后要使用bean的话,直接从工厂拿即可。
  • 所以 beanDefinitionReader.loadBeanDefinitions(resource); 就出现了。
  • 万事俱备,可以从工厂中拿对象了 Student student = (Student)factory.getBean("student");
  • 别忘记告诉工厂bean的唯一标识,就是xml文件中的id。这样活灵活现的对象就出来了。

  • 总之, Spring管理Bean的流程如下:
    • 先准备好定义Bean内容的资源(Resource)。
    • 需要一个工厂来管理和创建Bean。
    • 需要一个第三者,即BeanDefinitionReader来解析资源中Bean的定义,顺便将解析后的信息告诉工厂。
    • 这样,算是使用Spring提供的组件将容器搭建好了。

可以说一说IoC和DI了

  • IoC—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想
  • 曾经,对象的创建都是要程序员手动去new,现在用Spring反而不需要了,对象的创建都由Spring完成,往细了说,都由工厂去创建创建对象的控制权由程序员变成了spring中的工厂。

别忘了,工厂也是对象,创建对象的控制权从人类转移到了工厂手上。即由对象创建和管理对象。

  • 是程序主动去创建依赖对象;

  • DI—Dependency Injection,即依赖注入控制反转是通过依赖注入实现的,其实它们是同一个概念的不同角度描述。
  • 组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。
  • 下面的代码就是老师(Teacher)依赖学生(Student)
public class Teacher {
    private Student student;
}

Teacher需要使用Student对象提供的属性和方法,那student就必须实例化,所以Spring容器会将创建好的student对象注入到Teacher中。这样,Teacher中所依赖的student,Teacher就可以正常使用student了。

再次说明关于spring容器管理Bean的过程以及加载模式

  1. 需要将bean的定义信息声明在spring的配置文件当中。
  2. 需要通过spring抽象出的各种Resource来指定对应的配置文件。
  3. 需要显式声明一个spring工厂,该工厂用来掌控我们在配置文件中所声明的各种bean以及bean之间的依赖关系与注入关系
  4. 需要定义一个配置信息读取器(BeanDefinitionReader),该读取器用来读取之前所定义的bean配置文件信息。
  5. 读取器的作用是读取我们所声明的配置文件信息,并且将读取后的信息装配到之前所声明的工厂当中
  6. 需要将读取器工广以及资源对象进行相应的关联处理
  7. 工厂所管理的全部对象装配完毕,可以供客户端直接调用,获取客户端想要使用的各种bean对象。