Spring框架 作者:rod johnson
Spring框架是啥: IOC、DI
Inverse of Control :IOC、IoC
什么是控制反转
控制:生成实例。 应用程序控制实例的生成
UserService userService = new UserServiceImpl();
反转:将实例生成权交给了Spring
UserService userService = Spring.getXXX();
生成权为什么要反转给Spring?
单例,让实例在Spring中以单例的形式存在,从Spring中获得实例始终保证是同一个实例。可以方便维护多个实例之间的关系
容器:Spring来管理实例的地方。 → IOC容器、Spring容器
组件:Spring容器中管理的实例叫组件。
Dependency Inject 依赖注入
应用程序和Spring容器
经过了控制反转,谁贫穷,谁富有?
应用程序穷、Spring容器富有
依赖:
谁依赖谁? 应用程序依赖Spring容器
为什么? Spring容器提供了应用程序必须的外部资源
注入:
谁注入谁? Spring容器注入给应用程序
注入了什么?注入了应用程序必须的资源、实例、值。。
map.put → 控制反转
map.get → 依赖注入
Aspect Oriented Programming 面向切面编程
OOP:Object Oriented Programming面向对象编程
AOP是在IOC和DI的基础上的做
增强:对容器中所管理的组件进行增强,动态代理 粒度更精细
开始使用Spring
1.1 创建一个maven工程,提供一个userService
1.2 引入依赖
spring-context、core、expression、beans、aop
jcl
写这一个导入会自动导入其他的
目的是啥?引入一些配置、注册组件(控制反转)
xml格式 → 头 schema约束 → 我们可以写哪一些标签、标签里的属性、标签里的子标签、标签的顺序
引入Spring的schema约束:
1、 已有的配置文件
2、 Spring官网(找到the context schema https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#spring-core)
3、 创建文件模板
在Spring配置文件中注册组件
将实例交给Spring容器来进行管理,我们要知道实例是谁
使用的是全限定类名
维护Spring容器中的组件之间的关系
再注册一个dao组件
property子标签调用set方法来完成的
关注这个过程
容器
ClasspathXmlApplicationContext
FileSystemXmlApplicationContext
AnnotationConfigApplicationContext
SpringMVC: WebApplicationContext
生产bean,生产全部bean,容器。ApplicationContext接口继承了BeanFactory接口
Spring核心 控制反转,控制实例的生成
默认使用的就是无参构造方法,最常用的方式
工厂里的生产方法是静态方法
工厂里的方法不是静态的方法
使用getBeansOfType可以获得所有注册过的、传入类型的组件
tips:双击shift可以去查找类
getObject
通过FactoryBean注册的组件类型:和getObject方法的返回值是相关的(getObject返回了啥,组件的类型就是什么)
在注册组件的时候,发现无法识别username,后来发现我只在User类里加了@Data注解,但是并没有在UserFactoryBean中写上
在注册的时候,会去检测是否实现了FactoryBean接口,如果实现了,会把getObject的返回值类型注册为组件类型
都可以注册组件
BeanFactory:是Bean的一个工厂,生产的是全部组件
FactoryBean:注册的特定类型的组件
singleton:组件在容器中以单例的形式存在。组件默认的作用域就是singleton。最常用的
prototype:原型。每一次取出都是一个全新的组件,每一次取出都实例化
5.1 组件注册
通过内存地址查看是否是同一个实例
Prototype的三个实例并不是同一个地址
什么是生命周期,为什么要使用生命周期?
容器中的组件的生命,产生开始到容器关闭时候经过哪一些方法?
容器中的组件要到达一个可用状态,可以依赖注入了(可以从容器中取出了)
最终是要使用组件(对象)提供的方法
在组件到达可用状态之前会执行一些方法,准备这个实例
如果在容器中注册了BeanPostProcessor组件,那么所有的组件都会去做BeanPostProcessor 的实现类的before和after方法
类本身不知道BeanName,BeanFactory以及ApplicationContext,只有application知道,所以只能用一些方法来让它知道
接口
容器中的所有组件都会执行到
(看流程图)InitializationBean会在before和after之间来执行
<!-- init-method告诉容器哪个是自定义的初始化方法 --> <bean class="com.cskaoyan.bean.LifeCycleBean" init-method="costomInit"/> <bean class="com.cskaoyan.service.UserServiceImpl"/>
提供的接口DisposableBean的destroy
singleton:生命周期在容器初始化开始(立即加载)
protoype:获得组件的时候才开始生命期,没有destroy
生命周期的方法是否一定都执行到:不一定
为什么还要提供呢:在准备阶段提供这些方法能够执行到,提供不同的参数,这些方法之间存在先后顺序
之前写了个bean标签
使用注解来注册组件,设置了一个包目录,找到所有的类,遍历,是否包含组件注册功能的注解
@Component 组件
@Service service
@Repository dao
@Controller(SpringMVC阶段才会去使用) controller
可以使用注解的value属性指定组件id;如果没有使用value属性,默认的组件id是类名的首字母小写
容器中的组件里才可以使用注入功能
其实维护的是组件之间的依赖关系
组件注入功能做的工作是,从容器中取出组件给其他类的成员变量赋值
@Autowired注解是最常用的,默认按照类型注入
注入功能:为容器中的组件的成员变量赋值,维护组件之间的依赖关系
注意:注入功能要在容器中的组件里使用
@Scope:直接写在类上
目的是为了方便的测试组件提供的方法
从容器中取出组件