spring-bean的生命周期
Posted 野生java研究僧
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring-bean的生命周期相关的知识,希望对你有一定的参考价值。
前言
为什么要使用 spring?
1.简介
- 目的:解决企业应用开发的复杂性
- 功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
- 范围:任何Java应用
简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
2.轻量
从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。
3.控制反转
Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
4.面向切面
Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
5.容器
Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。
6.框架
Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。
使用spring和不使用springMVC的对比
spring最重要的就是:依赖注入,AOP,容器的概念。
以上的说明我们大概对spring有了个基本的了解。我们再来谈谈什么是依赖注入,以及容器的概念,最后在延伸出我们的主题spring中bean的生命周期。毫不夸张的来说,依赖注入,AOP,控制反转,甚至是事务,都跟bean的生命周期有关系。
总的来说我们的把创建对象的权利交给了spring去完成,我们只需要从spring中获取即可。
以前我们在web开发的时候我记得好像是这样用的,每次都有new,比较麻烦,反正我是记得每次都要去new的非常麻烦
public class UserServlet extends HttpServlet
private static UserDao userDao = new UserDao() ;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
在spring中我们直接这样注入就行了,比较简单
@RestController
public class UserController
@Autowired
private UserService userService;
public String getUserInfo(String userId)
return UserInfo userInfo = userService.selectById(userId)
虽然这里面是有SpringMVC的东西,打不死springMVC只是小角色,最重要的还是spring,因为springMVC是基于spring的,以及后面的springBoot等等,正是因为spring有bean的生命周期,才会让他怎么强大和什么框架都可以组合,以及你可以自己在spring框架的基础上进行扩展。别着急我马上解释bean的生命周期,因为了解bean的生命周期之前,我想大家有个概念先。
由创建对象引出的思考
我们先思考一个问题? 创建对象怎么简单的事情,为什么明明简单的一个 new 就好了,为什么还需要整个spring来给我们管理呢?明明我们一行代码就可以的事情。
你看就一行代码的事情:
我们来看下spring的代码量:这只是其中一部分为什么要搞的怎么复杂?
我们之前常说的一句话:什么是高内聚,低耦合,扩展开放,修改关闭。
我们的spring就是这样的,他并不是简单地给我们创建对象而已,而是给了我们很多的回调接口,只是如果你对spring不太理解,那你就亏大了,正是这些预留回调接口,才让spring怎么强大,就行一个万能胶,什么都能粘到一起。
我们步入正题:来看看spring的简单图,就知道他们为什么那么强大了,这只是随意的简单图,复杂的再后面,我们由浅入深。这就是基本你的流程,在每个步骤都给你关键的接口,让你有机会插入,如果你不进行干预,他在进行自动处理
大概就是这样子,因为spring需要很多前置知识才能了解清楚,所以不理解没关系,后面我会发布spring的一个设计架构,已经容器初始化,以及AOP等系列文章。
记住一点:spring强大就强大在他的那些个回调接口,有了这些回调接口,你甚至可以在spring的基础上进行扩展你想完成的功能,比如说日志记录,事务,请求参数校验,完全可以你自己手写,但是前提得了解spring的运行流程,你知道了运行流程,你就能很清楚的在哪一步进行干预,嵌入你想要的功能。
这点跟vue有点像,vue也是留了很多回调函数给你进使用,所以说,一个好的框架,或者说应用,应该面向接口编程,在你实现功能的同时,给别留一些回调接口,让别人可以对你的功能进行扩展,而不是一味的将逻辑写死,接口都不写,全是搞些普通类。
我们需要先再次理解下:接口,抽象类,实现类的作用
解接口的作用: 接口的作用就是规定功能,有具体的类实现,反正我只告诉你要完成这个功能,具体你怎么完成那我不管,就好像你的老板让你给他买早餐,他只想吃到早餐,你走路过去买还是坐车过去买他是不关心的。
抽象类的功能就是: 将一些公共的方法或者属性进行一个抽离,让后由子类去继承,在父类的基础上再次进行扩展,先有个基本实现。
实现类就是继承了抽象类:对父类的功能进行扩展,实现自己需要的功能,在父类的功能上再次对自己的实现进行个性化。
就比如说我们的spring,都是接口+抽象类+实现类这样的一个实现进行解耦
最明显的就是那几个IoC容器
我们选两个最明显的:ClassPathXmlApplicationContext和AnnotationConfigApplicationContext
bean生命周期的基本流程
我说下spring生命周期的大概流程: 然后我在给张图,你在需要创建对象的地方进行打断点进行调试,看堆栈跟踪,看个一两次,让后你自己去实现那些个接口体验一下,源码这个事情,说再多也不如自己打断点调试,这样你才记忆深刻,别人为什么要这么干。
1.准备一个AnnotatedBeanDefinitionReader并且用于解析扫描到的class,并且注册一些基础的组件
2.将配置类的信息注册到BeanDefinition中去
3.准备一个BeanFactory工厂,注解模式是准备工厂,xml方式是解析配置文件得到BeanDefinition
4.根据扫描配置类中指定的扫描路径,扫描到符合注入条件的class,解析得到BeanDefinition,执行BeanFactoryProcessor的所有回调
5.初始化所有的单例bean 如果你实现了InstantiationAwareBeanPostProcessor接口并且返回对象,接下来的流程不在继续
6.如果没有,确定构造函数,实例化对象,你也可以手动返回,spring有留SmartInstantiationAwareBeanPostProcessor接口
7.实例化完后回调InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation()让你有手动赋值的机会,如果你返回的是false自动注入结束
8.开始进行属性注入,如果在注入的过程中,有依赖其余的bean会先去创建其他的bean
9.赋值完毕后开始回调Aware接口,例如BeanNameAware 属性自动注入完毕后,如果使用了AOP,这里的AOP会创建代理对象
10.初始化完毕后回调BeanPostProcessor的postProcessBeforeInitialization() ()方法你可以检查bean或者是重新返回一个bean
11.调用InitializingBean接口方法给你进行回调
12.如果你有配置init()方法,也会再此时进行回调
13.执行BeanPostProcessor的postProcessAfterInitialization()回调 回到完毕后会添加到单例池
14.所有的单实例bean创建完毕后,如果你实现了SmartInitializingSingleton就会执行所有bean的void afterSingletonsInstantiated();方法,前提是bean是单例的。至此ioc容器的所有组件创建完毕。可以开始进行使用, @Lazy标注的bean需要使用getBean()的时候才会创建。
15.当容器关闭时会调用DisposableBean()中的方法
结尾散花
最后这张图才是重点,过多的文字描述都是累赘的,如果你有不明白的地方百度慢慢看,有点耐心。
起始远远不止这15步,这只是个大概,有了后面这张完整的图,你可以慢慢打断点机芯调试,有了这个图至少你能清楚几分,在打个断点就差不多明白了,我就不贴源码了,这源码贴太多篇幅长,看起也头疼。写程序这个东西要自己多思考,我如果一步步贴出源码,在写上中文注释,那没有多大意义,如果给你个大概思路,你自己慢慢断点调试,你不明白都难,认真看完后,你甚至想自己写个轻量版本的spring。
最后奉献上完全的大图:别把你吓到了,可以进行点击图片进行方法看,因为这个确实流程有点复杂,使用的spring版本不同也行有点差别,不过差不多的,不会变化太大。
以上是关于spring-bean的生命周期的主要内容,如果未能解决你的问题,请参考以下文章