Spring创建一个对象

原创: 码农翻身刘欣 码农翻身

“程序员要创建对象了,快去西天请Spring’佛祖’。” 一大早我就听到Tomcat在那里大喊。

“不就是创建一个对象吗,你给JVM老大打个电话,请他在堆里边new出来不就结了?无非就是一片儿内存而已。”我问道。

“唉,你不知道,这不仅仅是对象的创建,更是对象的装配,要依赖注入,要初始化,又要代理什么的… 这事儿Spring最擅长。”Tomcat感慨到。

Spring慢悠悠地来了:“想安静地喝一会儿茶都不行!让我瞧瞧,这个要创建的对象是单例吗? 嗯,果然是单例,也许之前创建过!让我从我的缓存中找找有没有! ”

Spring在他的缓存中扒拉半天,没有找到,不满地说:“缓存中没有,看来得忙碌一番了。”

他请JVM老大把要创建对象的类PetStoreService 从方法区取过来, 检查了一下,叹了口气。

我问道:“先生为何发愁啊?”

Spring说:“这个类没有缺省构造函数,你看看,它依赖AccountDao和ItemDao,我还得先把这两个bean给创建起来,然后才能调用这个构造函数创建这个PetStoreService对象,很麻烦的。”

public PetStoreService(AccountDao accountDao, 
       ItemDao itemDao){
    this.accountDao = accountDao;
    this.itemDao = itemDao;
}

我估计这个所谓的bean 就是一个java对象, 怪不得Tomcat说Spring做的主要是装配工作,此言不虚啊。

Spring 把当前的创建工作先放下,把工作中心转移到AccountDao, 照例还是要先看构造函数,这次运气不错,有个缺省的、无参数的构造函数。

我说:“这下可以把它给new 出来了吧!”

Spring说:“不不,在让JVM把它new 出来(这叫实例化)之前,我需要看看程序员有没有给我设置一些需要预先执行的代码, 如果有,我得先执行。 同理,实例化之后,还得做类似事情。”

在这里插入图片描述
Spring先执行了所谓“前置代码”,然后用反射的方式通知JVM把对象给创建起来。

注: 事实上在JVM那里还有一番折腾:

(1) 先执行AccountDao中实例变量的初始化
(2) 执行实例代码块
(3) 最后才是执行构造函数,把AccountDao创建起来,返回给Spring。

拿到了AccountDao的实例,Spring马上执行"实例化"以后的"后置代码"。

我对他深表同情:“不容易,这样一个对象就ok了,可以返回给程序员了吧?”

Spring说道:“哪有那么简单!还有一步,叫做初始化,需要调用程序员指定的***初始化方法***。”

初始化的前后也需要调用程序员设置的代码吧?”

“没错,就是这样,哎呀,你看看,这个AccountDao中还有@Autowired注解,需要注入一个User对象,我还得处理一下,真是麻烦!”

Spring再次放下手头工作,开始创建User对象,还是实例化,初始化,前置代码,后置代码,唉,这是一个递归的过程,我都懒得看了。

终于AcountDao对象创建完毕,接下来是ItemDao对象,又是一番同样的折腾。

总结:前置代码、jvm创建实例、后置代码、处理@Autowired注解的对象、初始化前置代码、初始化方法、初始化后置代码
在这里插入图片描述

手持AccountDao对象和ItemDao对象, Spring终于可以开始创建PetStoreService对象了。

实例化,初始化,前置代码调用,后置代码调用, 都是熟悉的配方、熟悉的味道。

PetStoreService的对象已经创建出来(简称petStore),也已经初始化完毕,只剩下最后一步:初始化的后置代码调用。

Spring看了看相关配置,心里咯噔了一下,说到:“坏了,这个PetStoreService 用了声明式事务,我还得创建一个代理出来(简称petStoreProxy),在这个proxy中来调用事务相关的代码。

“怎么创建代理对象?” 我问道。

“我看看这个程序员想要的是petStore的儿子还是兄弟。”

“儿子? 兄弟?”

“哈哈,那是我的做的一个比喻,儿子就是这个PetStoreService类没有实现接口, 我只好新创建一个类PetStoreServiceProxy,去继承PetStoreService。 兄弟就是我创建的类PetStoreServiceProxy 和PetStoreService都实现同样的接口。”
在这里插入图片描述

Spring看了看:“嗯,看来是’儿子’,JVM老兄,你去把CGLib叫来吧,我得请他在运行时生成一个新的Class,这个新的Class要继承PetStoreService。”

CGLib是个热情洋溢的小伙子,迅速地在内存中创建了新的字节码, 把我看得目瞪口呆,这个世界上还真有直接写字节码的人。

新的Class PetStoreProxy的字节码已经准备好,JVM把他装载到方法区,Spring用它创建了一个对象出来,终于返回给了程序员!

“程序员拿到的对象可不是PetStoreService啊,他会发现的吧?” 我善意地提醒Spring。

“没关系,两个类的’接口’都是相同的,除非他检查对象的所属类,否则是意识不到的。再说了,哪个程序员会闲得无聊去查看对象所属的类啊。”

"佛祖"Spring折腾了半天, 又去悠哉游哉地喝茶去了。

猜你喜欢

转载自blog.csdn.net/GoGleTech/article/details/82867006
今日推荐