1. spring
1.1spring是什么
- spring是一个开源框架,为了解决企业级编程开发中的复杂性,实现敏捷开发。
- 是一个轻量级的DOI(控制反转)和AOP(面向切面)容器的框架
1.2spring的特征
-
轻量:从大小和开销方面来说spring都是轻量级的。
-
控制反转:通过一种称作控制反转(IOC)的技术来促进低耦合。即不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
-
面向切面:spring支持面向切面编程,将业务逻辑和系统级服务分离。
-
容器:spring包含并管理应用对象的配置和生命周期。
-
框架:spring可以将简单的组件配置、组合成为复杂的运用。
-
非侵入式:spring应用中的对象不依赖于spring的特定类。
1.3侵入式与非侵入式
-
侵入式
使用该框架的功能强制要求用户代码继承框架提供的特定类或实现相应的接口。即用户代码需要“知道”框架的代码
优点:能够让用户和框架更好的结合,更容易更充分的发挥框架提供的功能。
缺点:让用户代码对框架产生依赖,即无法再框架外使用该代码,不利于代码的复用。
-
非侵入式
允许应用系统去自由选择和组装框架的各个模块,并且不强制要求用户去继承框架中的类和接口。即从类的编写者来看,察觉不到框架的存在。
优点:允许开发出来的运用程序能够自由移植,不需要在意运行的环境。即不需要通过修改核心代码来实现代码的复用。
1.4spring的特点(或者说优点)
-
方便解耦,简化开发
通过IOC容器,我们将对象之间的依赖关系交由spring来控制,用户不在为一些底层需求(如单实例模式类、属性文件解析等)编写代码,可以专注于上层的应用。
-
AOP编程的支持
通过AOP功能,能够方便进行面向切面编程。
-
声明式事务的支持
我们可以从事务管理代码中脱离出来,通过声明式方式灵活的进行事务的管理,提高开发效率和质量。
-
方便程序的测试
Spring对Junit4支持,可以通过注解方便的测试Spring程序。
-
方便集成各种优秀框架
spring不排斥其它优秀的开源框架,其内部提供了对各种框架的直接支持
-
降低Java EE API使用难度
spring对Java EE开发中一些难用的API进行了简单的封装,降低它们的使用难度。
综上所述,我们可以得知spring采取了如下策略来降低Java的开发难度:
- 基于POJO的轻量级和最小侵入性编程;
- 通过依赖注入(DI)和面向接口i实现松耦合;
- 基于切面和惯例进行了声明式编程;
- 通过切面和模板减少样式代码;
2. IOC
2.1 spring IOC容器背景
我们都知道在面向对象的软件设计中,业务逻辑的实现,是通过各个对象相互合作。
观察机械手表的齿轮,我们可以发现各个独立的齿轮在相互的啮合中,带动指针的旋转,就想我们软件中的各个对象,其齿轮间的啮合关系,就像对象之间的耦合关系。对象间的耦合是无法避免的,也是必须存在的,我们需要它来实现协同工作,就像齿轮的啮合来带动指针的转动。但随着发展,对象之间的关系依赖愈发复杂,多重依赖的情况常常发生。而如果对象之间的耦合度过高的系统,必然和出现牵一发而动全身的情形,即一个齿轮的问题,而使得整个齿轮组转到出现问题
当然耦合度不止存在于对象之间,各个模块,软件硬件之间也存在,而为了解决对象之间的耦合度过高问题,IOC应时而生,用来实现对象间的解耦。
2.2 什么是IOC
IOC—Inversion Of Control,即“控制反转”。
对于传统的Java SE程序的设计来说,我们直接在对象内部通过new进行对象的创建,即通过程序代码来进行对象的操作,来主动实现创建依赖对象;
IOC理论大致是:借助于“第三方”来实现具有依赖关系的对象之间的解耦。如下图:
通过引入第三方,即IOC容器,来隔开各个对象,使得各个对象间的耦合度降低,齿轮间的转动开始依赖第三方了,我们由此可以看出对象的控制权全部交由第三方,即对象的创建不再由我们自己来创建,而是由IOC容器来创建,即IOC控制了对象,控制了外部资源的获取。IOC有时被比喻为“粘合剂”,是因为它的作用就像粘合剂一样,把各个对象粘合在一起发挥作用。
我们将中间的齿轮拿走,在观察该系统:
此时的画面,就是我们实现这个系统所需要完成的内容。可以看出,图中的A、B、C、D之间不再啮合,即它们之间已经没有了耦合关系,所以我们在实现A的时候,就不再关注于B、C、D的实现,对象之间的依赖关系已经降低到了最低。借此我们可以明白,什么是反转,即依赖对象的创建和注入由容器来完成。而为什么是反转?是因为对象依赖对象的创建和查找,不再由自己主动进行,而是由容器帮我们进行,对象只能被动的接受依赖对象,即对象的获取反转了。
总结:对象获得依赖对象的过程,由主动变为了被动,控制权发生了颠倒。这就是控制颠倒(IOC)的由来。其实现的原理是工厂模式和反射机制。
2.3 DI(依赖注入)
依赖注入(DI),控制反转的另一个名字,也是其具体的实现形式。所谓的依赖注入,就是IOC容器在运行期间,动态的将某种依赖关系注入到对象之中。所以通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关系具体的资源来自何处,由谁来实现。
IOC和DI。其实质上是同一个概念的不同角度的描述,即IOC是一个广泛的概念,其中心思想在于控制权的反转,而没有指明哪一部份的控制权,Spring则是在对象的创建、释放、配置等控制权反转到自身。进而由设计大师Martin Fowler针对Spring这类型IoC实现对象提出了一个新的名词『Dependency Injection』。
进而我们引申出依赖注入的实现方式:接口注入(Interface Injection),Setter方法注入(Setter Injection)和构造器注入(Constructor Injection)三种方式。接口注入因为其较差的灵活性和易用性,已在spring4中被废弃。
构造器依赖注入:构造器依赖注入通过容器出发一个类的构造器来实现,该类由一系列参数,每个参数代表对一个其他类的依赖。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tDIb6ckj-1680171419179)(C:/Users/%E9%A9%AC%E6%AD%A3%E4%B9%89/AppData/Roaming/Typora/typora-user-images/image-20220404180147587.png)]
setter方法注入:setter方法注入是容器通过调用无参构造器或无参static工厂方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CkFxPZBO-1680171419180)(C:/Users/%E9%A9%AC%E6%AD%A3%E4%B9%89/AppData/Roaming/Typora/typora-user-images/image-20220404180201108.png)]
2.4 IOC的优缺点
第一、软件系统中引入了第三方IOC容器,虽然降低了代码量,但是生成对象的步骤变得有些复杂,本来是两者之间的事情,又凭空多出一道手续,所以,我们在刚开始使用IOC框架的时候,会感觉系统变得不太直观。所以,引入了一个全新的框架,就会增加团队成员学习和认识的培训成本,并且在以后的运行维护中,还得让新加入者具备同样的知识体系。
第二、由于IOC容器生成对象是通过反射方式,在运行效率上有一定的损耗。如果你要追求运行效率的话,就必须对此进行权衡。
第三、具体到IOC框架产品(比如:Spring)来讲,需要进行大量的配制工作,比较繁琐,对于一些小的项目而言,客观上也可能加大一些工作成本。
第四、IOC框架产品本身的成熟度需要进行评估,如果引入一个不成熟的IOC框架产品,那么会影响到整个项目,所以这也是一个隐性的风险。
2.5 IOC有什么作用
- 管理对象的创建和依赖关系的维护,对象的创建并不是一个简单的事情,在对象关系比较复杂的情况时,如果依赖关系由程序员来维护,会显得十分困难。
- 解耦,对象的维护将由容器来代替我们进行。
- 托管了类的生成过程,类的产生将由容器来进行,程序将不再管理类是如何生成的。
3. AOP
3.1 什么是AOP
一句话概括,AOP就是能够让我们在不影响原有程序功能(原代码)的情况下,为软件进行功能扩展。
AOP全称Aspect Oriented Programming意为面向切面编程,也是通过预编译方法和运行期动态代理的方式实现不修改源代码的情况下给程序动态统一添加功能的技术。
AOP技术利用一种称为“横切”的技术,剖解开封装对象的内部,将影响多个类的公共行为封装到一个可重用的模块中,并将其命名为Aspect
切面。所谓的切面,简单来说就是与业务无关,却为业务模块所共同调用的逻辑,将其封装起来便于减少系统的重复代码,降低模块的耦合度,有利用未来的可操作性和可维护性。
利用AOP可以对业务逻辑各个部分进行隔离,从而使业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高开发效率。
AOP的使用场景主要包括日志记录、性能统计、安全控制、事务处理、异常处理等。
例如:日志功能,日志代码往往横向散布在所有对象层次中,而与之对应的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理、透明的持续性等也都是如此,这种散布在各处而且无关的代码被称为横切(cross-cutting)。在OOP设计中,它们会导致大量重复的代码,不利用模块的重用。
3.2 补充一下AOP的一些相关术语
- Aspect(切面):
- 切面用来装载切入点
PointCut
和通知Advice切面通常是一个类,可以定义切入点和通知。 - Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。连接点是程序在运行过程中能够插入切面的点。
- Pointcut(切点):切入点是带有通知的增强点,切点用于定义通知该切入到哪些连接点中,其通过切入点的正则表达式来精确匹配该通知需要切入到的连接点。
- Advice(增强):通知是AOP在特定切入点上执行的增强处理模式拦截到连接点之后要执行的代码,它通过 前置通知(before)、后置通知(afterReturning) 和环绕通知 (around)、异常通知(afterThrowing)、最终通知(after) 来区别是在每个 joint point 中代码执行的位置和什么情况才执行。
- Target(目标对象):织入 Advice 的目标对象.。
- Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程
Proxy
代理对象:代理对象是AOP创建的对象,包含通知,代理是目标对象的加强。 代理是将通知应用到目标对象之后被动态创建的对象,可以简单理解代理对象的功能等同于目标对象的核心业务逻辑功能加上共有功能。代理对象对于使用者而言是透明的,是程序运行过程中的产物。
3.3 AOP的本质
AOP是实现分散关注的编程方法,将关注封装在切面中。如何分散关注呢?将需求功能从不相关的类中分离出来,同时使多个类共用一个行为,一旦行为发生变化,不必修改多个类,只修改行为即可。
AOP将软件系统划分为两个部分:核心关注点、横切关注点,业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的特点是经常发生在核心关注点的多个位置,而且它们功能基本相似。AOP的作用在于分离系统中的各个关注点,将核心关注点和横切关注点分离开来。
3.4 我所理解的AOP原理
spring用代理类来包裹切面,把他们织入到Spring管理的bean中。也就是说代理类伪装成目标类,它会截取目标类中的方法的调用,让调用者对目标类的调用都先变成调用伪装类,伪装类中就先执行了切面,再把调用转发给真正的目标bean。
spring代理由2种模式:
前一种兄弟模式,spring会使用JDK的java.lang.reflect.Proxy类,它允许Spring动态生成一个新类来实现必要的接口,织入通知,并且把对这些接口的任何调用都转发到目标类。
后一种父子模式,spring使用CGLIB库生成目标类的一个子类,在创建这个子类的时候,spring织入通知,并且把对这个子类的调用委托到目标类。
这就好比,一个人让你办件事,每次这个时候,你弟弟就会先出来,当然他分不出来了,以为是你,你这个弟弟虽然办不了这事,但是他知道你能办,所以就答应下来了,并且收了点礼物(写日志),收完礼物了,给把事给人家办了啊,所以你弟弟又找你这个哥哥来了,最后把这事办了的还是你自己。但是你自己并不知道你弟弟已经收礼物了,你只是专心把这件事情做好。
顺着这个思路想,要是本身这个类就没实现一个接口呢,你怎么伪装我,我就压根没有机会让你搞出这个双胞胎的弟弟,那么就用第2种代理方式,创建一个目标类的子类,生个儿子,让儿子伪装我。
这次的对比就是,儿子先从爸爸那把本事都学会了,所有人都找儿子办事情,但是儿子每次办和爸爸同样的事之前,都要收点小礼物(写日志),然后才去办真正的事。当然爸爸是不知道儿子这么干的了。这里就有件事情要说,某些本事是爸爸独有的(final的),儿子学不了,学不了就办不了这件事,办不了这个事情,自然就不能收人家礼了。
4. Spring Bean
4.1 什么是Bean
简而言之,就是由Spring IOC 容器初始化,装配和管理的对象。
4.2 Spring 支持的几种bean的作用域
- singleton:bean在每个Spring ioc 容器中只有一个实例(默认属性)。
- prototype:一个bean的定义可以存在多个实例。
- request:每一次HTTP请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。
- session:在一个HTTP Session中,一个bean定义仅对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
- global-session:全局 session 作用域,仅仅在基于 Portlet 的 web 应用中才有意义,Spring5 已经没有了。Portlet 是能够生成语义代码(例如:HTML)片段的小型 Java Web 插件。它们基于 portlet 容器,可以像 servlet 一样处理 HTTP 请求。但是,与 servlet 不同,每个 portlet 都有不同的会话。
ps:频繁的使用prototype属性会带来很多的性能开销,因为其会哦造成bean实例频繁的创建与销毁。
4.3 Spring中bean的生命周期
对于普通的Java对象来说,它们的生命周期就是:
- 初始化
- 当该对象不再被使用时,被垃圾回收机制进行回收。
而对于Spring Bean 的生命周期来说:
- 实例化Instantiation
- 属性赋值Populate
- 初始化 Initialization
- 销毁Destruction
即实例化–>属性赋值–>初始化–>销毁
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 实例化阶段
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
...
Object exposedObject = bean;
try {
// 属性赋值阶段
this.populateBean(beanName, mbd, instanceWrapper);
// 初始化阶段
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
...
}
...
}
至于销毁,是在容器关闭时调用,详见ConfigurableApplicationContext#close()。
其生命周期如下图:
spring bean 的生命周期扩展点
4.3.1 InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor该接口继承了BeanPostProcessor接口。该接口主要的作用在于目标对象的实例化过程中需要进行处理的事情,包括实例化对象的前后过程以及实例的属性设置。
4.3.1.1 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 调用点
- Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
我们首先要明白该方法执行的位置,在实例化之前调用。所以这个时候目标对象还没有完成实例化,其返回值类型为Object,所以我们可以返回任意的类型,所以我们可以返回一个值来代替原本该生成的目标对象的实例(一般都是代理对象,这里为什么是代理对象,这就是我们AOP等功能实现的关键点),如果其返回了值,那么我们后续的Bean流程(实例化,初始化afterProperties)都不会再执行,其默认是返回null。
4.3.1.1 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation调用点
- boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException
正常情况下在实例化之后在执行populateBean之前调用,如果有指定的bean的时候返回false,那么后续的属性填充和属性依赖注入【populateBean】将不会执行,同时后续的postProcessPropertyValues将不会执行,但是初始化和BeanPostProcessor的仍然会执行。
- public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
实例化之后调用,在方法applyPropertyValues【属性填充】之前.返回值:如果返回null,那么将不会进行后续的属性填充,比如依赖注入等,如果返回的pvs额外的添加了属性,那么后续会填充到该类对应的属性中。
pvs:财产Values对象,用于封装指定类的对象,简单来说就是PropertyValue的集合,里面相当于以key-value形式存放类的属性和值。
pds:PropertyDescriptor对象数组,PropertyDescriptor相当于存储类的属性,不过可以调用set,get方法设置和获取对应属性的值
4.3.2 BeanPostProcessor
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
进入初始化接口:
我们先来看
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
- 首先获取到所有的后置处理器 getBeanPostProcessors()
- 在 for 循环中依次调用后置处理器的方法 processor.postProcessBeforeInitialization(result, beanName);
- 进入 postProcessBeforeInitialization 方法
- org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization
进入 invokeAwareInterfaces(bean);
方法,当前 bean 实现了 ApplicationContextAware 接口。
- ApplicationContextAwareProcessor#postProcessBeforeInitialization 首先判断此 bean 是不是各种的Aware,如果是它列举的那几个 Aware 就获取 Bean 工厂的权限,可以向容器中导入相关的上下文环境,目的是为了 Bean 实例能够获取到相关的上下文,如果不是它列举的几个 Aware,那就调用 invokeAwareInterfaces(bean),向容器中添加相关接口的上下文环境。
4.3.3 工厂后处理器方法(BeanFactoryProcessor 一系列接口)
包括 AspectJWeavingEnabler、CustomAutowireConfigurer、ConfigurationClassPostProcessor 等。这些都是 Spring 框架中已经实现好的 BeanFactoryPostProcessor,用来实现某些特定的功能。
我们知道 Spring IoC 容器初始化的关键环节就在 org.springframework.context.support.AbstractApplicationContext#refresh 方法中 ,容器创建的主体流程都在这个方法里面,这个方法是真的重要!!!
对于工厂后处理器方法老周这里直接带你看 invokeBeanFactoryPostProcessors(beanFactory); 方法,这个方法处理的是 BeanFactoryPostProcessor 接口的 Bean。调用方法如下:
跟到最重要的方法里去,代码虽长,但逻辑中规中矩。
BeanFactoryPostProcessor:一切处理 BeanFactory 的父接口
BeanDefinitionRegistryPostProcessor:实现了 BeanFactoryPostProcessor 接口的接口
流程说明:
- 调用 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(registry) 方法。参数 beanFactoryPostProcessors 传入的优先处理掉。然后获取容器注册的,对于这些 Bean 按照 PriorityOrdered 接口、Ordered、没有排序接口的实例分别进行处理。
- 调用 BeanFactoryPostProcessor#postProcessBeanFactory(beanFactory) 方法。备注:BeanDefinitionRegistryPostProcessor 属于 BeanFactoryPostProcessor 子接口。先处理属于 BeanDefinitionRegistryPostProcessor 接口实例的 postProcessBeanFactory(beanFactory) 方法,然后获取容器注册的。对于这些 Bean 按照 PriorityOrdered 接口、Ordered、没有排序接口的实例分别进行处理。
4.3.4 Aware类型的接口
Aware 类型的接口的作用就是让我们能够拿到 Spring 容器中的一些资源。基本都能够见名知意,Aware 之前的名字就是可以拿到什么资源,例如 BeanNameAware 可以拿到 BeanName,以此类推。调用时机需要注意:所有的 Aware 方法都是在初始化阶段之前调用的。
Aware 接口众多,这里同样通过分类的方式帮助大家记忆。Aware 接口具体可以分为两组,至于为什么这么分,详见下面的源码分析。如下排列顺序同样也是 Aware 接口的执行顺序,能够见名知意的接口不再解释。
-
Aware Group1(调用invokeInitMethods方法)
- BeanNameAware
- BeanClassloaderAware
- BeanFactoryAware
-
Aware Group2(调用Aware和BeanPostProcessor# postProcessBeforeInitialization方法)
- EnvironmentAware
- EmbeddedValueResolverAware:这个知道的人可能不多,实现该接口能够获取 Spring EL 解析器,用户的自定义注解需要支持 SPEL 表达式的时候可以使用,非常方便。
- ApplicationContexrAware(ResourceLoderAware\AplicationEventPublisherAware\MessageSourceAware)
这几个接口可能让人有点懵,实际上这几个接口可以一起记,其返回值实质上都是当前的 ApplicationContext 对象,因为 ApplicationContext 是一个复合接口,如下:
Aware 调用时机源码分析
可以看到并不是所有的 Aware 接口都使用同样的方式调用。Bean××Aware 都是在代码中直接调用的,而 ApplicationContext 相关的 Aware 都是通过 BeanPostProcessor#postProcessBeforeInitialization() 实现的。感兴趣的可以自己看一下 ApplicationContextAwareProcessor 这个类的源码,就是判断当前创建的 Bean 是否实现了相关的 Aware 方法,如果实现了会调用回调方法将资源传递给 Bean。
BeanPostProcessor 的调用时机也能在这里体现,包围住 invokeInitMethods 方法,也就说明了在初始化阶段的前后执行。
关于 Aware 接口的执行顺序,其实只需要记住第一组在第二组执行之前就行了。
4.3.5 生命周期接口
实例化和属性赋值都是 Spring 帮助我们做的,能够自己实现的有初始化和销毁两个生命周期阶段。
-
InitializingBean 对应生命周期的初始化阶段,在上面源码的 invokeInitMethods(beanName, wrappedBean, mbd);方法中调用。
有一点需要注意,因为 Aware 方法都是执行在初始化方法之前,所以可以在初始化方法中放心大胆的使用 Aware 接口获取的资源,这也是我们自定义扩展 Spring 的常用方式。
除了实现 InitializingBean 接口之外还能通过注解或者 xml 配置的方式指定初始化方法,至于这几种定义方式的调用顺序其实没有必要记。因为这几个方法对应的都是同一个生命周期,只是实现方式不同,我们一般只采用其中一种方式。
-
DisposableBean 类似于 InitializingBean,对应生命周期的销毁阶段,以ConfigurableApplicationContext#close()方法作为入口,实现是通过循环取所有实现了 DisposableBean 接口的 Bean 然后调用其 destroy() 方法,感兴趣的可以自行跟一下源码。
4.4 总结
我们可以将其概括为如下流程:
- Spring对bean进行实例化;
- Spring将值和bean的引用注入到bean对应的属性中;
- 如果bean实现了BeanNameAware接口,Spring将bean的ID传递给setBean-Name()方法;
- 如果bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入;
- 如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的引用传入进来;
- 如果bean实现了BeanPostProcessor接口,Spring将调用它们的post-ProcessBeforeInitialization()方法;
- 如果bean实现了InitializingBean接口,Spring将调用它们的after-PropertiesSet()方法。类似地,如果bean使用initmethod声明了初始化方法,该方法也会被调用;
- 如果bean实现了BeanPostProcessor接口,Spring将调用它们的post-ProcessAfterInitialization()方法;
- 此时,bean已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁;
- 如果bean实现了DisposableBean接口,Spring将调用它的destroy()接口方法。同样,如果bean使用destroy-method声明了销毁方法,该方法也会被调用。
4.4 哪些是中要的bean生命周期方法?我们能重载它们吗?
有两个重要的bean 生命周期方法,第一个是setup , 它是在容器加载bean的时候被调用。第二个方法是 teardown 它是在容器卸载类的时候被调用。
bean 标签有两个重要的属性(init-method和destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct和@PreDestroy)。
Spring将调用它们的post-ProcessAfterInitialization()方法;
9. 此时,bean已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁;
10. 如果bean实现了DisposableBean接口,Spring将调用它的destroy()接口方法。同样,如果bean使用destroy-method声明了销毁方法,该方法也会被调用。
4.4 哪些是中要的bean生命周期方法?我们能重载它们吗?
有两个重要的bean 生命周期方法,第一个是setup , 它是在容器加载bean的时候被调用。第二个方法是 teardown 它是在容器卸载类的时候被调用。
bean 标签有两个重要的属性(init-method和destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct和@PreDestroy)。