spring的核心功能
1、ioc/DI
2、AOP
3、事务
Spring 核心容器 Core Container:spring启动最基本的条件
-
Spring Core
-
Spring Bean
-
Spring Context
-
SpEL (Spring Expression Language)
一、spring ioc
ioc控制反转:控制权的转移,应用程序本身不负责依赖对象的创建和维护,而是由外部容器负责创建和维护
DI依赖注入:是控制反转的一种实现方式
注:
- 控制反转:获得依赖对象的过程被反转
- 控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入,于是控制反转的另一个名称是依赖注入
- 实现ioc的方法:注入
- 所谓依赖注入:就是由IOC容器在运行期间动态地将某种依赖关系注入到对象之中。
总结:ioc完成的事情原先由程序员主动通过new实例化对象转交给spring负责:
传统的创建对象的方法是直接通过 new 关键字,而 spring 则是通过 IOC 容器来创建对象,也就是说我们将创建对象的控制权交给了 IOC 容器。
我们可以用一句话来概括 IOC:IOC 让程序员不在关注怎么去创建对象,而是关注与对象创建之后的操作,把对象的创建、初始化、销毁等工作交给spring容器来做。
作用:解耦 :1、程序员不需要管理对象 2、解除了对象管理与程序员之间的耦合
1.什么是 Spring IoC 容器
Spring 框架的核心是 Spring IoC 容器。容器创建 Bean 对象,将它们装配在一起,配置它们并管理它们的完整生命周期。
- Spring 容器使用依赖注入来管理组成应用程序的 Bean 对象。
- 容器通过读取提供的配置元数据 Bean Definition 来接收对象进行实例化,配置和组装的指令。
- 该配置元数据 Bean Definition 可以通过 XML,Java 注解或 Java Config 代码提供。
2、依赖注入
当一个类A中需要依赖另一个类B对象时,把B赋值给A的过程(另一个对象实例化的过程)叫做依赖注入。
spring注入是指在启动spring容器加载bean配置的时候,完成对变量的赋值行为,
可以通过三种方式完成
-
基于注解的注入
-
构造方法注入
-
setter 注入
3、Spring 提供了两种IoC 容器,是 BeanFactory、ApplicationContext 。
BeanFactory
BeanFactory 在
spring-beans项目提供。
BeanFactory ,就像一个包含 Bean 集合的工厂类。它会在客户端要求时实例化 Bean 对象。
ApplicationContext
ApplicationContext 在
spring-context项目提供。
ApplicationContext 接口扩展了 BeanFactory 接口,它在 BeanFactory 基础上提供了一些额外的功能
区别:ApplicationContext 的初始化和BeanFactory 有一个重大的区别:BeanFactory在初始化容器时,并未实例化Bean,直到第一次访问某个Bean 时才实例目标Bean;而ApplicationContext 则在初始化应用上下文时就实例化所有单实例的Bean 。
4、应用上下文
spring应用上下文,说的简单点就是容器的对象,是对spring容器抽象的实现,我们常见的ApplicationContext本质上来说是一种维护Bean的定义和对象之间协作关系的高级接口,spring的核心是容器,有且不止一个容器:如下
-
ClassPathXmlApplicationContext---从类路径下的xml配置文件中加载上下文定义,把应用上下文定义当作类资源。
-
FileSystemXmlApplicationContext--读取文件路径下的XML配置文件并加载上下文定义。
-
XmlWebApplicationContext--读取web应用下的XML配置文件并装载上下文定义。
无论我们是从文件路径下装载应用上下文还是从类路径下装载应用上下文,将Bean加载到Bean工厂的过程都是相似的,例如下列代码展示了如何加载一个FileSystemXmlApplicationContext:
ApplicationContext context=new FileSystemXmlApplicationContext("D:foo.xml");
类似的,你也可以用ClassPathXmlApplication从应用的类路径下加载应用上下文:
ApplicationContext context=new ClassPathXmlApplication("foo.xml");
使用FileSystemXmlApplicationContext与ClassPathXmlApplication的区别在于:FileSystemXmlApplicationContext在指定的文件系统路径下查找foo.xml文件;而ClassPathXmlApplication是在所有的类路径(包含jar文件)下查找foo.xml文件。
通过现有的应用上下引用,你可以调用应用上下文的getBean()方法从Spring容器中获取Bean。
5、ioc的初始化过程
IoC 在 Spring 里,只需要低级容器就可以实现,2 个步骤:
-
a. 加载配置文件,解析成 BeanDefinition 放在 Map 里。
-
b. 调用 getBean 的时候,从 BeanDefinition 所属的 Map 里,拿出 Class 对象进行实例化,同时,如果有依赖关系,将递归调用 getBean 方法 —— 完成依赖注入。
上面就是 Spring 低级容器(BeanFactory)的 IoC。
至于高级容器 ApplicationContext,他包含了低级容器的功能,当他执行 refresh 模板方法的时候,将刷新整个容器的 Bean。同时其作为高级容器,包含了太多的功能。一句话,他不仅仅是 IoC。他支持不同信息源头,支持 BeanFactory 工具类,支持层级容器,支持访问文件资源,支持事件发布通知,支持接口回调等等。
二、spring bean
- Bean 由 Spring IoC 容器实例化,配置,装配和管理。
- Bean 是基于用户提供给 IoC 容器的配置元数据 Bean Definition 创建。
Spring Bean 的初始化流程如下
-
实例化 Bean 对象
-
Spring 容器根据配置中的 Bean Definition(定义)中实例化 Bean 对象。
Bean Definition 可以通过 XML,Java 注解或 Java Config 代码提供。
-
Spring 使用依赖注入填充所有属性,如 Bean 中所定义的配置。
-
-
Aware 相关的属性,注入到 Bean 对象
- 如果 Bean 实现 BeanNameAware 接口,则工厂通过传递 Bean 的 beanName 来调用
#setBeanName(String name)方法。 - 如果 Bean 实现 BeanFactoryAware 接口,工厂通过传递自身的实例来调用
#setBeanFactory(BeanFactory beanFactory)方法。
- 如果 Bean 实现 BeanNameAware 接口,则工厂通过传递 Bean 的 beanName 来调用
-
调用相应的方法,进一步初始化 Bean 对象
- 如果存在与 Bean 关联的任何 BeanPostProcessor 们,则调用
#preProcessBeforeInitialization(Object bean, String beanName)方法。 - 如果 Bean 实现 InitializingBean 接口,则会调用
#afterPropertiesSet()方法。 - 如果为 Bean 指定了 init 方法(例如
<bean />的init-method属性),那么将调用该方法。 - 如果存在与 Bean 关联的任何 BeanPostProcessor 们,则将调用
#postProcessAfterInitialization(Object bean, String beanName)方法。
- 如果存在与 Bean 关联的任何 BeanPostProcessor 们,则调用
Spring Bean 的销毁流程如下:
- 如果 Bean 实现 DisposableBean 接口,当 spring 容器关闭时,会调用
#destroy()方法。 - 如果为 bean 指定了 destroy 方法(例如
<bean />的destroy-method属性),那么将调用该方法。
总结:
1.Spring对Bean进行实例化,默认bean是单例。
2.Spring 将值和Bean的引用注入到Bean对应的属性中。
3.如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给setBeanName()接口方法。
4.如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()接口方法,将BeanFactory容器实例传入。
5.如果Bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()接口方法,将上下文的引用传入。
6.如果Bean实现了BeanPostProcessor接口,Spring将调用它们的postProcessBeforeInitialization()接口方法。
7.如果Bean实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()接口方法,类似地,如果Bean使用init-method声明了初始化方法,该方法也会被调用。
8.如果Bean实现了BeanPostProcessor接口,Spring将调用他们的postPoressAfterInitialization()方法。
9.此时此刻,Bean准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁。
10.如果Bean实现了DisposableBean接口,Spring将调用他的destory()接口方法,同样,如果Bean使用destory-method声明了销毁方法,该方法也会被调用。
spring aop
1、Spring AOP 中的动态代理主要有两种方式,
-
JDK 动态代理
JDK 动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是 InvocationHandler 接口和 Proxy 类。
-
CGLIB 动态代理
如果目标类没有实现接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类。当然,Spring 也支持配置,强制使用 CGLIB 动态代理。
CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用 CGLIB 做动态代理的。
2、在 Spring AOP 中,有两种方式配置 AOP 切面:
- 基于 XML 方式的切面实现。
- 基于 注解 方式的切面实现。
3、
Spring AOP是基于动态代理实现的,代理类封装了目标类,并拦截被通知方法的调用,再把调用转发给真正的目标bean。
参考: