Spring
2022-7-19
核心概念
IoC控制反转
全称是 Inversion of Control
使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象的创建控制权由程序转移到外部,这种思想称为控制反转
Sping技术对IoC思想进行了实现
Spring提供了一个容器,称为IoC容器,用来充当IoC思想中的外部
IoC容器负责对象的创建,初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean
DI 依赖注入
全称: Dependency Injection
在容器中建立Bean之间的依赖关系的整个过程,称为依赖注入
目的:充分解耦
使用IoC容器管理Bean(IoC)
在IoC容器内将有依赖关系的bean进行关系绑定(DI)
最终效果
使用对象时不仅可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系
IoC入门案例
思路分析
1.管理什么?(Service与Dao)
2.如何将被管理的对象告知IoC容器?(配置)
3.被管理的对象交给IoC容器,如何获取到IoC容器?(接口)
4.IoC容器得到后,如何从容器中获取bean?(接口方法)
5.使用Spring导入哪些坐标?(pom.xml)
步骤(XML版):
1.导入Spring坐标
2.定义Spring管理的类(接口)
3.创建Spring配置文件,配置对应类作为Spring管理的Bean
4.初始化容器(Spring核心容器/Spring容器),通过容器获取bean
DI入门案例
思路分析
1.基于IoC管理bean
2.Service中使用new形式创建的dao对象是否保留(否)
3.Service中需要的Dao对象如何进入到Service中(提供方法)
4.Service与Dao间的关系如何描述?(配置)
步骤
1.删除使用new的形式创建对象的代码
2.提供依赖对象对应的setter方法
3.配置service与dao之间的关系
bean配置
bean基本配置
bean别名配置
bean作用范围
为什么bean默认为单例?
适合交给容器进行管理的bean
表现层对象
业务层对象
数据层对象
工具对象
不适合交给容器进行管理的bean
封装实体的域对象
bean实例化
有三种方式: 构造方法、静态工厂、实例工厂
构造方法(常用)
bean本质上是对象,创建bean使用构造方法完成
提供可访问的构造方法
无参构造器方法如不存在,将抛出BeanCreationException
静态工厂(了解)
实例工厂(了解)
FactoryBean(实用)
bean生命周期
bean生命周期:bean从创建到销毁的整体过程
bean生命周期控制:在bean创建后到销毁前做一些事情
接口控制(了解)
实现IntializingBean,DisposableBean接口
初始化容器
1.创建对象(内存分配)
2.执行构造方法
3.执行属性注入(set操作)
4.执行bean初始化方法
使用bean
1.执行业务操作
关闭/销毁容器
1.执行bean销毁方法
依赖注入方式
总共两种方式
-
setter注入
简单类型
引用类型 -
构造器注入
简单类型
引用类型
setter注入
- 引用类型
在bean中定义引用类型属性并提供可访问的set方法
配置中使用property标签ref属性注入引用类型对象
- 简单类型
在bean中定义引用类型属性并提供可访问的set方法
配置中使用property标签value属性注入简单数据类型
构造器注入
- 引用类型(了解)
在bean中定义引用类型属性并提供可访问的构造方法
配置中使用constructor-arg标签ref属性注入引用类型对象
2.简单类型(了解)
在bean中定义引用类型属性并提供可访问的构造方法
配置中使用constructor-arg标签value属性注入引用类型对象
依赖注入方式选择
依赖自动装配
IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配
自动装配方式:
按类型(最常用)
按名称
按构造方法
不自动装配
自动装配使用autowire属性
自动装配特征
用于引用类型依赖注入,不能对简单类型进行操作
使用按类型装配时必须保障容器中相同类型的bean唯一,推荐使用
使用按名称装配时必须保障容器中具有指定名称 的bean,因变量名与配置耦合,不推荐使用
自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
集合注入
数组
List
Set
Map
Properties
案例
数据源对象管理
第三方资源配置管理
注解开发定义bean
使用@Component定义bean
@Component("bookDao")
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("book dao save...");
}
}
核心配置文件中通过扫描加载bean
// 写在applicationContext.xml中
<context:component-scan base-package="com.itheima" />
sping提供@Component注解的三个衍生注解
@Controller:用于表现层bean定义
@Service用于业务层bean定义
@Repository:用于数据层bean定义
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
}
@Service
public class BookServiceImpl implements BookService {
}
纯注解开发
Spring3.0升级了纯注解开发模式,使用java类替代配置文件,开启了spring快速开发赛道
java类代替Spring核心配置文件
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
@Configuration注解用于设定当前类为配置类
@ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式
@ComponentScan({"com.itheima.service","com.itheima.dao"})
读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象
// 读取Spring核心配置文件初始化容器对象
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//读取Java配置类初始化容器对象
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
bean管理
bean作用范围
使用@scope定义bean作用范围
@Repository
// @Scope("singleton") 单例(默认)
@Scope("prototype") //
public class BookDaoImpl implements BookDao {
}
bean生命周期
想执行destroy方法,需关闭容器
使用 @PostConstruct、 @PreDestroy
@Repository
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("book dao save...");
}
@PostConstruct
public void init() {
System.out.println("init...");
}
@PreDestroy
public void destroy() {
System.out.println("destroy...");
}
}
依赖注入
使用@Autowired注解开启自动装配模式(按类型)
@Service
public class BookServiceImpl implements BookService {
@Autowired
//@Qualifier("bookDao") 如有多个,可用这个注解来区分,但前提必须把@Autowired写在前面
private BookDao bookDao;
@Override
public void save() {
System.out.println("book service save...");
bookDao.save();
}
}
注意:自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此无需提供setter方法
自动装配建议使用无参构造方法创建对象(默认),如不提供构造方法,请提供唯一的构造方法
使用@Value简单类型注入
@Service
public class BookServiceImpl implements BookService {
@Value("itheima")
private String name;
}
使用properties配置文件加载
jdbc.properties配置文件
name=itheima
@Configuration
@ComponentScan("com.itheima")
@PropertySource("jdbc.properties")
public class SpringConfig {
}
@Service
public class BookServiceImpl implements BookService {
@Value("${name}")
private String name;
}
注解开发管理第三方bean
完成对Druid数据源的管理
1.导入Druid对应的jar包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
2.在外部配置类中添加一个方法
public class JdbcConfig {
// 1.定义一个方法获得要管理的对象
//2.添加@Bean注解,表示当前方法的返回值是一个bean
@Bean
public DataSource dataSource() {
DruidDataSource ds =new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("hsp");
return ds;
}
}
3.在方法上添加@Bean注解
4.从IoC容器中获取对象打印
public class App {
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext(SpringConfig.class);
DataSource dataSource = ctx.getBean(DataSource.class);
System.out.println(dataSource);
}
这个配置类如何能被spring配置类加载到,并创建DataSource对象在IoC容器中呢?
使用包扫描引入(不推荐)或使用@Import导入
//在spring配置类引入
@Configuration
@Import(JdbcConfig.class)
public class SpringConfig {
}
//@Import参数是一个数组,可以引入多个配置类
//@Import({JdbcConfig.class,...})
注解开发实现为第三方bean注入资源
简单类型注入
用@Value属性
//配置文件
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.userName}")
private String userName;
@Value("${jdbc.password}")
private String password;
}
引用类型依赖注入
引用类型注入只需要为bean定义形参即可,容器会根据类型自动装配对象
@Bean
public DataSource dataSource(BookDao bookDao) {
System.out.println(bookDao);
DruidDataSource ds =new DruidDataSource();
//属性设置
return ds;
}
注解开发总结
XML配置比对注解配置
Spring整合MyBatis
1.Spring要管理MyBatis中的SqlSessionFactor
2.Spring要管理Mapper接口的扫描
public class MybatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
ssfb.setTypeAliasesPackage("com.itheima.domain");
ssfb.setDataSource(dataSource);
return ssfb;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mscf = new MapperScannerConfigurer();
mscf.setBasePackage("com.itheima.dao");
return mscf;
}
}
Spring整合Junit
单元测试,如果测试的是注解配置类,则使用
@ContextConfiguration(classes = 配置类.class)
单元测试,如果测试的是配置文件,则使用
@ContextConfiguration(locations={配置文件名,...})
// 设置类运行器
@RunWith(SpringJUnit4ClassRunner.class)
//设置Spring环境对应的配置类
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {
@Autowired
private AccountService accountService;
@Test
public void testSelectById(){
System.out.println(accountService.selectById(1));
}
@Test
public void testSelectAll(){
System.out.println(accountService.selectAll());
}
}