Do a simple program wang, share dry goods, talk about life.

Wechat public account: Advanced backend architecture

Follow me to find more dry goods, microservices, Spring source, JVM, SpringCloud Alibaba, K8S, etc.

If you found this article helpful, please give me a like and thank you for your support!

In the last article we discussed how Spring fetches beans, so check it out if you’re interested.

Learn how to get beans from Spring in 5 minutes a day.

So in this section we’ll talk about how Spring actually creates a Bean, that is, what the Bean life cycle looks like.

In the previous section, we talked about ways to create fetch beans, either by creating beans from XML or by annotations. So today we will continue to talk about the internal implementation of annotation-based approach, exactly how to create a Bean.

Pull open AnnotationConfigApplicationContext, we can see:

public AnnotationConfigApplicationContext(Class<? >... componentClasses) { this(); this.register(componentClasses); this.refresh(); }Copy the code

Initialize the reader and scanner defined by the Bean

As you can see above, the this() method simply calls one of its empty parameter constructors. Normally, this is for initialization, right?

We see only two cores. One creates a reader for the annotation-based Bean definition, and the other creates a scanner for the Bean definition under the classpath, which is obvious.

public AnnotationConfigApplicationContext() {
    StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
    this.reader = new AnnotatedBeanDefinitionReader(this);
    createAnnotatedBeanDefReader.end();
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}
Copy the code

Register the Bean definition

Continuing to open our register, we can see that a class is registered in the reader that was initialized in init() in the previous step.

public void register(Class<? >... componentClasses) { ...... this.reader.register(componentClasses); . }Copy the code

Follow along and we can see the following code. Spring code has a lot of conventions, and basically anything that is doing this will have a do, such as doCreateBean() and doRegisterBean().

public void registerBean(Class<? > beanClass) { this.doRegisterBean(beanClass, (String)null, (Class[])null, (Supplier)null, (BeanDefinitionCustomizer[])null); }Copy the code

What exactly is going on inside? Let’s keep following them. Remember, we don’t want to catch every line of code, we need to understand the trunk first, otherwise it is easy to get entangled and get confused.

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) { AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); . BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); . BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }}Copy the code

In this way, we also keep the main parts, which is very easy to view and understand, of course, not to say that the omission is not important, but when we look at it for the first time, it will interfere with our understanding, when we have all the complete, we will pick up the details so that it is very clear.

From the above, all you have done is create an annotated normal Bean definition. Then wrap it with the Bean definition holder and register the Bean definition.

What is a Bean definition? If you see this for the first time, it might be a little confusing, but you can think of it as an unformed Bean. For example, chickens are hatched from eggs, which can be interpreted as creating eggs and putting them into a chicken nest.

Finally according to the registration is registered to where? That’s a good question.

private final Map<String, BeanDefinition> beanDefinitionMap;
Copy the code
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) { ...... this.beanDefinitionMap.put(beanName, beanDefinition); . }Copy the code

Where do I register? Just put it in a Map, our henhouse beanDefinitionMap. Is not in fact the source code is not so difficult, as long as insist to see, slowly familiar with. Ok, our register() is done.

Refresh Spring’s core entry

This is the core step of Spring, starting our container does so much of the following. Spring YYDS.

Public void Refresh() throws BeansException, IllegalStateException {//1. ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); PrepareBeanFactory (beanFactory); prepareBeanFactory(beanFactory); Try {/ / 3, the inside is empty, can be extended to do this. PostProcessBeanFactory (the beanFactory); / / 4, call the Bean factory rear processor enclosing invokeBeanFactoryPostProcessors (the beanFactory); / / 5, registered Bean factory rear processor enclosing registerBeanPostProcessors (the beanFactory); beanPostProcess.end(); // initialize the message resource this.initMessagesource (); / / 7, initialization event multicast implement this. InitApplicationEventMulticaster (); // this. OnRefresh (); // Listeners(); / / 10, finish initializing Bean factory enclosing finishBeanFactoryInitialization (the beanFactory); // finishRefresh this.finishrefresh (); } catch (BeansException var10) { if (this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10); } // If there is an exception, destroy the Bean this.DestroyBeans (); // Cancel the refresh. this.cancelRefresh(var10); throw var10; } finally {//12, reset some general caches this.resetCommoncaches (); //13, refresh end contextrefresh.end (); }}}Copy the code

By following these steps, our Bean has been initialized for us and can be used directly from level 1 cache. There is a concept of level 3 cache. As I wrote in the previous article, I looked at solving the problem of circular dependencies. The first level is the storage of our hatched chickens, that is, our beans.

Spring level 3 cache solution to loop dependency

Level 3 cache is actually three maps, not so lofty, mainly the idea and method to solve the problem. Caching is also to improve the efficiency of our program.

Four, summary

This article we will analyze here, above more than ten steps to the initial creation we will analyze one by one, eat not fat. Let’s start by knowing that our Bean creation will go through each of these steps. If lazy loading is set, it will not be used until the time to create.

Five minutes a day, learn through Spring, so that source code is no longer difficult.

Summary of historical articles, including Netty, source code, concurrency, JVM

conclusion

The above is the summary and sharing of the previous content, thank you for your attention, thumbs up and favorites!

Wechat public account: Advanced backend architecture

More articles are coming, like to remember to give me a 👍, thank you for your support!

Public article synchronous update! Focus on me, don’t get lost!