一、Spring框架概述
1、Spring框架是什么?
Spring 是一个轻量级的开源的JavaEE框架
开源:免费提供源代码
框架:让开发更加方便简洁
2、spring的目的与作用:
目的:Spring框架是由于软件开发的复杂性而创建的,解决企业应用开发的复杂性,适用于任何java应用
作用:【Spring 解决了的最核心的问题就是把对象之间的依赖关系转为用配置文件来管理,也就是Spring的依赖注入机制。这个注入机制是在Ioc 容器中进行管理的】
3、Spring 的两个核心:控制反转(loC)和面向切面(AOP)
控制反转(loC):把创建对象过程交给Spirng进行管理
面向切面(AOP):不修改代码进行功能增强
4、Spring特点
(1)方便解耦,简化开发
(2) Aop.编程支持
(3)方便程序测试
(4)方便和其他框架进行整合
(5)方便进行事务操作
(6)降低API开发难度
5、Spring弊端:
发展太久,违背了原理的理念(轻量级)配置十分繁琐 (被称为配置地狱 )——解决方法:SpringBoot
备注:
SpringBoot:一个快速开发的脚手架,基于SpringBoot看可以快速开发单个微服务(约定大于配置)
SpringCloud:云服务(SpringCloud是基于SpringBoot实现的)
二、IOC容器概述
1、什么是IOC?控制反转/反转控制
控制反转IOC(Inversion of Control) 是一种设计思想,把对象创建和对象之间的调用过程,交给Spring进行管理
场景/作用:
传统开发方式——高耦合
由于代码的高耦合,一旦修改源码,就需要重新编译、测试、部署、发布
例如:下面如果想要修改创建的BookDaoImpl对象为BookDaoImpl2对象
如何解决这种高耦合呢?
使用对象时,在程序中不要主动使用new产生对象,转 换为由外部提供对象——【Spring提供了一个容器,来为程序提供对象(IOC容器)】
(IoC控制反转:对象的创建控制权由程序转移到外部,这种思想称为控制反转)
说明1:IoC容器负责对象的创建、初始化等一系列工作
说明2:被创建或被管理的对象在IoC容器中统称为Bean
DI思想:依赖注入
在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入
因此,使用SpringIOC容器可以实现下面两个目标
使用IoC容器管理bean (IoC)
在IoC容器内将有依赖关系的bean进行关系绑定(DI)
最终效果:
使用对象时不仅可以直接从IoC容器中获取
并且获取到的bean已经绑定了所有的依赖关系
为什么说IOC耦合度降低?
1、读取xml配置文件,根据id表示获取全限定名
2、使用了反射创建Bean对象
只需要修改xml配置文件中的地址,仍旧可以使用
推荐文章:Spring 程序间的耦合和解耦
三、IOC容器-快速入门(基于XML方式)
Bean管理就是两个操作 :
(1)由Spring创建对象; ----/将创建对象交给spring/(前提:先有一个实体类)
(2)Spring注入属性----/前提:在类中新建属性、在xml中定义属性/
先通过快速入门案例简单了解一下
【快速入门案例】
准备工作:导入依赖
步骤一:创建一个类(或接口+它的实现类),并且该类有set方法
步骤二:在容器中,创建对象并且注入属性——基于XML方式
步骤三:工具类的main可以从容器中调用容器中的对象和功能
0、导入依赖:
<!--单元测试:通过单元测试可以测试每一个方法-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--Spring的依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
1、创建Bean类
(接口+它的实现类)
2、创建applicationContext.xml并配置对象
1、applicationContext.xml位于resource包中
2、在applicationContext.xml中配置bean对象
3、备注:
//class”引入当前id的包路径.类名“
//id 唯一标识符
<?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="bookDao" class="org.example.dao.Impl.BookDaoImpl"></bean>
<bean id="bookService" class="org.example.service.Impl.BookServiceImpl"></bean>
</beans>
附:如何创建spring.xml文件(前提:导入spring-context的jar包)
3、测试:
说明一:ApplicationContext接口的作用:加载spring配置文件(将xml文件加载到当前类中)
实现类:ClassPath-Xml-ApplicationContext(创建时参数是Src下的类路径)
说明二:getBean方法(通过id或者类路径.class反射来获取该对象)
解耦合:只需要修改xml配置文件中bean对象,所有调用到该配置文件的程序都会同步修改
//1、创建Spring容器:以类加载路径下的beans.xml文件创建Spring容器
ApplicationContext app
= new ClassPathXmlApplicationContext("applicationContext.xml");
//2、获取bean/获取xml中的类对象(通过id或者类路径.class反射来获取该对象)
BookDaoImpl bookDao = app.getBean("bookDao", BookDaoImpl.class);
bookDao.save();
附 :IOC的两种接口:(作用:加载spring配置文件)
a)BeanFactory接口:
IOC容器基本实现,是Spring内部接口的使用接口,不提供给开发人员进行使用(加载配置文件时候不会创建对象,在获取对象时才会创建对象。)
b)ApplicationContext接口:----推荐使用
BeanFactory接口的子接口,提供更多更强大的功能,提供给开发人员使用(加载配置文件时候就会把在配置文件对象进行创建)
(将耗时耗资源的操作在项目启动时进行处理更合适–内存换响应时间)
4、优化:解耦合:
DI思想:依赖注入:在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入。
!–property标签表示配置当前bean的属性
name属性表示配置哪一个具体的属性
ref属性表示参照哪一个bean–>
四、bean管理:基于XML配置文件在容器中创建对象.
基于XML配置文件在容器中创建对象,当需要使用时,从容器中调用即可(像上面使用mapper代理对象调用)
第一种创建方式:构造方法(常用)
xml创建对象的路径默认使用无参构造
假如创建的类中没有无参构造,会报错
备注:
//class”引入当前id的包路径.类名“
//id 唯一标识符
第二种创建方式:静态工厂(了解)
备注:下面写的原理不用编写,是为了表述xml文件配置完成了什么操作
原理:通过静态工厂的静态方法直接创建对象
(根据原理去配置成spring的xml形式来解耦)
spring配置:
通过静态工厂的静态方法直接创建对象
第三种创建方式:实例工厂方式(了解)
(区别:这个工厂是非静态的,因此得创建出工厂对象)
原理:
1、创建实例工厂对象
2、工厂实例对象调用方法创造出对象
spring配置:
第三种创建方式的改良:FactoryBean接口(需要掌握)
为了创建容器对象,每次都得创建实例工厂对象,实际无意义——写一个FactoryBean类,在这个类实现FactoryBean接口
1、创建FactoryBean类
2、配置文件
附:bean标签的属性
1.1 id属性:唯一标识
1.2 class属性:类全路径(包路径)
1.3 scope:配置对象的作用范围了解)
singleton:默认,单例的(多次创建的对象是同一个)
prototype:多例的(多次创建的对象不是同一个)
推荐文章:java中的单例和多例
1.4 name属性:bean别名配置(了解)
一个bean可以有多个id ,配置
五、bean管理:Spring注入属性
在Spring配置文件中配置对象创建,配置属性注入
5.1 属性注入:
附:传统方式:通过new Book对象,对象调用set/构造器方法来传递数据给属性
public class Book {
//创建属性
private String bname;
//创建属性对应的【set方法】
public void setBname(String bname) {
this.bname = bname;}
//
a)Spring注入属性之setter注入属性(推荐)
流程
1、提供set方法
2、配置文件中使用property标签去配置
name:变量名
value:注入值
a-1):setter注入简单类型属性(基本数据类型+String)
步骤1:定义属性+提供set方法
public class BookDaoImpl implements BookDao {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public void save() {
System.out.println("DAO save");
}
}
步骤2:使用property标签value属性 注入
<bean id="bookDao" class="org.example.dao.Impl.BookDaoImpl"><!--注册对象id为bookDao(该对象的包路径为org.example.dao.Impl.BookDaoImpl)-->
<property name="name" value="aaa"/><!--给变量名为name属性 注入的值value为 “aaa”-->
</bean>
a-2):set注入引用类型属性
Spring配置
步骤1、提供可访问的set方法
public class BookServiceImpl {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
步骤2、使用ref属性注入引用类型对象(注入多个对象,写多个property标签即可)
<bean id="bookDao" class="org.example.dao.Impl.BookDaoImpl"></bean>
<!--roperty标签表示配置当前bean的属性
name属性表示配置哪一个具体的属性
ref属性表示参照哪一个bean-->
<bean id="bookService" class="org.example.service.Impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/>
</bean>
b)构造器注入:(了解)
流程:
1、提供构造方法
2、配置文件中使用constructor-arg标签去配置
name:构造方法中的形参
value:注入值
注:(构造器注入方式 耦合度更高,因为形参的名字在配置文件中固定了)
b-1)构造器注入简单类型属性
b-2)构造器注入引用类型属性
依赖注入方式的选择
1、强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
2、可选依赖使用setter注入进行,灵活性强
3、Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
4、如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
5、实际开发过程中还要根据实陈情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
6、自己开发的模块推荐使用setter注入
5.2 依赖注入:【自动装配】(引用类型)
1、按类型自动装配 (推荐使用)
使用《bean标签》属性autowire=“byType”
2、按名称自动装配 (耦合、不推荐)
使用《bean标签》属性autowire=“byName”
自动装配用于引用类型依赖注入,不能对简单类型进行操作
使用按类型装配时( byType )必须保障容器中相同类型的bean唯一,推荐使用
使用按名称装配时( byName )必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用·
自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效(优先级:手动大于自动)
5.3 注入集合(了解)
1、给集合属性添加对应的set方法
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;
}
2、在配置文件中注入集合
<?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="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<!--数组注入-->
<property name="array">
<array>
<value>100</value>
<value>200</value>
<value>300</value>
</array>
</property>
<!--list集合注入-->
<property name="list">
<list>
<value>itcast</value>
<value>itheima</value>
<value>boxuegu</value>
<value>chuanzhihui</value>
</list>
</property>
<!--set集合注入-->
<property name="set">
<set>
<value>itcast</value>
<value>itheima</value>
<value>boxuegu</value>
<value>boxuegu</value>
</set>
</property>
<!--map集合注入-->
<property name="map">
<map>
<entry key="country" value="china"/>
<entry key="province" value="henan"/>
<entry key="city" value="kaifeng"/>
</map>
</property>
<!--Properties注入-->
<property name="properties">
<props>
<prop key="country">china</prop>
<prop key="province">henan</prop>
<prop key="city">kaifeng</prop>
</props>
</property>
</bean>
</beans>
5.4 注入外部属性文件
附:Spring文件中直接配置连接池
<bean 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="root"/>
</bean>
这种直接将数据库的配置信息和xml文件耦合在一起,如何解耦合呢?
可以将数据库的配置信息写到一个文件,使用注入外部属性文件 将外部的文件注入到spring文件中
1、抽取数据库信息到外部文件jdbc.properties中
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
jdbc.username=root
jdbc.password=root
2、注入外部文件
a)开启context名称空间
b)使用context空间加载properties文件
加载单个文件(文件名为jdbc.properties)
<context:property-placeholder location="classpath:jdbc.properties"/>
加载多个文件
<context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>
system-properties-mode=“NEVER”/> 表示不加载系统属性,防止加载参数的时候(如 username)加载到相同的系统属性
c)使用${}读取加载的属性值
专栏文章:
Spring框架(一):概述及简单使用(基于XML方式)