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