一、认识Spring
1.1、Spring家族
SpringFramework: Spring框架:是Spring中最早核心的技术,也是所有其他技术及的基础。
SpringBoot:Spring是用来简化开发。而SpringBoot是来帮助Spring在简化的基础上能更快速进行开发。
SpringCloud:这个是用来做分布之微服务架构的相关开发。
除了上面的这三个技术外,还有很多其他的技术,也比较流行,如SpringData,SpringSecurity等,这些都可以被应用在我们的项目里。
二、Spring框架:
在我们写代码的时候通常修改代码要经过以下步骤:
修改源码--编译--打包--部署--重启
每修改一次代码就要经过这些步骤,当项目比较大的时候重新编译甚至需要几个小时,大大的不方便,因此我们可以通过反射来解决问题。
反射的特点:可以运行时修改。
dao:数据库的增删改查
service:业务处理
servlet:前后端交互
通过反射加载驱动:
Class.forName(" 类的全类名:即包名加类名 ")
通过Class类加载获得类的Class加载器。
功能:类的加载器可以获得类中的东西,相当于解剖的手术刀
即:属性(存储数据),构造方法(创建对象),功能方法(完成功能)
1.获取类中的属性:
getFields()//获取所有公开的成员变量,包括继承变量
getDeclaredFields()//获取本类定义的成员变量,包括私有,但不包括继承的变量
2.获取类中的构造方法
getConstructors()//获取所有的公开的构造方法
getDeclaredConstructors()//获取所有的构造方法,包括私有
3.获取类中的功能方法
getMethods()//获取所有可见的方法,包括继承的方法
getDeclaredMethods()//获取本类定义的的方法,包括私有,不包括继承的方法
三,IOC/DI
IOC控制反转:
(1)什么是控制反转呢?
使用对象时,由主动new产生对象转换为由==外部=提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转
- 业务层要用数据层的类对象,以前是自己new的
- 现在自己不new了,交给别人[外部]来创建对象
- 别人[外部]就反转控制了数据层对象的创建权
那么,别人[外部]指定是什么呢?
(2)Spring和IOC之间的关系是什么呢?
- Spring技术对IOC思想进行了实现
- Spring提供了一个容器,称为==lOC容器==,用来充当IOC思想中的“外部”
- IOC思想中的别人[外部]指的就是Spring的IOC容器
(3)IOC容器的作用以及内部存放的是什么?
- IOC容器负责对象的创建、初始化等一系列工作,其中包含了数据层和业务层的类对象
- 被创建或被管理的对象在IOC容器中统称为==Bean==
- IOC容器中放的就是一个个的Bean对象
(4)当I0C容器中创建好service和dao对象后,程序能正确执行么?
- 不行,因为service运行需要依赖dao对象
- IOC容器中虽然有service和dao对象,但是service对象和dao对象没有任何关系,需要把dao对象交给service也就是说要绑定service和dao对象之间的关系,像这种在容器中建立对象与对象之间的绑定关系就要用到DI:
通俗的讲:IOC:控制反转,以前依赖的对象自己直接new,现在不需要new,框架会自动注入对象,创建对象的权利转移给了框架;
DI:依赖注入。
(1)什么是依赖注入呢?
业务层要用数据层的类对象,以前是自己new的,现在自己不new了,靠别人[外部其实指的就是IOC容器]来给注入进来。这种思想就是依赖注入
在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入
(2)IOC容器中哪些bean之间要建立依赖关系呢?
这个需要程序员根据业务需求提前建立好关系,如业务层需要依赖数据层,service就要和dao建立依赖关系
通俗的讲:一个BookService类的功能需要依赖另外一个BookDao类配合,同时需要赋上一 个具体的对象,则成这种关系是依赖注入;
具体使用:
1.创建项目,导入spring的jar包
2.按照如下目录结构创建接口及其实现类,做好准备工作
servlet层
public class BookServlet {
BookService bookService;
@Test
public void add(){
System.out.println("BookServlet...add");
//1.获得IOC容器
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("Spring.xml");
//2.根据名字从容器中获取对象
bookService = (BookService) context.getBean("bookService");
bookService.save();
}
}
service层
接口:
public interface BookService {
void save();
}
实现类:
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
@Override
public void save() {
System.out.println("BookServiceImpl...save");
bookDao.insert();
}
}
public interface BookDao {
public void insert();
}
实现类:
public class BookDaoImpl implements BookDao {
@Override
public void insert() {
System.out.println("BookDaoImpl......insert");
}
}
注意:此时项目没法执行,因为没有做依赖对象的注入。
3.使用spring完成IOC的配置和DI依赖注入
?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">
<!--把所有对象创建到spring的IOC容器中,并起上名字
id:表示给对象起名字
class:类的全类名
-->
<bean id="bookDao" class="com.chen.dao.impl.BookDaoImpl"></bean>
<bean id="bookService" class="com.chen.service.impl.BookServiceImpl">
<!--spring的依赖注入:property表示BookServiceImpl的属性,常规属性使用value赋值,
类型属性使用ref引用-->
<property name="name" value="张三"/>
<property name="bookDao" ref="bookDao"/>
</bean>
</beans>
bean 标签表示把对应 class 的对象创建到 IOC 容器中,如果当前对象有依赖的其他对象,那么可以 通过property 对依赖的对象使用 ref 引用容器中已经注册过的对象。
注意:BookServiceImpl需要给bookDao属性设置setter方法,框架才能自动注入
对于基本数据类型(包括String),指定属性值使用"value"属性,而对于引用类型使用"ref"属性。
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
@Override
public void save() {
System.out.println("BookServiceImpl...save");
bookDao.insert();
}
}
构造器注入:
- 使用constructor-arg标签进行依赖注入。name属性要与实现类中提供的形参类型和个数一致,否则将会报错。ref属性指向的是spring的IOC容器中其他bean对象
- 在BookServiceImpl中定义引用类型属性,提供有参的构造方法
public class BookServlet {
BookService bookService;
@Test
public void add(){
System.out.println("BookServlet...add");
//1.获得IOC容器
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("Spring.xml");
//2.根据名字从容器中获取对象
bookService = (BookService) context.getBean("bookService");
bookService.save();
}
}
集合注入:常见的集合类型有哪些?
- 数组
- List
- set
- Map
再重新创建一个BookService的接口实现类BookServiceVip
使用相应标签(list、set、array、map...)对属性值进行注入
<property name="list">
<list>
<value>张三</value>
<value>小明</value>
<value>小美</value>
</list>
</property>
<property name="set">
<set>
<value>南阳</value>
<value>洛阳</value>
<value>安阳</value>
</set>
</property>
<property name="map">
<map>
<entry key="sex" value="男"></entry>
<entry key="age" value="19"></entry>
<entry key="phone" value="110"></entry>
</map>
</property>
注解:
在BookDaoimpl上添加@Component注解
注:@Component注解不可以添加在接口上,因为接口是无法创建对象的
配置Spring的注解包扫描
为了让Spring框架能够扫描到写在类上的注解,需要在配置文件上进行包扫面
@component:组件,Spring将管理的bean视作自己的一个组件scan:扫描
base-package指定Spring框架扫描的包路径,它会扫描指定包及其子包中的所有类上的注解
包路径越多[如:comshidaoimpl],扫描的范围越小速度越快
@Autowired:自动注入属性。自动注入优先按照类型注入,如果有多个对象,按照名字进行注入
之前是根据名字从容器中获取对象
注解是根据类型获得对象,前提是类型有唯一对象