文章目录
1、Spring
Spring地址:
https://spring.io
Spring技术的优点:
Spring家族(Spring全家桶):
2、SpringFramework系统架构
Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基。
Spring Framework系统架构图如下:
核心概念
代码书写现状–耦合度偏高
基于上面的问题,我们考虑
使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象
Ioc(Inversion of Control)即,控制反转,这种思想核心在于
把对象的创建控制权由程序转移到外部
,以达到解耦的目的。
-
Spring技术对Ioc思想进行了实现—提供一个
Ioc容器
,来充当Ioc思想中的”外部” -
Ioc容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在Ioc容器中统称
Bean
-
在容器中建立bean与bean之间的依赖关系的整个过程,称为
依赖注入
(DI,Dependency Injection)
小结:
Ioc入门案例
源码结构如下:
使用之前耦合度较高的方式,则:
使用Ioc思想之后,先准备一个配置文件applicationContext.xml:
(新建没有Spring Config选项的,先导入Spring坐标,看下图:)
接下来新建App2.java文件,使用Ioc思想:
- 获取Ioc容器
- 获取bean
DI入门案例
做完上面的Ioc,还遗留两个问题:
-
删除业务层中使用new对象创建的dao对象,提供set方法给容器调用,用来传对象
-
在配置文件中配置两个bean之间的关系,Service中注入dao
3、Bean
Bean的配置
Bean的基础配置
属性中,除了id,也可用name属性来标识,name是在起别名。多个别名之间用逗号封号空格都行。getBean方法中除了传入id,传入别名name也可,ref属性中也可以用name代替id
注意,当getBean传入的id或者name不存在,出现异常:
两次获取bookService对象:
根据输出结果可以看到这是同一个对象:
由此,使用scope属性来控制创建出来的实例是一个还是多个:
关于bean默认是单例的一些思考:如果这个对象是每次会记录一些成员变量的属性值,即不能复用,那这种对象就不适合交给容器进行管理。
Bean的实例化
Bean的本质就是对象,创建bean是使用构造方法完成的
Bean的实例化--构造方法
Spring创建对象的时候默认使用对应类的无参构造,而且构造方法是private也可以成功(底层走的是反射)
当手写了有参,无参被覆盖后,再执行程序:
在这种创建bean的方法中,如果无参构造不存在,则有
BeanCreationException异常
Bean的实例化--静态工厂
相比于之前的使用构造方法,静态工厂即某个工厂类中写一个get方法,来return一个需要的对象。一般为了兼容早期的遗留系统使用。
Bean的实例化--实例工厂与FactoryBean
和之前的静态方法不同的是,实例工厂即通过工厂类的实例方法来造对象。
如此,有两个缺陷,一是工厂对象的创建,而是创建所需对象
由此有了另一种思路:
此时的配置文件就只需:
Bean的生命周期
-
初始化容器
- 创建对象(new,分一块内存)
- 执行构造方法
- 执行属性注入(set方法)
- 执行bean的初始化方法
-
使用bean
- 执行业务操作
-
关闭或销毁容器
- 执行bean的销毁方法
使用自己定义的方法对bean的生命周期进行控制:
也可以直接实现这两个接口,然后重写方法来完成,这样就不用在xml文件中加配置了:
注意到:初始化bean的时机是在set完属性之后,而销毁bean的时机是
容器关闭前触发bean的销毁
而容器关闭的方式有两种:
- 使用ConfigurableApplicationContext接口的close方法
- 注册关闭钩子,这样程序运行完退出JVM前会先关闭容器再退出虚拟机
bean的一些总结:
4、依赖注入DI
setter注入和构造器注入
依赖注入描述了在容器中建立bean与bean之间依赖关系的过程,可以使用set方法或者构造方法来完成:
使用setter注入引用类型
-
在bean中定义引用类型的属性,并提供相应的set方法
-
在xml配置中使用property标签的ref属性来注入引用类型的对象,name后是属性名,ref后是参照对象的id
需要注入多个引用类型属性的时候,再加property标签就行
使用setter注入简单数据类型
- 提供对应属性的set方法
- 还是使用property标签,不同的是不再用引用类型专属的ref,而是value
构造器注入
-
定义引用类型属性并提供构造方法
-
xml配置中使用constructor-arg标签,name属性是构造方法中的形参名,不再是属性名。ref属性和之前一样。name是形参名,这样耦合度很高,可以用type属性(即按形参类型区分注入)或者index属性(按照形参位置注入)
-
对于普通类型,也是提供构造方法,使用constructor-arg标签
依赖自动装配
Ioc容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程,有以下几种方式:
- 按类型
- 按名称
- 按构造方法
- 不启用自动装配
配置中使用bean标签autowrite属性设置自动装配的类型:
举例:
自动装配的注意点:
集合注入
定义集合类型的属性,提供set方法:
修改对应的bean,添加property标签:
运行:
案例–数据源对象管理
管理一个陌生的第三方的bean,以两个数据源对象为例:
DruidDataSource
-
添加坐标
-
配置管理bean
-
测试
ComboPooledDataSource
加载properties文件
观察到上面管理bean的时候,数据库的很多配置信息直接写在标签中,不合规范。将数据库配置信息写入properties文件:
在Spring中加载properties文件,步骤如下:
-
开启context的命名空间
-
使用context空间加载properties文件
-
使用属性占位符${}读取properties文件中的属性
加载properties文件的一些其余情况:
依赖注入相关总结:
5、容器
创建容器的两种方式
- 从类路径加载配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
- 从文件系统下加载配置文件
ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\applicationContext.xml");
不管以上哪种方式,都可加载多个配置文件,用逗号隔开,相当于把两部分bean放一起管理了
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml","bean2.xml");
获取bean的三种方式
- 使用bean名称获取
BookDao bookDao = (BookDao)ctx.getBean("bookDao");
- 使用bean名称获取并指定类型(此时不再需要强转)
BookDao bookDao = ctx.getBean("bookDao",BookDao.class);
- 使用bean的类型获取(此时容器中这个类型的bean只能有一个)
BookDao bookDao = ctx.getBean(BookDao.class);
容器类层次结构图
IDEA中打开类的继承结构Ctrl+H