Spring快速入门详解
前言
Spring技术是JavaEE开发必备技能,企业开发技术选型命中率>90%。
Spring具有简化开发,降低企业级开发的复杂性和框架整合,高效整合其他技术,提高企业级应用开发与运行效率的特点。
本文详细讲解Spring快速入门。
简介
官网:spring.io
Spring发展到今天已经形成了一种开发的生态圈,Spring提供了若干个项目,每个项目用于完成特定的功能。以下就是Spring的全家桶。
image.png
本文主要讲解Spring Framework
image.png
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基础配置
image.png
4.2 bean别名配置
image.png
注意:获取bean无论是通过id还是name获取,如果无法获取到,将抛出异常NoSuchBeanDefinitionException,意思是这个bean没有被定义。此问题很大可能是配置时写错,或者是获取时候写错导致的,到时候看看修改一下就解决了。
4.3 bean作用范围
image.png
由此可知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注入和构造器注入。
- setter注入包含:简单类型和引用类型
- 构造器注入包含:简单类型和引用类型
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必须与属性bean的id或name一致
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
那么关于druid的bean配置就可以写成如下:
<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。
如果有什么问题,我们可以一起交流讨论解决。
最后,希望可以帮助到有需要的码友。