认识Spring
-
Spring官网:https://spring.io/
-
spring Framework是Spring生态圈中最基础的项目,是其他项目的根基
-
Spring Frame系统架构图
核心概念(理解)
当前代码现状:耦合度高
例子:
业务层:
public class BookServiceImpl implements BoosService{
private BookDao bookDao;
public void save(){
bookDao.save();
}
}
数据层实现:
public class BookDaoImpl implements BookDao{
public void save(){
System.out.println("book dao save ...");
}
}
public class BookDao Impl2 implements BookDao{
public void save(){
System.out.println("book dao save ... 2");
}
}
为了解决这个问题,在程序中不要主动new产生对象,转换为由外部提供对象
所以提出了Ioc(Inversion of Control)
控制反转思想
Ioc
控制反转:对象的创建控制权由程序转移到外部,这种思想被称之为控制反转
spring技术对Ioc思想进行了实现:
- Spring提供了一个容器,成为Ioc容器,用来充当Ioc思想中的“外部”
- Ioc容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在Ioc容器中统称为
Bean
DI
DI(Dependency Injection)依赖注入:
- 在容器建立bean与bean之间的依赖关系的整个过程,被称之为依赖注入
Ioc入门案例
项目准备:
1.创建一个maven项目
2.创建包结构:
3.文件:
BookDaoImpl.java
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
public void save(){
System.out.println("book dao save ... ");
}
}
BookDao.java
package com.itheima.dao;
public interface BookDao {
void save();
}
BookServiceImpl.java
package com.itheima.service.Impl;
import com.itheima.dao.BookDao;
import com.itheima.dao.impl.BookDaoImpl;
import com.itheima.service.BookService;
public class BookServiceImpl implements BookService {
private BookDao bookDao = new BookDaoImpl();
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
BookService.java
package com.itheima.service;
public interface BookService {
void save();
}
App.java
package com.itheima;
import com.itheima.service.BookService;
import com.itheima.service.Impl.BookServiceImpl;
public class App {
public static void main(String[] args) {
BookService bookService = new BookServiceImpl();
bookService.save();
}
}
愉快的开始
1.在pom.xml导入spring坐标,刷新一下maven
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.21</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
2.定义Spring的管理类(接口),在准备阶段已经完成
3.鼠标右键resources文件夹,创建一个Spring配置:applicationContext.xml,注意要完成导入坐标才可以创建
application.xml
<?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">
<!-- 1.导入Spring的坐标:spring-context,对应版本是5.3.21-->
<!-- 2.配置bean-->
<!-- 注意这里要配实现类,不要配接口-->
<!-- id属性表示给bean起名字-->
<!-- class属性表示给bean定义类型-->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.itheima.service.Impl.BookServiceImpl"/>
</beans>
- 注:bean定义时id属性在同一个上下文中不能重复
4.初始化Ioc容器(Spring核心容器/Spring容器),通过容器获取bean
App2.java
package com.itheima;
import com.itheima.dao.BookDao;
import com.itheima.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App2 {
public static void main(String[] args) {
//3.获取Ioc容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//4.获取bean
// BookDao bookDao = (BookDao)ctx.getBean("bookDao");
// bookDao.save();
BookService bookService = (BookService) ctx.getBean("bookService");
bookService.save();
}
}
DI入门案例(XML版本)
1.删除使用new形式创建的代码
//5.删除业务层中使用new的方式创建的dao对象
private BookDao bookDao ;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
//6.提供对应的set方法
public void setBookDao(BookDao bookDao){
this.bookDao=bookDao;
}
2.提供依赖对象对应的setter方法
3.配置service与dao之间的关系
<?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">
<!-- 1.导入Spring的坐标:spring-context,对应版本是5.3.21-->
<!-- 2.配置bean-->
<!-- 注意这里要配实现类,不要配接口-->
<!-- id属性表示给bean起名字-->
<!-- class属性表示给bean定义类型-->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.itheima.service.Impl.BookServiceImpl">
<!-- 7.配置service与dao的关系-->
<!-- property表示关联的属性-->
<!-- name表示的是service实现类里面的属性对象-->
<!-- ref表示的是配置文件里的bean的id-->
<property name="bookDao" ref="bookDao"/>
</bean>
</beans>
bean基础配置
bean
类别 | 描述 |
---|---|
名称 | bean |
类型 | 标签 |
所属 | beans标签 |
功能 | 定义Spring核心容器所管理的对象 |
格式 | |
属性列表 | id:bean的id,使用容器可以通过id值获取对应的bean,在一个容器中id值唯一 class:bean的类型,即配置的bean的全路径类名 |
范例 |
name
类别 | 描述 |
---|---|
名称 | name |
类型 | 属性 |
所属 | bean标签 |
功能 | 定义bean的别名,可定义多个,使用逗号(,)分号(;)或者空格( )分割 |
范例 |
<bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl"/>
<!-- name表示别名,多个别名之间用空格隔开-->
<bean id="bookService" name="service service2 bookEbi" class="com.itheima.service.Impl.BookServiceImpl">
<!-- 这里的ref可以使用别名了-->
<property name="bookDao" ref="bookDao"/>
</bean>
- 注:获取bean无论是通过id还是name获取,如果无法获取到,将抛出异常
NoSuchBeanDefinitionException``NoSuchBeanDefinitionException:No bean named 'bookServiceImpl' available
scope
类别 | 描述 |
---|---|
名称 | scope |
类型 | 属性 |
所属 | bean标签 |
功能 | 定义bean的作用范围,可选范围如下:①singleton :单例(默认)②protortype :非单例 |
范例 |
- bean默认为单例,适合交给容器管理的bean一般不可改变
- 表现层对象
- 业务层对象
- 数据层对象
- 工具对象
- 不适合交给容器进行管理的bean:有状态的对象
- 封装实体的域对象
bean实例化
- 查看IDEA报错的方法:
从最底部的错误原因逐层往上找
最终会发现这个是没有无参构造函数导致的错误
构造方法(常用)
- 提供可访问的构造方法
public class BookDaoImpl implements BookDao {
// 提供无参构造
public BookDaoImpl() {
System.out.println("book dao constructor is running ...");
}
public void save() {
System.out.println("book dao save ... ");
}
}
- 配置
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"></bean>
- 如果无参构造方法不存在,将抛出异常
BeanCreationException
静态工厂(了解)
- 静态工厂
package com.itheima.factory;
import com.itheima.dao.OrderDao;
import com.itheima.dao.impl.OrderDaoImpl;
public class OrderDaoFactory {
public static OrderDao getOrderDao(){
System.out.println("factory setup ......");
return new OrderDaoImpl();
}
}
- 配置
<!-- 方式一:构造方法实例化bean-->
<!-- <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"></bean>-->
<!-- 方式二:使用静态工厂实例化bean-->
<bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"></bean>
实例工厂(了解)
- 实例工厂
package com.itheima.factory;
import com.itheima.dao.UserDao;
import com.itheima.dao.impl.UserDaoImpl;
public class UserDaoFactory {
public UserDao getUserDao(){
return new UserDaoImpl();
}
}
- 配置–需要先配置一个工厂bean,然后再造一个bean,没有class属性
<!-- 方式三:使用实例工厂实例化bean-->
<bean id="userFactory" class="com.itheima.factory.UserDaoFactory"></bean>
<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"></bean>
为了简化上面的流程于是推出第四种:
实例工厂FactoryBean(进阶)(实用)
- FactoryBean
package com.itheima.factory;
import com.itheima.dao.UserDao;
import com.itheima.dao.impl.UserDaoImpl;
import org.springframework.beans.factory.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() {
//true表示单例,false表示非单例
return true;
}
}
- 配置
<!-- 方式四,方式三的进阶:使用FactoryBean实例化bean-->
<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"></bean>
bean的生命周期
- ctrl+h表示查看层次结构
- Alt+7查看结构
- 查看成员方法:Ctrl+F12
方法一
- 提供生命周期的控制方法
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ... ");
}
//表示bean初始化对应的操作
public void init() {
System.out.println("init ...");
}
//表示bean销毁前对应的操作
public void destroy() {
System.out.println("destroy ... ");
}
}
- 配置
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destroy"></bean>
方法二
- 实现
InitializingBean
,DisposableBean
接口
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
//5.删除业务层中使用new的方式创建的dao对象
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
public void setBookDao(BookDao bookDao) {
//在属性设置之前
System.out.println("set ...");
this.bookDao = bookDao;
}
@Override
public void afterPropertiesSet() throws Exception {
//初始化方法,在属性设置之后
System.out.println("service init ... ");
}
@Override
public void destroy() throws Exception {
//销毁操作时方法
System.out.println("service destroy ... ");
}
}
-
注意生命周期的流程:
- 初始化容器
1.创建对象(内存分配)
2.执行构造方法
3.执行属性注入(set方法)
4.执行bean初始化方法
-
使用bean
- 执行业务操作
-
关闭/销毁容器
- 执行bean销毁方法
-
注:容器关闭前才会触发bean的销毁
-
关闭容器的方式:
- 手工关闭容器:
ConfigurableApplicationContext
接口close
操作- 注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机
ConfigurableApplicationContext
接口registerShutdownHook()
操作
-
public static void main(String[] args) {
// ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//注册关闭钩子,在任何时间都可以写这句代码,在虚拟机退出之前会自动退出
ctx.registerShutdownHook();
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
//手动关闭
// ctx.close();
}