1、什么是Spring

Spring是一个由Rod Johnson组织开发的一个分层的Java SE/EE 一站式轻量开源框架,它是以Ioc(控制反转)和AOP(面向切面编程)为内核,使用基本的JavaBean来完成以前只可能由EJB完成的工作,取代了EJB的臃肿,低效的开发模式。
Sping致力于JavaEE应用各层的解决方案,子啊表现层提供了SpringMVC以及与Struts框架整合的功能,在业务逻辑层可以管理事务、记录日志等;在持久层可以整合Mybatis、Hibernate、JdbcTemplete等技术。

2、Spring的优点

  • 非侵入式设计
  • Spring是一种非侵入式设计,它可以使应用程序对框架的依赖最小化。
  • 方便解耦、简化开发
  • Sping就是一个大工厂,可以将所有对象得的创建和依赖关系的维护工作都交给Spring容器来进行管理,大大降低了组件之间的耦合性。
  • 支持AOP
  • Spring提供了对AOP的支持,它允许将一些通用任务,如安全、事务、日志等进行集中式处理,大大提高了程序的复用性。
  • 支持声明式事务处理
  • 只要通过配置就可以完成对事务的管理,而无需手动编程。
  • 方便程序员的测试
  • Spring提供了对Junit4测试的支持,可以通过注解的方式方便的测试Spring程序。
  • 降低了JavaEE API的使用难度
  • Spring对JavaEE中使用难度较高的API都进行了封装,大大降低了开发难度。

3、Spring的体系结构

【图示结构】:

spring sowing 手法_配置文件

1、Core Container(核心容器)

  • Spring核心容器是其他模块建立的基础,主要由Beans模块、Core模块、Context模块、Context-Support模块、SpEL模块组成。
  • Beans模块:在此模块中提供了BeanFactory,是对工厂模式的经典实现,Spring将管理对象称为Bean。
  • Core核心模块:提供了Spring框架的基本组成部分,包括Ioc和DI功能。
  • Context上下文模块:建立在Beans和Core模块的基础之上,它是访问定义和配置的任何对象的媒介。
  • Context-Support模块:提供第三方库嵌入Spring应用的集成支持。
  • SpEL模块:是Spring3.0之后新添加的模块,他提供Spring Expression Language支持,是运行时查询和操作对象图的强大的表达式语言。

2、Date Access/Integration(数据访问/集成)

数据访问/集成层包括JDBC、ORM、OXM、JMS、和Transactions模块。

  • JDBC模块:提供了一个JDBC抽象层,大幅度减少了在开发过程中对数据的操作。
  • ORM模块:对流行的对象关系映射API提供了集成层支持。
  • OXM模块:提供一个支持对象/XML映射的抽象层实现。
  • JMS模块:指Java消息传递服务、包含使用和产生信息的特性。
  • Transactions事务模块:支持对实现特殊接口以及所有的POJO类的编程和声明式事务的管理。

3、Web

Spring的We包含WebSocket、Servlet、Web和Portlet模块。

  • WebSocket模块:Spring4.0以后新增的模块,它提供了WebSocket和SockJS的实现,以及对STOMP的支持。
  • Servlet模块:实现了web的应用程序。
  • Web模块:提供了基本的web开发集成的特性。
  • Portlet模块:提供了在Portlet环境中使用MVC的实现。

4、其他模块简介

  • AOP 模块提供了一个符合 AOP 联盟标准的面向切面编程的实现。
  • Test 模块支持使用 JUnit 和 TestNG 对 Spring 组件进行测试。

4、Sping核心容器

Sping提供了两个核心容器,一个是BeanFactory另外一个是ApplicationContext。

1、BeanFactory

【定义位置】:

package org.springframework.beans.factory;

【类型】: 接口类型。

【作用】: 简单来说,BeanFactory就是一个管理Bean的工厂,它主要负责初始化各种Bean,并调用它们的生命周期方法。

【常见实现类】:

  • XmlBeanFactory:该类会根据XML配置文件中的定义来装配Bean。

2、ApplicationContext

ApplicationContext是BeanFactory的子接口,也被称为应用上下文,是另外一种常用的Sping核心容器。

【定义位置】:

package org.springframework.context;

【类型】: 接口类型。

【作用】: 包含了BeanFactory的所有功能,同时还支持对国际化、资源访问、事件传播等方面的支持。

1、通过ClassPathXmlApplicationContext创建

ClassPathXmlApplicationContext会从类路径classPath中寻找指定的XML配置文件,找到并装载完成ApplicationContext的实例化工作。

  • 语法:
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("配置文件名称和位置")

2、通过FileSystemXmlApplicationContext 创建

此时的路径不再是从类路径开始查找,而是通过参数指定配置文件的位置,如果参数使用的不是绝对路径,方法在调用的时候会默认使用绝对路径。(不推荐使用)。

  • 语法:
FileSystemXmlApplicationContext  applicationContext=new FileSystemXmlApplicationContext("配置文件名称和位置");

3、获取对象的两种基本方式

  • Object getBean(String name):根据容器中Bean的id或者name来获取指定的Bean,获取之后要进行强制类型转换。
  • T getBean(Class requeryType):根据类的类型来获取Bean的实例,获取之后不需要进行类型转换。

3、BeanFactory和ApplicationContext的区别

  • 都是通过XML配置文件的方式加载Bean。
  • 当Bean的某一个属性没有注入的时候,使用BeanFactory加载后,在第一次调用getBean()方法的时候就会抛出异常。而ApplicationContext则是在初始化自检的时候就会报出异常。
  • 推荐使用ApplicationContext。

5、Spring入门案例之HelloWorld

1、创建maven项目添加如下依赖

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>16</maven.compiler.source>
    <maven.compiler.target>16</maven.compiler.target>
</properties>

<dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.12</version>
		<scope>test</scope>
	</dependency>
	
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>5.0.8.RELEASE</version>
	</dependency>
</dependencies>

2、创建一个类

package cn.simplelife.domain;

/**
 * @ClassName Person
 * @Description
 * @Author simplelife
 * @Date 2022/11/17 22:46
 * @Version 1.0
 */

public class Person {
    private Long id;
    private String name;

    public Person(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public Person() {
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    public void work() {
        System.out.println("疯狂写代码");
    }
}

3、编写配置文件让容器创建对象

<?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">
    <!--使用spring创建对象
    id:名称一般采用类名的首字母小写
    class:要创建对象的全限定类名
    property:属性
    name:对象的属性名称
    value:想要赋值的值
    创建完成之后会将其存放在ioc容器中
    -->
    <bean id="person" class="cn.simplelife.domain.Person">
        <property name="id" value="1"/>
        <property name="name" value="李四"/>
    </bean>
</beans>

4、编写测试类获取对象

import cn.simplelife.domain.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @ClassName PersonTest
 * @Description
 * @Author simplelife
 * @Date 2022/11/17 22:49
 * @Version 1.0
 */

public class PersonTest {

    @Test
    public void testPersonBySpring() {
        // 1、根据配置文件启动spring容器
        // 2、对象是在容器启动的时候创建的
        // 3、在容器启动的时候创建的好处:
        // 1、提高用户体验度
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("_01helloworld.xml");
        // 2、从容器中获取对象
        Person person = (Person) applicationContext.getBean("person");
        // 3、使用对象
        person.work();
    }
}

6、依赖注入

1、什么是依赖注入

依赖注入简称DI与控制反转Ioc描述的是同一种含义,只不过是角度不同。
当某个Java对象(调用者)需要调用另外一个Java对象(被调用者)的时,在以前的写法中,需要我们手动的去在调用者的类中new被调用者的对象来创建被调用者对象。这样的方式导致调用者和被调用者之间的耦合度增高,不利于项目的维护和升级。

在Spring被广泛使用之后,对象实例的调用不需要调用者通过new的方式创建,而是将这部分工作交给spring容器来进行创建,并且spring容器会负责控制调用者与被调用者之间的关系,不再像之前一样由调用者去控制程序之间的关系。

2、依赖注入的实现方式

1、setter方法注入

  • Spring使用setter方法注入被依赖的实例对象。通过调用无参构造器或无参静态工厂实例化Bean对象之后,调用该Bean的Setter方法,就可以实现基于setter方法的注入。
  • 代码演示
package cn.simplelife.dao.impl;

import cn.simplelife.dao.StudentDAO;
import lombok.Cleanup;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * @ClassName StudentDAOImpl
 * @Description
 * @Author simplelife
 * @Date 2022/11/21 11:21
 * @Version 1.0
 */

public class StudentDAOImpl implements StudentDAO {

    private DataSource dataSource;
    // 提供set方法,在配置文件中进行注入
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public void save(String name, String password) throws SQLException {
        @Cleanup
        Connection connection = dataSource.getConnection();
        @Cleanup
        PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO student(name,password)VALUES (?,?)");
        preparedStatement.setString(1, name);
        preparedStatement.setString(2, password);
        preparedStatement.executeUpdate();
    }
}
  • 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!--关联db.properties-->
    <context:property-placeholder location="classpath:db.properties"/>
    <!--配置数据库连接池-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="driverClassName" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${password}"/>
    </bean>
    <!--配置StudentDAOImpl-->
    <bean id="studentDAO" class="cn.simplelife.dao.impl.StudentDAOImpl">
    <!--此时注入连接池对象-->
        <property name="dataSource" ref="druidDataSource"/>
    </bean>