Spring快速入门详解

  • 前言
  • 简介
  • 快速入门
  • 1. ApplicationContext配置文件
  • 2. IoC(Inversion of Control)控制反转
  • 2.1 概念
  • 2.2 IoC快速入门
  • 2.2.1 在pom.xml中导入Spring坐标
  • 2.2.2 定义Spring管理的类(接口)
  • 2.2.3 创建Spring的xml配置文件,配置对应类作为Spring管理的bean
  • 2.2.4 初始化IoC容器,通过容器获取bean
  • 3. DI(Dependency injection)依赖注入
  • 3.1 概念
  • 3.2 快速入门
  • 3.2.1 删除使用new的形式创建对象的代码
  • 3.2.2 提供依赖对象对应的setter方法
  • 3.2.3 配置Service与Dao之间的关系
  • 4. bean配置
  • 4.1 bean基础配置
  • 4.2 bean别名配置
  • 4.3 bean作用范围
  • 4.3.1 适合交给容器进行管理的bean
  • 4.3.2 不适合交给容器进行管理的bean
  • 5. bean实例化
  • 5.1 构造方法(常用)
  • 5.1.1 提供可访问的构造方法
  • 5.1.2 配置
  • 5.2 静态工厂(了解)
  • 5.2.1 提供静态工厂类
  • 5.2.2 配置
  • 5.3 实例工厂(了解)
  • 5.3.1 提供实例工厂类
  • 5.3.2 配置
  • 5.4 使用FactoryBean(了解)
  • 5.4.1 提供FactoryBean实现类
  • 5.4.2 配置
  • 6. bean生命周期
  • 6.1 概念
  • 6.2 bean生命周期控制
  • 6.2.1 提供生命周期控制方法
  • 6.2.2 实现InitializingBean, DisposableBean接口
  • 6.3 bean销毁时机
  • 6.3.1 手工关闭容器
  • 6.3.2 注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机
  • 7. 依赖注入方式
  • 7.1 setter注入--引用类型
  • 7.1.1 在bean中定义引用类型属性并提供可访问的set方法
  • 7.1.2 配置中使用property标签ref属性注入引用类型对象
  • 7.2 setter注入--简单类型
  • 7.2.1 在bean中定义简单类型属性并提供可访问的set方法
  • 7.2.2 配置中使用property标签value属性注入简单类型数据
  • 7.3 构造器注入--引用类型 (了解)
  • 7.3.1 在bean中定义引用类型属性并提供可访问的构造方法
  • 7.3.2 配置中使用constructor-arg标签ref属性注入引用类型对象
  • 7.4 构造器注入--简单类型(了解)
  • 7.4.1 在bean中定义简单类型属性并提供可访问的构造方法
  • 7.4.2 配置中使用constructor-arg标签value属性注入简单类型数据
  • 7.4.3 配置中使用constructor-arg标签type属性设置按形参类型注入数据
  • 7.4.4 配置中使用constructor-arg标签value属性设置按形参位置注入数据
  • 7.5 依赖注入方式选择
  • 8. 依赖自动装配(autowire)
  • 8.1 概念
  • 8.2 自动装配方式
  • 8.2.1 按类型(常用)
  • 8.2.2 按名称
  • 8.3 特征
  • 9. 集合注入
  • 9.1 注入数组对象
  • 9.2 注入List对象(重点)
  • 9.3 注入Set对象
  • 9.4 注入Map对象(重点)
  • 9.5 注入Properties对象
  • 10. 第三方资源配置管理
  • 10.1 在pom.xml中导入druid坐标
  • 10.2 配置数据源对象作为Spring管理的bean
  • 11. 加载properties文件
  • 11.1 在配置文件中开启context命名空间
  • 11.2 使用context命名空间,加载指定properties文件
  • 11.2.1 正常加载properties
  • 11.2.2 不加载系统属性
  • 11.2.3 加载多个properties文件
  • 11.2.4 加载所有properties文件
  • 11.2.5 加载properties文件标准格式
  • 11.2.6 从类路径或jar包中搜索并加载properties文件
  • 11.3 使用${}读取加载的属性值
  • 总结


前言

Spring技术是JavaEE开发必备技能,企业开发技术选型命中率>90%。
Spring具有简化开发,降低企业级开发的复杂性和框架整合,高效整合其他技术,提高企业级应用开发与运行效率的特点。
本文详细讲解Spring快速入门。

简介

官网:spring.io Spring发展到今天已经形成了一种开发的生态圈,Spring提供了若干个项目,每个项目用于完成特定的功能。以下就是Spring的全家桶。

spring快递 spring 快速入门_spring


本文主要讲解Spring Framework

spring快递 spring 快速入门_xml_02


Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基。

快速入门

1. ApplicationContext配置文件

本文需要创建applicationContext.xml文件放入resources中内容如下:

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

下文所提到的bean的配置均是在此文件中进行配置。

2. IoC(Inversion of Control)控制反转

2.1 概念

使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转。
Spring技术对IoC思想进行了实现。
Spring提供了一个容器,称为IoC容器,用来充当IoC思想中的外部。
IoC容器负责对象的创建,初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean

2.2 IoC快速入门

2.2.1 在pom.xml中导入Spring坐标
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.19</version>
</dependency>
2.2.2 定义Spring管理的类(接口)
public interface BookService {
    void save();
}
public class BookServiceImpl implements BookService {
    
    private BookDao bookDao = new BookDaoImpl();
    @Override
    public void save() {
        bookDao.save();
    }
}
2.2.3 创建Spring的xml配置文件,配置对应类作为Spring管理的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="bookService" class="com.hao.service.impl.BookServiceImpl"/>
</beans>

注意事项:bean定义时id属性在同一个上下文中不能重复

2.2.4 初始化IoC容器,通过容器获取bean
public class App {
    public static void main(String[] args) {
        /* 加载配置文件 获取IoC容器 */
        ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
        /* 获取bean */
        BookService bookService = (BookService) cxt.getBean("bookService");
        bookService.save();
    }
}

现在运行App类可以看到这里可以正常得到bookService并使用。

3. DI(Dependency injection)依赖注入

3.1 概念

在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入。

3.2 快速入门

3.2.1 删除使用new的形式创建对象的代码
public class BookServiceImpl implements BookService {
    /* 删除业务层中使用new的方式创建的dao对象 */
    private BookDao bookDao;
    @Override
    public void save() {
        System.out.println("book service save...");
        bookDao.save();
    }    
}
3.2.2 提供依赖对象对应的setter方法
public class BookServiceImpl implements BookService {
    /* 删除业务层中使用new的方式创建的dao对象 */
    private BookDao bookDao;
    @Override
    public void save() {
        System.out.println("book service save...");
        bookDao.save();
    }
    /* 提供对应的setter方法 */
    public void setBookDao(BookDao bookDao) {
        System.out.println("set book dao...");
        this.bookDao = bookDao;
    }
}
3.2.3 配置Service与Dao之间的关系
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.hao.service.impl.BookServiceImpl">
    <!-- 配置Service与Dao的关系 -->
    <!--
        property标签:表示配置当前bean的属性
        name属性:表示配置哪一个具体的属性
        ref属性:表示参照哪一个bean 可以是id,也可以是name 建议使用id
    -->
    <property name="bookDao" ref="bookDao"/>
</bean>

4. bean配置

4.1 bean基础配置

spring快递 spring 快速入门_java_03

4.2 bean别名配置

spring快递 spring 快速入门_xml_04


注意:获取bean无论是通过id还是name获取,如果无法获取到,将抛出异常NoSuchBeanDefinitionException,意思是这个bean没有被定义。此问题很大可能是配置时写错,或者是获取时候写错导致的,到时候看看修改一下就解决了。

4.3 bean作用范围

spring快递 spring 快速入门_后端_05


由此可知bean默认是创建的单例对象。

4.3.1 适合交给容器进行管理的bean

表现层对象
业务层对象
数据层对象
工具对象

4.3.2 不适合交给容器进行管理的bean

封装实体的域对象

5. bean实例化

bean本质上就是对象,创建bean使用构造方法完成。
实例化bean有四种方式。

5.1 构造方法(常用)

5.1.1 提供可访问的构造方法
public class BookDaoImpl implements BookDao {
    private BookDaoImpl() {
        System.out.println("book dao constructor is running...");
    }
    @Override
    public void save() {
        System.out.println("book dao save...");
    }
}
5.1.2 配置
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl"/>

这里注意一个小细节,就算无参构造方法是私有的,也是可以通过无参构造方法来创建对象。但是如果无参构造方法不存在,将抛出异常BeanCreationException

5.2 静态工厂(了解)

5.2.1 提供静态工厂类
public class OrderDaoFactory {
    public static OrderDao getOrderDao() {
        return new OrderDaoImpl();
    }
}
5.2.2 配置
<bean id="orderDao" class="com.hao.factory.OrderDaoFactory" factory-method="getOrderDao"/>

5.3 实例工厂(了解)

5.3.1 提供实例工厂类
public class UserDaoFactory {
    public UserDao getUserDao() {
        return new UserDaoImpl();
    }
}
5.3.2 配置
<bean id="userFactory" class="com.hao.factory.UserDaoFactory"/>
<bean id="userDao" factory-bean="userFactory" factory-method="getUserDao"/>

5.4 使用FactoryBean(了解)

5.4.1 提供FactoryBean实现类
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
    /* 代替原始实例工厂中创建对象的方法 */
    @Override
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
    }
    /* 对象类型 */
    @Override
    public Class<?> getObjectType() {
        return UserDao.class;
    }
    /* 创建的对象是否是单例 默认是单例 */
    @Override
    public boolean isSingleton() {
        return true;
    }
}
5.4.2 配置
<bean id="userDao" class="com.hao.factory.UserDaoFactoryBean"/>

6. bean生命周期

6.1 概念

生命周期:从创建到消亡的完整过程
bean生命周期:bean从创建到消亡的整体过程
bean生命周期控制:在bean创建后到销毁前做一些事情

6.2 bean生命周期控制

有两种方式可以来实现bean生命周期的控制。

6.2.1 提供生命周期控制方法
public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
        System.out.println("book dao save...");
    }
    /* 定义该方法 表示bean初始化对应的操作 */
    public void init() {
        System.out.println("book dao init...");
    }
    /* 定义该方法 表示bean销毁前对应的操作 */
    public void destory() {
        System.out.println("book dao destory...");
    }
}

配置如下

<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
6.2.2 实现InitializingBean, DisposableBean接口
public class BookServiceImpl implements BookService , InitializingBean, DisposableBean {
    @Override
    public void save() {
        System.out.println("book service save...");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("book service destroy...");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("book service init...");
    }
}

6.3 bean销毁时机

容器关闭前触发bean的销毁

关闭容器方式有两种:手工关闭容器和注册关闭钩子。

6.3.1 手工关闭容器

ConfigurableApplicationContext接口close()操作

public class AppForLifeCycle {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
        /* 获取bean */
        BookDao bookDao = (BookDao) cxt.getBean("bookDao");
        bookDao.save();
        /* 关闭容器 close比较暴力 */
        cxt.close();
    }
}
6.3.2 注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机

ConfigurableApplicationContext接口registerShutdownHook()操作

public class AppForLifeCycle {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
        /* 注册关闭钩 在程序退出之前会先关闭容器 */
        cxt.registerShutdownHook();
        /* 获取bean */
        BookDao bookDao = (BookDao) cxt.getBean("bookDao");
        bookDao.save();
    }
}

7. 依赖注入方式

依赖注入的方式分为setter注入和构造器注入。

  1. setter注入包含:简单类型和引用类型
  2. 构造器注入包含:简单类型和引用类型

7.1 setter注入–引用类型

7.1.1 在bean中定义引用类型属性并提供可访问的set方法
public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}
7.1.2 配置中使用property标签ref属性注入引用类型对象
<bean id="bookService" class="com.hao.service.impl.BookServiceImpl">
        <property name="bookDao" ref="bookDao"/>
    </bean>

7.2 setter注入–简单类型

7.2.1 在bean中定义简单类型属性并提供可访问的set方法
public class BookDaoImpl implements BookDao {
    private int connectionNum;
    private String databaseName;
    public void setConnectionNum(int connectionNum) {
        this.connectionNum = connectionNum;
    }
    public void setDatabaseName(String databaseName) {
        this.databaseName = databaseName;
    }
}
7.2.2 配置中使用property标签value属性注入简单类型数据
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
        <property name="connectionNum" value="123"/>
        <property name="databaseName" value="mysql"/>
    </bean>

7.3 构造器注入–引用类型 (了解)

7.3.1 在bean中定义引用类型属性并提供可访问的构造方法
public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    public BookServiceImpl(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}
7.3.2 配置中使用constructor-arg标签ref属性注入引用类型对象
<bean id="bookService" class="com.hao.service.impl.BookServiceImpl">
        <constructor-arg name="bookDao" ref="bookDao"/>
    </bean>

7.4 构造器注入–简单类型(了解)

7.4.1 在bean中定义简单类型属性并提供可访问的构造方法
public class BookDaoImpl implements BookDao {
    private int connectionNum;
    private String databaseName;
    public BookDaoImpl(int connectionNum, String databaseName) {
        this.connectionNum = connectionNum;
        this.databaseName = databaseName;
    }
}
7.4.2 配置中使用constructor-arg标签value属性注入简单类型数据
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
        <constructor-arg name="connectionNum" value="10"/>
        <constructor-arg name="databaseName" value="mysql"/>
    </bean>

该方式耦合度比较高。

7.4.3 配置中使用constructor-arg标签type属性设置按形参类型注入数据
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
        <constructor-arg type="int" value="10"/>
        <constructor-arg type="java.lang.String" value="mysql"/>
    </bean>

该方式解决参数名耦合问题。

7.4.4 配置中使用constructor-arg标签value属性设置按形参位置注入数据
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
        <constructor-arg index="0" value="666"/>
        <constructor-arg index="1" value="mysql"/>
    </bean>

该方式解决参数类型重复问题。

7.5 依赖注入方式选择

a. 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
b. 可选依赖使用setter注入进行,灵活性强
c. Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
d. 如果有必要可以两者同时使用呢,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
e. 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
f. 自己开发的模块推荐使用setter注入

8. 依赖自动装配(autowire)

8.1 概念

IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程成为自动装配。

8.2 自动装配方式

public class BookServiceImpl implements BookService{
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}
8.2.1 按类型(常用)
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.hao.service.impl.BookServiceImpl" autowire="byType"/>
8.2.2 按名称
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.hao.service.impl.BookServiceImpl" autowire="byName"/>

注意:属性名称bookDao必须与属性beanidname一致

8.3 特征

a. 自动装配用于引用类型依赖注入,不能对简单类型进行操作。
b. 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用。
c. 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用。
d. 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置无效。

9. 集合注入

public class BookDaoImpl implements BookDao {
    private int[] array;
    private List<String> list;
    private Set<String> set;
    private Map<String, String> map;
    private Properties properties;
    
    public void setArray(int[] array) {
        this.array = array;
    }
    public void setList(List<String> list) {
        this.list = list;
    }
    public void setSet(Set<String> set) {
        this.set = set;
    }
    public void setMap(Map<String, String> map) {
        this.map = map;
    }
    public void setProperties(Properties properties) {
        this.properties = properties;
    }

}

9.1 注入数组对象

<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
        <property name="array">
            <array>
                <value>100</value>
                <value>200</value>
                <value>300</value>
            </array>
        </property>
    </bean>

9.2 注入List对象(重点)

<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
        <property name="list">
            <list>
                <value>ithao</value>
                <value>hao</value>
                <value>java</value>
            </list>
        </property>
    </bean>

9.3 注入Set对象

<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
        <property name="set">
            <set>
                <value>ithao</value>
                <value>hao</value>
                <value>spring</value>
            </set>
        </property>
    </bean>

9.4 注入Map对象(重点)

<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
        <property name="map">
            <map>
                <entry key="country" value="China"/>
                <entry key="province" value="henan"/>
                <entry key="city" value="yuzhou"/>
            </map>
        </property>
    </bean>

9.5 注入Properties对象

<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
        <property name="properties">
            <props>
                <prop key="country">China</prop>
                <prop key="province">henan</prop>
                <prop key="city">yuzhou</prop>
            </props>
        </property>
    </bean>

10. 第三方资源配置管理

这里以第三方资源druid为例来讲解详细步骤。

10.1 在pom.xml中导入druid坐标

<dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.9</version>
    </dependency>

10.2 配置数据源对象作为Spring管理的bean

这个bean其实就是管理DruidDataSource对象

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Diver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

测试一下如下:

public class App {
    public static void main(String[] args) {
        ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
        DataSource dataSource = (DataSource) cxt.getBean("dataSource");
        System.out.println(dataSource);
    }
}

11. 加载properties文件

11.1 在配置文件中开启context命名空间

<?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/context
            http://www.springframework.org/schema/context/spring-context.xsd">

11.2 使用context命名空间,加载指定properties文件

比如创建一个jdbc.properties文件,加载jdbc.properties有多种写法如下:

11.2.1 正常加载properties
<context:property-placeholder location="jdbc.properties"/>
11.2.2 不加载系统属性
<context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/>
11.2.3 加载多个properties文件
<context:property-placeholder location="jdbc.properties, jdbc2.properties"/>
11.2.4 加载所有properties文件
<context:property-placeholder location="*.properties"/>
11.2.5 加载properties文件标准格式
<context:property-placeholder location="classpath:*.properties"/>
11.2.6 从类路径或jar包中搜索并加载properties文件
<context:property-placeholder location="classpath*:*.properties"/>

11.3 使用${}读取加载的属性值

jdbc.properties文件中存入druid的配置信息如下:

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=123456

那么关于druidbean配置就可以写成如下:

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

总结

以上就是关于Spring快速入门详解的全部内容,本文详细介绍了使用xml配置的方式来使用Spring Framework

如果有什么问题,我们可以一起交流讨论解决。

最后,希望可以帮助到有需要的码友。