The last article is very relaxed as a whole, because before the container starts, only one bean definition is registered, which is the main class of SpringBoot.
OK, start from the container today Start, find out the registration process of all remaining bean definitions.
The details will definitely be quite complicated. Similarly, everyone only needs to pay attention to what they did, not how to do it.
Let’s take a macro look at the start of the container The process, the refresh method, as shown in Figure 01:
p>
Only the important ones, It is four big steps:
First, prepare the BeanFactory.
Second, call the registered bean Factory post processor (BeanFactoryPostProcessor).
Third, register bean post processor (BeanPostProcessor).
Fourth, instantiate all orders Example bean.
the second and third introduce two A new concept, “bean factory post processor” and “bean post processor”.
To better understand them, come again Repeat the operation process related to the bean.
registered bean definition->①-> Instantiate the bean -> Dependent assembly->②< span style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; font-size: 15px; letter-spacing: 2px ;">-> Initialize bean ->③-> OK
This is the whole process from the beginning to the preparation of the bean instance. where①②③are three buried points reserved by Spring, you can insert some user code in these places, Do some customization.
where①After the bean definition has been registered, when the bean instance has not yet started to be generated, here is the custom processing of the bean definition.
remaining②and③located Before and after the initialization method of the bean instance is executed, here is the custom processing of the bean instance.
So ① corresponds to the above The second is the bean factory post processor. ② and ③ correspond to the third above, that is, the bean post processor.
So, it can be seen that in the container During the startup process, the only thing that can be connected with the bean definition is the second mentioned above, which is the bean factory post processor.
It is our next breakthrough. But someone will ask, from the beginning to now, no one has registered it, why is it called here?
Hey, this is a good question. Let’s push it backwards. First of all, the bean factory post-processor must be registered. Otherwise, why call it here, or how are the remaining bean definitions registered in the container?
Since we (the user code) don’t Register, it must be automatically registered by the system (ie, the framework code). Well, I can only think so for the time being.
Let’s find it, it must be hidden Somewhere. Find and find friends, find and find.
Finally, hard work pays off, find It is hidden in two classes, which are two classes responsible for registering bean definitions.
AnnotatedBeanDefinitionReader in the constructor of this class, As shown in Figure 02 below:
< p>
ClassPathBeanDefinitionScanner In the scan method of the class, as shown in Figure 03:
we It is found that they are executing the same code. Wouldn’t it be executed twice? Haha, idempotent processing is done inside.
Enter this method and you will find registration There are several beans, but there is only one bean factory processor, as shown in Figure 04:
its bean There is an internal in the name, indicating that it is used internally, that is, the role of “infrastructure”, as shown in Figure 05:
this The name of the class starts with ConfigurationClass, which means that it is the full treatment of the classes marked with @Configuration annotations.
Think carefully, let you in Spring Choose one of the most special and common annotations in the family, and anyone will choose the annotation @Configuration.
more carefully, this note is actually It has functions similar to “configuration” and “management”. It can be said that the entire Spring is built around it.
OK, now we are about to usher in this article Core content, cheer up. As usual, focus on the overall process and weaken the specific implementation details.
First, take out the registered bean The definition is actually the polished commander of the main class himself.
Second, determine whether it needs to be Processing, the conditions met are:
1 ) Marked with @Configuration annotation
2) Marked with @Component annotation
3) Annotated with @ComponentScan
4) marked with @Import annotation
5) marked with @ImportResource annotation
6) contains @Bean method
As long as one of these six conditions is met, it needs to be processed.
Because the main class of SpringBoot is marked with @SpringBootApplication annotation, so the above item 1 is satisfied.
So the main class needs to be processed, this No nonsense, it has only registered itself at present, and it must be processed.
New programming note:每一个符合条件的类,都可以认为是一个源(Source,即源泉),它的作用就是向容器中贡献bean定义。
第三,如果类上标有@Component注解,就去处理它的静态内部(嵌套)类,如下图06:
这其实已经是递归了,所以处理方式是一样的。
第四,接着处理@PropertySource注解,它可以引入.properties文件,会把文件中的属性值放入到Environment中。 如下图07:
第五,接着处理@ComponentScan注解,它会扫描指定的jar包,并从中获取bean定义,如下图08:
第六,然后再处理@Import注解,如下图09:
该注解共可以引入三类内容:
1)另一个普通类,但是当作@Configuration类
2)ImportSelector接口的实现类
3)ImportBeanDefinitionRegistrar接口的实现类
其中第2、 3是通过实现接口,自己写代码来注册bean定义,超级灵活,随意掌控。
编程新说注:这种方式的一般典型用法是,在实现第三方框架和Spring框架整合时使用。
请看下代码,如下图10:
第七,然后处理@ImportResource注解,它用于引入.xml文件,可以使xml和注解两种方式混合使用,如下图11:
第八,然后再处理类中的@Bean方法,如下图1213:
第九,然后再处理接口里面的默认方法,且方法上有@Bean注解的,如下图1415:
第十,最后再处理父类,如下图16:
因为每个@Configuration类除了自身是源之外,还可以向容器贡献其它的源,所以总体是递归进行的。
在进行的过程中,做好了防重复处理,所以不会出现重复注册。
以上所有这些其实都是ConfigurationClassPostProcessor这类里面的逻辑。
它不仅仅是一个bean工厂后处理器,还是一个专门用于注册bean定义的后处理器。
这个类在容器启动时会被调用,因此把其它类的bean定义注册到了容器中。
>>> 品Spring系列文章 <<<
p>
品Spring:帝国的基石
品Spring:bean定义上梁山
品Spring:实现bean定义时采用的“先进生产力”
品Spring:注解终于“成功上位”
品Spring:能工巧匠们对注解的“加持”
品Spring:SpringBoot和Spring到底有没有本质的不同?
品Spring:负责bean定义注册的两个“排头兵”
品Spring:SpringBoot轻松取胜bean定义注册的“第一阶段”
作者是工作超过10年的码农,现在任架构师。喜欢研究技术,崇尚简单快乐。 追求以通俗易懂的语言解说技术,希望所有的读者都能看懂并记住。 下面是公众号和知识星球的二维码,欢迎关注!