1.IOC/DI配置管理第三方bean
之前都是基于自己写的类,如果有需求去管理第三方
Jar
包中的类,该如何管理?
案例:数据源对象管理
使用
Spring
的IOC
容器来管理Druid
连接池对象
思路分析
-
要使用第三方的技术,需要在pom.xml添加依赖
-
在配置文件中将第三方的类(指
DruidDataSource
)制作成一个bean
,让IOC
容器进行管理 -
数据库连接需要基础的四要素(驱动、连接、用户名和密码)如何注入到对应的
bean
中?setter
注入(因为Druid
源码中没有构造器方法能接受这四个参数) -
四要素写死在配置文件中不利于后期为维护,该如何修改?将值提取到外部的
properties
配置文件,Spring
再去读取
代码实现
参考Spring_09_dataSource
2.核心容器
简单理解就是
ApplicationContext
代码参考Spring_10_container
容器的创建方式
// 1.加载类路径下的配置文件(常用)
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2.从文件系统下加载配置文件(需要写绝对路径)
ApplicationContext ctx = new FileSystemXmlApplicationContext("xxx\\applicationContext.xml");
Bean的三种获取方式
BookDao bookDao1 = (BookDao) ctx.getBean("bookDao"); // 每次获取的时候都需要进行类型转换
BookDao bookDao2 = ctx.getBean("bookDao",BookDao.class); // 多加了一个参数
BookDao bookDao3 = ctx.getBean(BookDao.class); // 必须要确保IOC容器中该类型对应的bean对象只能有一个
总结
-
容器相关:
BeanFactory
是IOC
容器的顶层接口,初始化BeanFactory
对象时,加载bean
是延迟加载(即需要在代码中使用到bean
才会去初始化)ApplicationContext
接口是Spring
容器的核心接口,初始化时bean
立即加载(不过有没使用到bean
,只要加载了配置文件都会去初始化)ApplicationContext
接口提供基础的bean
操作相关方法,通过其他接口扩展其功能ApplicationContext
接口常用初始化类:ClassPathXmlApplicationContext
(常用)FileSystemXmlApplicationContext
-
bean相关:
- 依赖注入相关:
3.IOC/DI注解开发
注解开发定义bean
使用配置文件定义bean时,需要写以下代码,使用注解开发时该如何定义
bean
?<bean id="bookDao" class="com.psj.dao.impl.BookDaoImpl"/>
代码参考Spring_11_annotation_bean
- 删除原
XML
配置 BookDaoImpl
类上添加@Component
注解:- 不可添加在接口上,因为接口无法创建对象
- 如果不起别名,会有以当前类名首字母小写为默认名称
- 该注解还有三个衍射注解:
@Controller
::用于定义表现层bean
@Service
:用于定义业务层bean
@Repository
:用于定义数据(Dao
)层bean
- 配置
Spring
的注解包扫描:为了让Spring
框架能扫描到写在类上的注解,需要在配置文件上进行包扫描
<context:component-scan base-package="com.psj"/>
纯注解开发模式
上面代码中还是使用了配置文件用于对包进行扫描,纯注解开发模式则使用Java类替代配置文件,也就不需要
applicationContext.xml
代码参考Spring_11_annotation_bean
-
创建配置类
SpringConfig
-
标识
SpringConfig
为配置类:添加@Configuration
注解 -
用注解替换包扫描配置:添加包扫描注解
@ComponentScan
(需要添加多个扫描路径用数组格式) -
运行时使用
AnnotationConfigApplicationContext
类
bean作用范围与生命周期管理
代码参考Spring_12_annotation_bean_manager
-
Bean
的作用范围:比如要将BookDaoImpl
变成非单例,只需要在其类上添加@scope
注解(默认值singleton
,可选值prototype
) -
Bean
的生命周期:- 在
BookDaoImpl
中添加两个方法,方法名可以任意 - 在对应的方法上添加
@PostConstruct
和@PreDestroy
注解即可(注意要在pom
文件中添加javax.annotation
的依赖,因为JDK9
移除了)
- 在
注解开发依赖注入
Spring
为了使用注解简化开发,没有提供构造函数注入、setter
注入对应的注解,只提供了自动装配(自动装配基于反射设计创建对象并通过暴力反射为私有属性进行设值,所以无需setter
方法)的注解实现代码参考Spring_13_annotation_bean_manager
- 按照类型注入:
@Autowired
默认按照类型自动装配,如果IOC
容器中同类的Bean
找到多个,就按照变量名和Bean
的名称匹配
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
...
}
- 按照名称注入:
@Qualifier
注解后的值就是需要注入的Bean
的名称@Qualifier
不能独立使用,必须和@Autowired
一起使用
@Service
public class BookServiceImpl implements BookService {
@Autowired
@Qualifier("bookDao1")
private BookDao bookDao;
...
}
-
简单数据类型注入:使用
@Value
注解- 将值直接写入注解的参数
@Repository("bookDao") public class BookDaoImpl implements BookDao { @Value("psj") private String name; ... }
- 读取配置文件:
@PropertySource
属性可用数组形式指定多个@PropertySource
属性中不支持使用通配符*
@PropertySource
属性中可以把classpath:
加上,代表从当前项目的根路径找文件
// ①使用注解加载properties配置文件 @Configuration @ComponentScan("com.psj") @PropertySource("jdbc.properties") public class SpringConfig { } // ②读取配置文件 @Repository("bookDao") public class BookDaoImpl implements BookDao { @Value("${name}") private String name; }
4.IOC/DI注解开发管理第三方bean
前面定义
bean
时候是在自己开发的类上面写注解,如果是第三方的类则没有办法在类上面添加注解,该怎么办?代码参考Spring_14_annotation_third_bean_manager
管理第三方bean
-
新建
JdbcConfig
配置类:该类代码可以直接写在SpringConfig
类中,但是不利于区分和管理 -
把数据源配置到该类下,并在方法上添加
@Bean
注解,表示将方法的返回值制作为Spring
管理的bean
对象:
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
...
return ds;
}
}
- 在
SpringConfig
使用@Import
引入JdbcConfig
配置类:
@Configuration
@Import({JdbcConfig.class})
public class SpringConfig {}
第三方bean注入资源*
在使用
@Bean
创建bean
对象时,如果方法在创建的过程中需要其他资源该怎么办?
- 注入简单类型:
- 类中提供四个属性
- 使用
@Value
注解引入值
public class JdbcConfig {
@Value("com.mysql.jdbc.Driver")
private String driver;
@Value("jdbc:mysql://localhost:3306/xxxx")
private String url;
@Value("xxxx")
private String userName;
@Value("xxxx")
private String password;
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
...
return ds;
}
}
- 注入引用类型:只需要为
bean
定义方法设置形参即可,容器会根据类型自动装配对象
@Bean
public DataSource dataSource(BookDao bookDao){
System.out.println(bookDao); // 前提是要扫描到该bean
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
...
return ds;
}
5.注解开发总结
6.Spring整合
使用
Spring
整合其他框架其实就是将其他框架需要的配置文件中的信息以bean
的形式注入到Spring
的容器中管理
整合Mybatis
代码参考Spring_15_spring_mybatis
未整合前,
Mybatis
的核心文件为App.java
和properties
配置文件,其中哪些对象可交给Spring
来管理?
SqlSessionFactory
(SqlSession
对象在SqlSessionFactory
中已经造出来了,并不属于核心对象):SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
Mapper
接口和Mapper
映射文件(如果使用注解就没有映射文件),这个是在获取到SqlSession
后执行具体操作时用:<mappers> <package name="com.psj.dao"></package> </mappers>
Spring
管理MyBatis
中的SqlSessionFactory
:
public class MybatisConfig {
// 定义bean,SqlSessionFactoryBean,用于产生SqlSessionFactory对象
// SqlSessionFactoryBean中将SqlSessionFactory的创建进行了封装,简化对象的创建,
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){ // dataSource在JdbcConfig中已经注入到Spring中
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
// 下面两句分别是对SqlMapConfig.xml配置文件中typeAliases和environments的替换
ssfb.setTypeAliasesPackage("com.psj.domain");
ssfb.setDataSource(dataSource);
return ssfb;
}
}
Spring
要管理Mapper
接口的扫描:
// 定义bean,返回MapperScannerConfigurer对象
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
// MapperScannerConfigurer用来处理原始配置文件中的mappers相关配置,加载数据层的Mapper接口类
MapperScannerConfigurer msc = new MapperScannerConfigurer();
// 对SqlMapConfig.xml配置文件中mappers的替换
msc.setBasePackage("com.psj.dao");
return msc;
}
Spring整合Junit
代码参考Spring_16_spring_junit
重点在于添加相应的依赖以及在测试类中完成相关配置
参考
https://www.bilibili.com/video/BV1Fi4y1S7ix?p=17-30