Spring 是什么

Spring 是一个分层的 Java SE/EE 的轻量级框架,能够提高开发人员的开发效率以及系统可维护性

Spring 的特征

非侵入性

Spring 框架的 API 不会在业务逻辑上出现,业务逻辑可以从 Spring 框架快速地移植到其他框架,和环境无关。

容器

作为一个容器,可以管理对象的生命周期、对象与对象的依赖关系,可以通过配置文件来定义对象并设置与其他对象的依赖关系。

IoC

IoC(Inverse of Control,控制反转),既创建被调用者的实例不是由调用者完成,而是由 Spring 容器,并注入调用者。当应用了 IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。即,不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。

AOP

通过分离应用的业务逻辑与系统级服务(例如日志和事务管理)进行开发。应用对象只实现它们应该做的——完成业务逻辑。它们并不负责其它的系统级关注点,例如日志或事务支持。

我们可以把日志、安全、事务管理等服务理解成一个「切面」,那么以前这些服务一直是直接写在业务逻辑的代码当中的,这有两点不好:首先业务逻辑不纯净;其次这些服务被很多业务逻辑反复使用,完全可以剥离出来做到复用。那么 AOP 就是这些问题的解决方案, 可以把这些服务剥离出来形成一个「切面」,以期复用,然后将「切面」动态的「织入」到业务逻辑中,让业务逻辑能够享受到此「切面」的服务。

入门代码

引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mindartisan</groupId>
    <artifactId>Spring</artifactId>
    <version>1.0-SNAPSHOT</version>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.8.RELEASE</version>
        </dependency>
    </dependencies>

</project>

创建 HelloSpring 类

package com.mindartisan.spring1;

public class HelloSpring {
    private String name;

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

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

resources 文件夹下新建配置文件

命名一般为「applicationContext.xml」,代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
       default-autowire="byName">
    <!-- 配置 Bean:其中,class 为 bean 的全类名,通过反射的方式在 IOC 容器中创建 Bean,故要求 Bean 中有无参构造器;id 作用为标识容器中的 bean,id 唯一。-->
    <bean id="helloSpring" class="com.mindartisan.spring1.HelloSpring">
        <!-- name 会调用类属性的 set 方法-->
        <property name="name" value="MindArtisan-Spring"></property>
    </bean>
</beans>

创建一个类测试

传统写法

代码:

package com.mindartisan.spring1;

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

public class Main {
    public static void main(String[] args) {
        /**
         * 传统写法
         */
        // 1.实例一个 hellospring 对象
        HelloSpring helloSpring=new HelloSpring();
        // 2. 设置属性
        helloSpring.setName("MindArtisan——traditional");
        // 3. 调用方法
        helloSpring.hello();
    }
}

输出结果:

springer审稿状态有好几个under peer review_java

使用 Spring 后写法

代码:

package com.mindartisan.spring1;

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

public class Main {
    public static void main(String[] args) {
         /**
         * Spring 写法
         */
        // 1. 创建 Spring 的 IOC 容器
        // 1.1 ApplicationContext 是一个接口,而 ClassPathXmlApplicationContext 是其实现类,具体可看 UML 图
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 2. 从 IOC 容器中获取 Bean 实例
        // 2.1 方式一:利用 id 定位到 IOC 容器中的 Bean
        HelloSpring helloSpring = ((HelloSpring) applicationContext.getBean("helloSpring"));
        // 2.2 方式二:利用类型返回 IOC 容器中的 Bean,要求是 IOC 容器中只有一个该类型的 Bean,否则代码不知道应该返回哪个 Bean,不推荐使用
        //HelloSpring helloSpring1 = applicationContext.getBean(HelloSpring.class);
        // 3. 调用方法
        helloSpring.hello();
    }
}

输出:

springer审稿状态有好几个under peer review_java_02

几点思考

思考一: 这里咱们没有显示地为 name 赋值,咋就成 MindArtisan-Spring 了呢?

答案: 再看下 resources 文件夹下新建配置文件 中的内容即可明白。

思考二: applicationContext 为我们做了什么呢?

分析:
将 Main 类中的下述代码注释:

// 2. 从 IOC 容器中获取 Bean 实例
        // 2.1 方式一:利用 id 定位到 IOC 容器中的 Bean
        // HelloSpring helloSpring = ((HelloSpring) applicationContext.getBean("helloSpring"));
        // 2.2 方式二:利用类型返回 IOC 容器中的 Bean,要求是 IOC 容器中只有一个该类型的 Bean,否则代码不知道应该返回哪个 Bean,不推荐使用
        //HelloSpring helloSpring1 = applicationContext.getBean(HelloSpring.class);
        // 3. 调用方法
        // helloSpring.hello();

并将 HelloSpring 代码改成下述内容:

package com.mindartisan.spring1;

    public class HelloSpring {
        private String name;

        public void setName(String name) {
            System.out.println("name 被设置为:"+name);
            this.name = name;
        }

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

        public HelloSpring() {
            System.out.println("Constructor-HelloSpring");
        }
    }

输出:

springer审稿状态有好几个under peer review_业务逻辑_03

答案: 在创建 applicationContext 容器的时会调用构造器,将配置在配置文件中的 Bean 进行初始化,并调用 Bean 的 set 方法对属性赋值。