学习目标
- 能够说出Spring的体系结构
- 能够编写IOC入门案例
- 能够编写DI入门案例
- 能够配置setter方式注入属性值
- 能够配置构造方式注入属性值
- 能够理解什么是自动装配
一、Spring简介
1 Spring课程介绍
问题导入
我们为什么要学习Spring框架?
1.1 为什么要学
-
Spring技术是JavaEE开发必备技能,企业开发技术选型命中率>90%
-
专业角度
- 简化开发,降低企业级开发的复杂性
- 框架整合,高效整合其他技术,提高企业级应用开发与运行效率
- 节约成本
1.2 学什么
-
简化开发
- IOC(控制反转) DI
- AOP(面向切面编程)
- 事务处理
-
框架整合
- MyBatis
- MyBatis-plus
- Struts
- Struts2
- Hibernate
- ……
1.3 怎么学
- 学习Spring框架设计思想
- 学习基础操作,思考操作与思想间的联系
- 学习案例,熟练应用操作的同时,体会思想
2 初识Spring
问题导入
目前我们使用的是Spring几版本?
2.1 Spring家族
- 官网:https://spring.io
- Spring发展到今天已经形成了一种开发的生态圈,Spring提供了若干个项目,每个项目用于完成特定的功能。
2.2 Spring发展史
3 Spring体系结构
问题导入
通过系统架构图,Spring能不能进行数据层开发?Spring能不能进行web层开发?
3.1 Spring Framework系统架构图
- Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基
4 Spring核心概念
代码演示
4.1 目前我们代码存在的问题
- 代码书写现状
- 耦合度偏高
- 解决方案
- 使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象
4.2 核心概念
-
IOC(Inversion of Control)控制反转
使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转。通俗的讲就是“将new对象的权利交给Spring,我们从Spring中获取对象使用即可”
-
Spring技术对IoC思想进行了实现
- Spring提供了一个容器,称为IOC容器,用来充当IoC思想中的“外部”
- IOC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean
-
DI(Dependency Injection)依赖注入
- 在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入。
- 目标:充分解耦
- 使用IoC容器管理bean(IOC)
- 在IoC容器内将有依赖关系的bean进行关系绑定(DI)
- 最终效果
- 使用对象时不仅可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系
二、IOC和DI入门案例【重点】
1 IOC入门案例【重点】
问题导入
<bean>标签中id属性和class属性的作用是什么?
1.1 入门案例思路分析
- 管理什么?(Service与Dao)
- 如何将被管理的对象告知IOC容器?(配置文件)
- 被管理的对象交给IOC容器,如何获取到IoC容器?(接口)
- IOC容器得到后,如何从容器中获取bean?(接口方法)
- 使用Spring导入哪些坐标?(pom.xml)
1.2 实现步骤
【第一步】导入Spring坐标
【第二步】定义Spring管理的类(接口)
【第三步】创建Spring配置文件,配置对应类作为Spring管理的bean对象
【第四步】初始化IOC容器(Spring核心容器/Spring容器),通过容器获取bean对象
1.3 实现代码
【第一步】导入Spring坐标
<dependencies>
<!--导入spring的坐标spring-context,对应版本是5.2.13.RELEASE-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
</dependencies>
【第二步】定义Spring管理的类(接口)
- BookDao接口和BookDaoImpl实现类
public interface BookDao {
public void save();
}
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
- BookService接口和BookServiceImpl实现类
public interface BookService {
public void save();
}
public class BookServiceImpl implements BookService {
private BookDao bookDao = new BookDaoImpl();
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
【第三步】创建Spring配置文件,配置对应类作为Spring管理的bean对象
- 定义applicationContext.xml配置文件并配置BookServiceImpl
<?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标签:表示配置bean
id属性:表示给bean起名字
class属性:表示给bean定义类型
-->
<bean id="bookService" class="com.itgaohe.service.impl.BookServiceImpl"></bean>
</beans>
注意事项:bean定义时id属性在同一个上下文中(IOC容器中)不能重复
【第四步】初始化IOC容器(Spring核心容器/Spring容器),通过容器获取Bean对象
public class App {
public static void main(String[] args) {
//1.创建IoC容器对象,加载spring核心配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//2 从IOC容器中获取Bean对象(BookService对象)
BookService bookService= (BookService)ctx.getBean("bookService");
//3 调用Bean对象(BookService对象)的方法
bookService.save();
}
}
1.4 运行结果
2 DI入门案例【重点】
问题导入
<property>标签中name属性和ref属性的作用是什么?
2.1 DI入门案例思路分析
- 基于IOC管理bean
- Service中使用new形式创建的Dao对象是否保留?(否)
- Service中需要的Dao对象如何进入到Service中?(提供方法)
- Service与Dao间的关系如何描述?(配置)
2.2 实现步骤
【第一步】删除使用new的形式创建对象的代码
【第二步】提供依赖对象对应的setter方法
【第三步】配置service与dao之间的关系 xml
2.3 实现代码
【第一步】删除使用new的形式创建对象的代码
public class BookServiceImpl implements BookService {
private BookDao bookDao; //【第一步】删除使用new的形式创建对象的代码
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
【第二步】提供依赖对象对应的setter方法
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
//【第二步】提供依赖对象对应的setter方法
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
【第三步】配置service与dao之间的关系
在applicationContext.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">
<!--
bean标签:表示配置bean
id属性:表示给bean起名字
class属性:表示给bean定义类型
-->
<bean id="bookDao" class="co.gaohe.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.gaohe.service.impl.BookServiceImpl">
<!--配置server与dao的关系
property标签:表示配置当前bean的属性
name属性:表示配置哪一个具体的属性
ref属性:表示参照哪一个bean
-->
<property name="bookDao" ref="bookDao"/>
</bean>
</beans>
随堂练习:创建一个Student类对象被spring管理
- 创建Student对象
- 写bean配置
- 从工厂中获取一个对象、完成操作
三、Bean的基础配置
问题导入
问题1:在<bean>标签上如何配置别名?
问题2:Bean的默认作用范围是什么?如何修改?
1 Bean基础配置【重点】
配置说明
2 Bean别名配置
配置说明
打印结果
3 Bean作用范围配置【重点】
配置说明
扩展:scope的取值不仅仅只有singleton和prototype,还有request、session、application、 websocket ,表示创建出的对象放置在web容器(tomcat)对应的位置。比如:request表示保存到request域中。
取值范围 说明 singleton 默认值,单例的 prototype 多例的 request WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中 session WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中 global session WEB 项目中,应用在 Portlet 环境,如果没有 Portlet 环境那么globalSession 相当于 session
最后给大家说明一下:在我们的实际开发当中,绝大部分的Bean是单例的,也就是说绝大部分Bean不需要配置scope属性。
步骤1.创建无参构造器 里面打印一句话
步骤2.分别传入 scope="singleton" /scope="prototype"
1.先默认只加载
ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext2.xml");
此时控制台 打印 如果是singleton则会有内容 如果是prototype 则没有内容 说明 singleton是加载容器的时候加载了内容
2.此时 打开AService aService1 = (AService) app.getBean("aService"); prototype打印内容 说明两个作用范围加载实际是不同的。
3.多次调用
AService aService1 = (AService) app.getBean("aService");
AService aService2 = (AService) app.getBean("aService");
AService aService3 = (AService) app.getBean("aService");
发现控制台打印 如果是singleton 只加载一次 prototype加载三次。
单例和非单例区别:
- 加载时机不同。单例在工厂初始化的时候加载,非单例在调用的时候加载。
- 对象个数不同。单例只创建一个对象,非单例用一次创建一个。(多次调用getBean)
当scope的取值为singleton时
Bean的实例化个数:1个
Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
Bean的生命周期:
对象创建:当应用加载,创建容器时,对象就被创建了
对象运行:只要容器在,对象一直活着
对象销毁:当应用卸载,销毁容器时,对象就被销毁了
当scope的取值为prototype时
Bean的实例化个数:多个
Bean的实例化时机:当调用getBean()方法时实例化Bean
对象创建:当使用对象时,创建新的对象实例
对象运行:只要对象在使用中,就一直活着
对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了
四、Bean的实例化
问题导入
Bean的实例化方式有几种?构造方法方式、静态工厂方式、实例工厂方式
1 Bean是如何创建的【理解】
Bean本质上就是对象,创建Bean使用构造方法完成
2 实例化Bean的三种方式
2.1 构造注入【重点】
- BookDaoImpl实现类 (默认是无参构造注入)
public class BookDaoImpl implements BookDao {
public BookDaoImpl() {
System.out.println("book dao constructor is running ....");
}
public void save() {
System.out.println("book dao save ...");
}
}
- applicationContext.xml配置
<!--方式一:构造方法实例化bean-->
<bean id="bookDao" class="com.itgaohe.dao.impl.BookDaoImpl"/>
- AppForInstanceBook测试类
public class AppForInstanceBook {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
}
}
- 运行结果
注意:无参构造方法如果不存在,将抛出异常BeanCreationException
2.1.1 构造方法进阶
BookServiceImpl
public class BookServiceImpl implements BookService {
private BookDao bookDao;
//service实现类中创建构造器 构造器是dao的
private String name;
private int age;
public BookServiceImpl(BookDao bookDao) {
this.bookDao = bookDao;
}
public BookServiceImpl(BookDao bookDao, String name, int age) {
this.bookDao = bookDao;
this.name = name;
this.age = age;
}
@Override
public void save() {
System.out.println(name);
System.out.println(age);
System.out.println("book service save ...");
bookDao.save();
}
}
xml
<bean id="bookService" class="com.itgaohe.service.impl.BookServiceImpl">
<!--name 是引用的注入们 ref是容器名-->
<constructor-arg ref="bookDao" name="bookDao"></constructor-arg>
<constructor-arg name="age" value="18"/>
<constructor-arg name="name" value="zs"/>
<!--也可以换为索引-->
<!-- <constructor-arg index="2" value="18"/>-->
<!-- <constructor-arg index="1" value="zs"/>-->
</bean>
<bean id="bookDao" class="com.itgaohe.dao.impl.BookDaoImpl"/>
2.2 静态工厂方式(了解)
- OrderDao接口和OrderDaoImpl实现类
public interface OrderDao {
public void save();
}
public class OrderDaoImpl implements OrderDao {
public void save() {
System.out.println("order dao save ...");
}
}
- OrderDaoFatory工厂类
//静态工厂创建对象
public class OrderDaoFactory {
public static OrderDao getOrderDao(){
System.out.println("factory setup....");
return new OrderDaoImpl();
}
}
- applicationContext.xml配置
<!--方式二:使用静态工厂实例化bean-->
<bean id="orderDao" class="com.itgaohe.factory.OrderDaoFactory" factory-method="getOrderDao"/>
- AppForInstanceOrder测试类
public class AppForInstanceOrder {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
OrderDao orderDao = (OrderDao) ctx.getBean("orderDao");
orderDao.save();
}}
- 运行结果
应用场景:
- 在初始化bean前进行参数项设置。
- 对老系统架构进行兼容时使用。
从官网中查看:
2.3 实例工厂方式(了解)
- UserDao接口和UserDaoImpl实现类
public interface UserDao {
public void save();
}
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("user dao save ...");
}
}
- UserDaoFactory工厂类
//实例工厂创建对象
public class UserDaoFactory {
public UserDao getUserDao(){
return new UserDaoImpl();
}
}
- applicationContext.xml配置
<!--方式三:使用实例工厂实例化bean-->
<bean id="userFactory" class="com.gaohe.factory.UserDaoFactory"/>
<bean id="userDao" factory-bean="userFactory" factory-method="getUserDao" />
- AppForInstanceUser测试类
public class AppForInstanceUser {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) ctx.getBean("userDao");
userDao.save();
}
}
- 运行结果
应用场景:
- 借助工厂类批量加载类。
- 老项目升级时,可将老项目中的bean加载到新工厂中。
- 许多框架底层实现都是基于此。比如springMVC框架,把批量的controller类加载到容器中!
2.4 实现FactoryBean<T>方式【扩展,了解】
- 定义UserDaoFactoryBean实现FactoryBean<UserDao>
UserDaoFactoryBean中实例化什么类型的对象泛型就是该类型。
//FactoryBean创建对象
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
//代替原始实例工厂中创建对象的方法
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
public Class<?> getObjectType() {
return UserDao.class;
}
}
- applicationContext.xml配置
<!--方式四:使用FactoryBean实例化bean-->
<bean id="userDao" class="com.gaohe.factory.UserDaoFactoryBean"/>
使用之前的AppForInstanceUser测试类去运行看结果就行了。注意配置文件中id="userDao"是否重复。
五、Bean的生命周期【了解】
问题导入
问题1:多例的Bean能够配置并执行销毁的方法?
问题2:如何做才执行Bean销毁的方法?
1 生命周期相关概念介绍
- 生命周期:从创建到消亡的完整过程
- bean生命周期:bean从创建到销毁的整体过程
- bean生命周期控制:在bean创建后到销毁前做一些事情
2 代码演示
2.1 Bean生命周期控制
- 提供生命周期控制方法
public class People {
private String name;
private int id;
public People() {
System.out.println("1. 无参构造器。。。");
}
public void init(){
System.out.println("3. init初始化。。。");
}
public void destroy(){
System.out.println("5. destroy 对象销毁");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
System.out.println("4. 对象调用 getId");
return id;
}
public void setId(int id) {
System.out.println("2. set id 赋值");
this.id = id;
}
}
- applicationContext.xml配置
<!--init-method:设置bean初始化生命周期回调函数,此处填写init方法名-->
<!--destroy-method:设置bean销毁生命周期回调函数,仅适用于单例对象,此处填写destory方法名-->
<bean id="people" class="com.itgaohe.pojo.People" scope="singleton" init-method="init" destroy-method="destroy">
<property name="id" value="22"/>
<property name="name" value="zs"/>
</bean>
- 测试类
public class AppForLifeCycle {
public static void main( String[] args ) {
//此处需要使用实现类类型,接口类型没有close方法
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
People people = app.getBean(People.class);
// People people = (People) app.getBean("people");
String name = people.getName();
int id = people.getId();
System.out.println(id);
System.out.println(name);
//关闭容器,执行销毁的方法
app.close();
}
}
2.2 Bean生命周期控制
- 实现InitializingBean, DisposableBean接口
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
System.out.println("set .....");
this.bookDao = bookDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
public void destroy() throws Exception {
System.out.println("service destroy");
}
public void afterPropertiesSet() throws Exception {
System.out.println("service init");
}
}
3 Bean销毁时机
- 容器关闭前触发bean的销毁
- 关闭容器方式:
- 手工关闭容器
ConfigurableApplicationContext
接口close()
操作 - 注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机
ConfigurableApplicationContext
接口registerShutdownHook()
操作
- 手工关闭容器
public class AppForLifeCycle {
public static void main( String[] args ) {
//此处需要使用实现类类型,接口类型没有close方法
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
//注册关闭钩子函数,在虚拟机退出之前回调此函数,关闭容器
ctx.registerShutdownHook();
//关闭容器
//ctx.close();
}
}
六、依赖注入(DI配置)
1 依赖注入方式【重点】
1.1 依赖注入的两种方式
- setter注入
- 构造器注入
1.2 setter方式注入
在bean中定义引用类型属性并提供可访问的set方法
public class BookServiceImpl implements BookService{
private BookDao bookDao;
private String name;
// set方法自行创建}
配置中使用property标签
<bean id="bookService"class="com.itgaohe.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/>
<property name="name" ref="zhangsan"/></bean>
<bean id="bookDao" class="com.itgaohe.dao.impl.BookDaoImpl"/>
1.3 构造方式注入
类中制定好指定参数的构造器 同上
配置中使用constructor-arg标签
<bean id="bookService" class="com.itgaohe.service.impl.BookServiceImpl">
<constructor-arg name="bookDao" ref="bookDao"/>
<constructor-arg name="name" ref="lisi"/></bean>
<bean id="bookDao" class="com.itgaohe.dao.impl.BookDaoImpl"/>
1.4 依赖注入方式选择
- 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
- 可选依赖使用setter注入进行,灵活性强
- Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
- 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
- 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
- 自己开发的模块推荐使用setter注入
2 依赖自动装配【理解】
2.1 自动装配概念
- 每一个bean都需要配置,如此很麻烦。不如自动配置。
- 自动装配方式
按类型(常用)
按名称
按构造方法
不启用自动装配
2.2 自动装配类型
我们在之前注入数据的时候
如果使用构造注入
<bean id="people" class="com.itgaohe.pojo.People">
<constructor-arg ref="bookDao" name="bookDao"/>
<constructor-arg name="name" value="zs"/>
<constructor-arg value="1" name="id"/>
</bean>
那接下来我们来说一下 自动注入
依赖自动装配
配置中使用bean标签autowire属性设置自动装配的类型
<bean id="peopleDao" class="com.itgaohe.dao.impl.PeopleDaoImpl"/>
<bean id="peopleService" class="com.itgaohe.service.impl.PeopleServiceImpl" autowire="byType"/>
依赖自动装配特征
- 自动装配用于引用类型依赖注入,不能对简单类型进行操作
- 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
- 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
- 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
代码演示:
public class Emp {
private String name;//普通类型
private BookDao bookDao;//引用类型 不要忘记getset
private List<String> hobby;//集合类型
public Emp() {
}
public Emp(String name, BookDao bookDao, List<String> hobby) {
this.name = name;
this.bookDao = bookDao;
this.hobby = hobby;
}
// get/set tostring
}
public interface BookDao {
public void save();
}
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("save");
}
}
applicationContext.xml
1.autowire=“byName”
<bean id="bookDao1/bookDao" class="com.itgaohe.dao.impl.BookDaoImpl"/>
<bean id="emp" class="com.itgaohe.pojo.Emp" autowire="byName"></bean>
bookDao1和bookDao切换使用
打印结果分别为:
Emp{name='null', bookDao=com.itgaohe.dao.impl.BookDaoImpl@2038ae61, hobby=null}
Emp{name='null', bookDao=null, hobby=null}
结论:使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐
2.autowire=“byType”
<bean id="bookDao" class="com.itgaohe.dao.impl.BookDaoImpl"></bean>
<bean id="bookDao2" class="com.itgaohe.dao.impl.BookDaoImpl"></bean>
<bean id="emp" class="com.itgaohe.pojo.Emp" autowire="byType"/>
出现问题:
No qualifying bean of type 'com.itgaohe.dao.BookDao' available: expected single matching bean but found 2: bookDao,bookDao2
测试:
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
Emp emp = app.getBean("emp", Emp.class);
System.out.println(emp);
}
3 集合注入
public class Emp {
private String name;//普通类型
private BookDao bookDao;//引用类型
private String[] hobby;
private List<String> hobby2;//集合类型
private Set<String> hobby3;//集合类型
private Map<String,String>hobby4;
private Properties properties;
}
3.1 注入数组类型数据
<bean id="emp" class="com.itgaohe.pojo.Emp" autowire="byType">
<property name="hobby">
<array>
<value>100</value>
<value>200</value>
<value>300</value>
</array>
</property>
</bean>
3.2 注入List类型数据
<property name="hobby2">
<list>
<value>itgaohe1</value>
<value>itgaohe2</value>
<value>boxuegu</value>
<value>chuanzhihui</value>
</list>
</property>
3.3 注入Set类型数据
<property name="hobby3">
<set>
<value>gaohejituan</value>
<value>gaohe</value>
<value>boxuegu</value>
<value>boxuegu</value>
</set>
</property>
3.4 注入Map类型数据
<property name="hobby4">
<map>
<entry key="country" value="china"/>
<entry key="province" value="henan"/>
<entry key="city" value="kaifeng"/>
</map>
</property>
3.5 注入Properties类型数据
<property name="properties">
<props>
<prop key="country">china</prop>
<prop key="province">henan</prop>
<prop key="city">kaifeng</prop>
</props>
</property>
说明:property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写<array>、<list>、<set>、<map>、<props>标签
七、第三方资源配置管理
说明:以管理DataSource连接池对象为例讲解第三方资源配置管理
7.1 管理DataSource连接池对象
问题导入
配置数据库连接参数时,注入驱动类名是用driverClassName还是driver?
1.1 管理Druid连接池【重点】
【第一步】添加Druid连接池依赖
【第二步】配置DruidDataSource连接池Bean对象
【第三步】在测试类中从IOC容器中获取连接池对象并打印
数据库准备
create database if not exists spring_db character set utf8;
use spring_db;
create table if not exists tbl_account(
id int primary key auto_increment,
name varchar(20),
money double
);
insert into tbl_account values(null,'Tom',1000);
insert into tbl_account values(null,'Jerry',1000);
【第一步】添加Druid连接池依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
注意:除了添加以上两个依赖之外,别忘了添加spring-context依赖。
【第二步】配置DruidDataSource连接池Bean对象
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
【第三步】在测试类中从IOC容器中获取连接池对象并打印
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
DataSource dataSource = (DataSource) ctx.getBean("dataSource");
System.out.println(dataSource);
}
}
7.2 spring整合mybatis配置文件版
0.引入表user.sql
1.导入依赖pom.xml
<!--数据库--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.27</version> </dependency> <!--spring--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.13.RELEASE</version> </dependency> <!-- mybatis依赖 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.5</version> </dependency> <!-- 阿里的连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.6</version> </dependency> <!--spring整合mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.1</version> </dependency> <!--jdbc的相关依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.13.RELEASE</version> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> </dependency>
2.建立结构
@Alias("user")
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
}
public interface UserMapper {
List<User> findAll() throws IOException;
}
public class UserMapperImpl implements UserMapper {
@Autowired
private SqlSessionTemplate sqlSessionTemplate;
@Override
public List<User> findAll() throws IOException {
//此时不能通过 mybatis工具去完成该操作
//因为:此时管理权交给了spring去控制 增删改查的能力交给了spring
//通过 sqlSessionTemplate 来管理工厂的操作
// SqlSession sqlSession = MybatisUtils.getSqlSession();
// UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// List<User> all = mapper.findAll();
// return all;
//1.加载核心配置文件
// InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//2.获取sqlsessionfactory 加载 输入流到 工厂中
// SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.打开sqlSessionFactory 拿到单个的sqlsession对象
// SqlSession sqlSession = sqlSessionFactory.openSession();
// List<Object> findAll = sqlSession.selectList("com.itgaohe.mapper.UserMapper.findAll");
// for (Object o : findAll) {
// System.out.println(o);
// }
//关闭 释放资源
// sqlSession.close();
//sqlSession模板操作
UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class);
List<User> all = mapper.findAll();
return all;
}
public static void main(String[] args) throws IOException {
UserMapperImpl userMapper = new UserMapperImpl();
List<User> all = userMapper.findAll();
System.out.println(all);
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itgaohe.dao.UserMapper">
<select id="findAll" resultType="user">
select * from user
</select>
</mapper>
3.SpringConfig写bean配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:property-placeholder location="jdbc.properties"/> <!--2.开启数据源--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/db1?characterEncoding=utf-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean> <!--3.开启数据源--> <!--3.开启数据源--> <!-- <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>--> <!--1.spring整合mybatis后控制的创建连接用的对象--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!--1.1整合数据源--> <property name="dataSource" ref="dataSource"/> <!--1.2整合mapper映射位置--> <property name="mapperLocations" value="classpath:com/itgaohe/dao/*.xml"/> <!--1.3实体类起别名--> <property name="typeAliasesPackage" value="com.itgaohe.pojo"/> <!--1.4配置文件的位置--> <!-- <property name="configLocation" value="classpath:mybatis-config.xml"/>--> <!--1.5分页助手--> <!-- <property name="plugins">--> <!-- <array>--> <!-- <bean class="com.github.pagehelper.PageHelper">--> <!-- <property name="properties">--> <!-- <value>--> <!-- dialect=mysql--> <!-- </value>--> <!-- </property>--> <!-- </bean>--> <!-- </array>--> <!-- </property>--> </bean> <!--3.加载mybatis映射配置的扫描,将其作为spring的bean进行管理--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.itgaohe.dao"/> </bean> <!--4.注入SqlSessionTemplate模板--> <bean id="sessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> <!--5.注入userMapper 不注入也行 但是要保证只有一个--> <bean id="userMapper" class="com.itgaohe.dao.impl.UserMapperImpl" > </bean> </beans>
4.test
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("SpringConfig.xml");
UserMapper userDao = app.getBean("userMapper",UserMapper.class);
List<User> all = userDao.findAll();
System.out.println(all);
}
}
Result type not match for select id=“findAll” srcType: com.itgaohe.pojo.User targetType: com.itgaohe.pojo.User
问题可能原因:
1.在多个module中定义了多个相同的类名,比如我是在不同的module中定义了多个User类,导致MyBatisX不能精确识别到方法的返回类型User是哪个module下的User类。
解决方法:
1.不用管它,自动忽略,MyBatisX会自动识别到最近的User类,就近原则,报红不会影响程序运行
也可以不注入Mapper
1.注释掉实现类 2.容器中不注入mapper 3.app.getBean(UserMapper.class)
public static void main(String[] args) throws IOException {
ApplicationContext app = new ClassPathXmlApplicationContext("SpringConfig.xml");
UserMapper userDao = app.getBean("userMapper",UserMapper.class);
List<User> all = userDao.findAll();
System.out.println(all);
}
今日总结
总结:
- 为什么要学习spring:(重要)
- 简化开发
- 解耦代码
- 提高效率
- 当下企业都在用!你不会,找不到工作!!!
- spring-core 控制狂: IOC/DI (控制反转、依赖注入) (重要:操作)
- 创建一个类
- 写配置文件,配置bean 注入bean属性
- getBean() 获得bean
- bean的作用范围: 单例、非单例
- 加载时机不同。
- 对象不同。
- bean的生命周期(了解): 1构造器、2setter 、3init 、4调用方法、 5销毁
- bean实例化方式:(对象如何到容器)
- 构造方法方式(默认)、静态工厂方式(了解)、实例工厂方式(了解)、FactoryBean
- 依赖注入方式(练习)
- 构造器注入(了解)— 了解
- setter注入(重要)— 掌握
- 自动装配(了解)— 为了学注解做准备
- 集合注入(练习)
userDao = app.getBean(“userMapper”,UserMapper.class);
List all = userDao.findAll();
System.out.println(all);
}
}
Result type not match for select id="findAll" srcType: com.itgaohe.pojo.User targetType: com.itgaohe.pojo.User
问题可能原因:
1.在多个module中定义了多个相同的类名,比如我是在不同的module中定义了多个User类,导致MyBatisX不能精确识别到方法的返回类型User是哪个module下的User类。
**解决方法:**
1.不用管它,自动忽略,MyBatisX会自动识别到最近的User类,就近原则,报红不会影响程序运行
也可以不注入Mapper
1.注释掉实现类 2.容器中不注入mapper 3.app.getBean(UserMapper.class)
```java
public static void main(String[] args) throws IOException {
ApplicationContext app = new ClassPathXmlApplicationContext("SpringConfig.xml");
UserMapper userDao = app.getBean("userMapper",UserMapper.class);
List<User> all = userDao.findAll();
System.out.println(all);
}
今日总结
总结:
- 为什么要学习spring:(重要)
- 简化开发
- 解耦代码
- 提高效率
- 当下企业都在用!你不会,找不到工作!!!
- spring-core 控制狂: IOC/DI (控制反转、依赖注入) (重要:操作)
- 创建一个类
- 写配置文件,配置bean 注入bean属性
- getBean() 获得bean
- bean的作用范围: 单例、非单例
- 加载时机不同。
- 对象不同。
- bean的生命周期(了解): 1构造器、2setter 、3init 、4调用方法、 5销毁
- bean实例化方式:(对象如何到容器)
- 构造方法方式(默认)、静态工厂方式(了解)、实例工厂方式(了解)、FactoryBean
- 依赖注入方式(练习)
- 构造器注入(了解)— 了解
- setter注入(重要)— 掌握
- 自动装配(了解)— 为了学注解做准备
- 集合注入(练习)