在bean的实例化过程中,也会用到一系列的相关注解。
如@PostConstruct和@PreDestroy用来标记初始化和销毁方法。
平常更多的是侧重于应用,很少会有人去了解它背后发生的事情。
今天就来看下它们的源码,这样它们对你来说就不再是黑盒子了,而且学习源码对每个技术人来说都是必经之路。
人们对事物的认知以及自己的做法,往往分为三个阶段:
1)最初看一个事物,非常复杂,简直没有一点头绪,此时很多人就会放弃。
2)过了一段时间后,发现整体来看没有想象中的那么难,此时很多人以为自己已经get到了,然后就停止不前。
3)随着了解的深入,发现很多细节的处理,很多方方面面的考虑是自己无法想到的,此时才会有一点点的东西转化为你的智慧,永远的属于你。只可惜能够到达这一步的人已经凤毛麟角了。
因此能够到达第3步的人就已经很少了,如果你恰巧到达了,那么需要做的就只剩下坚持了。
坚持了足够的时间之后,你付出的努力对你付出的时间的累积效果(类似于高数中的积分)就会非常明显,此时你已经站在了一个相对较高的位置。可以体会下“会当凌绝顶,一览众山小”。
学习源码就是要做到第2点和第3点。既要知道宏观的处理进程,也要知道一部分处理细节。
而且宏观过程很容易理解,很多时候猜都能猜出来,难就难在细节处理上。
因为宏观对应的是说,细节对应的是做,用嘴说说谁都会,一旦做起来就不是那么回事了。
细节处理之所以难,是因为没有找到一种很好的表述方法。
一个很重要但从不被重视的观点:
要解决一个问题,首先要找到这个问题,并把它描述(表示)出来。
编程新说注:很多时候我们看到的只是现象,隐藏在现象背后的才是问题。
我想表达,其实如何把一个事物准确而又良好的描述出来,是很重要的。
在编程的世界里,描述事物很大程度上对应于广义的数据结构。
一、注解的描述
使用两个Class<? extends Annotation>字段存储两个注解,通过setter方法设置进来,而不是写死。如下图0102:
这样做的好处是,如果你看不上Java提供的这两个注解,完全可以自己定义两个,把它们替换掉,效果完全一样。
二、方法的描述
我们都能想到使用反射在一个类里面找出所有标有注解的方法,就是Method类型的一个对象。
Spring也是这样做的,但是它考虑的更加细节化。如下图0304:
把Method保存起来不足为奇,而且还要求方法的参数个数必须为0,即没有参数。
还有一个String类型的identifier字段,这个单词是标识符的意思。
看到下面对它的赋值,如果是私有方法,则是方法的全名(包括类名),否则是方法的简单名(不包括类名)。
看到这里,一定会觉得很奇怪,先卖个关子,到后面再说明为什么。
还重写了hashCode和equals方法,也是依赖identifier字段来实现的。说明这个字段非常重要。
还说明可能会把这个类的对象作为Map的key使用,或往Set集合中添加,其实都是在比较两个对象是否相等。
三、类和方法的对应关系描述
其实我们需要知道的是每个类中的相应方法,所以要和类关联起来。如下图05: