Springboot Source Analysis: a, SpringApplication instantiation

Analytical Springboot Source: SpringApplication instantiation

Play ad

Personal write "springboot source analysis" of this series for a long time, but the lack of knowledge has been accumulated angle child's heart, it has not put pen to paper.
So I am looking to write this series of small partners, error correction mutual exchange of learning.

If there is little interested partners put together a series of words to explain the finish, plus my micro letter: 13670426148, we finish together, when the exchange of learning.

Late want to write a series of introductory rpc framework, but to another for a while, finished the first springboot

Foreword

This series of tutorials from the entrance Springboot projects, namely SpringApplication.run (Application.class, args) begin to explain.

Boot entry

First posted the code entry class:

@SpringBootApplication
//@EnableTransactionManagement
@EnableAsync
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
@EnableScheduling
@EnableRetry
@ComponentScan(basePackages = {"*** ", "***"})
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Among them, the class name import category is Application, the type of the class as a parameter passed to SpringApplication the run () method, there are some initialization parameters, these will be processed when the run () method, you can remember they.

Can now remember @EnableAutoConfigurationand @EnableSchedulingand @ComponentScanand other notes, these notes in mind, its operation will be described later.

SpringApplication instantiation

Application of this class does not inherit any class of all, he really is a startup class , quite and write algorithms that title when the main function, and you write the calculation process in which other classes or methods.

SpringApplication for guidance and start the Spring application from the java main method, by default, will perform the following steps to guide our application:

  • ApplicationContext it creates an appropriate instance (depending on the classpath)
  • Registration CommandLinePropertySource, open the command-line arguments for the Spring Properties
  • Refresh application context, load all singleton bean
  • All CommandLineRunner bean trigger

 In most cases, like SpringApplication.run (ShiroApplication.class, args); so start our application, you can also create and customize SpringApplication example, you can refer to specific comments before running the example.

 SpringApplication bean may be read from various sources. @Configuration generally recommended to use a single class to boot, but we can also set up a resource in the following ways:

  • By loading AnnotatedBeanDefinitionReader fully qualified class name
  • Load XML resource position through XmlBeanDefinitionReader, or groovy script is loaded position by GroovyBeanDefinitionReader
  • By scanning the package name ClassPathBeanDefinitionScanner
  • That SpringApplication still do a lot of things, specific implementation of the follow-up to speak slowly, today's hero just SpringApplication constructor.
public class SpringApplication{
    
     public SpringApplication(ResourceLoader resourceLoader, Object... sources) {
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.headless = true;
        this.registerShutdownHook = true;
 
        //todo -------------------------------------------------------
        this.additionalProfiles = new HashSet();
        //上面的信息都不是主要的,主要的信息在这里,在这里进行
        //(1)运行环境 (2) 实例化器 (3)监听器等的初始化过程,下面将详细解析
        this.initialize(sources);
    }
    
    public ConfigurableApplicationContext run(String... args) {
        *******
    }
}

This this.initialize (sources) method or in SpringApplication inside, so this is really SpringApplication springboot throughout the entire process of starting a class, and there are a run () method.

We look initialize (Object [] sources) content method

private void initialize(Object[] sources) {
        //sources里面就是我们的入口类: Application.class
        if (sources != null && sources.length > 0) {
            this.sources.addAll(Arrays.asList(sources));
        }
        //这行代码设置SpringApplication的属性webEnvironment,deduceWebEnvironment方法是推断是否是web应用的核心方法
        this.webEnvironment = this.deduceWebEnvironment();
       //获取所有的实例化器Initializer.class this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        //获取所有的监听器
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        //这个不解释了,就是我们的Application.class ,我们写的入口类,过程就是从当前的堆栈中找到我们写main方法额类,就是获取我们的入口类了
        this.mainApplicationClass = this.deduceMainApplicationClass();
}

The following will explain the specific implementation of three parts:

(1) speculated that the operating environment

(2) Get all instances homogenizer Initializer.class

It has demonstrated its acquisition process

(3) Get all listeners Initializer.class

Speculated that the operating environment

Presumed operating environment, and give a this.webEnvironment this property, deduceWebEnvironment method is a method to infer whether the core web application.
SpringApplication behind the run () method to create ApplicationContext time is judged according to webEnvironment this property is AnnotationConfigEmbeddedWebApplicationContextstillAnnotationConfigApplicationContext

code show as below:

private boolean deduceWebEnvironment() {
        String[] var1 = WEB_ENVIRONMENT_CLASSES;
        int var2 = var1.length;

        for(int var3 = 0; var3 < var2; ++var3) {
            String className = var1[var3];
            if (!ClassUtils.isPresent(className, (ClassLoader)null)) {
                return false;
            }
        }

        return true;
    }

WEB_ENVIRONMENT_CLASSES = new String[]{
    "javax.servlet.Servlet",
    "org.springframework.web.context.ConfigurableWebApplicationContext"
 };

Inference process is very simple, but I do not understand why so write, because this is my web projects, so the this.webEnvironmentvalue oftrue

ClassUtils.isPresent () process is actually very simple, is to determine WEB_ENVIRONMENT_CLASSESwhich of the two categories can not be loaded, if that can be loaded into, it indicates that the web projects, one of which can not be loaded into, not explained.

Get all the instantiators Initializer.class

//看完这个方法真觉得很棒,获取工厂实例
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type) {
    return this.getSpringFactoriesInstances(type, new Class[0]);
}
//记住 ty
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
        //这个是获取类加载器
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        //type是ApplicationContextInitializer.class,获取类型工厂的名字
        Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        //获取工厂实例
        List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        //排序,按照@Order的顺序进行排序,没有@Order的话,就按照原本的顺序进行排序,不管他问题不大
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }

Gets the name of the specified type of plant

public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();

        try {
            //获取所有 jar包下面的 META-INF/spring.factories 的urls
            Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
            ArrayList result = new ArrayList();

            while(urls.hasMoreElements()) {
                URL url = (URL)urls.nextElement();
                //每个spring.factories里的下的内容装载成Properties信息
                Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                //下面内容会继续解析
                String factoryClassNames = properties.getProperty(factoryClassName);
                result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
            }

            return result;
        } catch (IOException var8) {
            throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8);
        }
    }

Figure 1.1 is as follows:

There are many, I will not list out

(1) is to find all / MEIT-INF following spring.factory

(2) is converted into properties,

(3)properties.getProperty(factoryClassName)

About /MEIT-INF/spring.factory , I do not know if you have not written a starter, if you do not know what it is, many rely on such mybatis-plus, springboot package which has a lot of dependencies labeled form of starter, which we springboot project dependencies.

You can check out springboot Custom Starter , look, you probably know a spring.factory role in the. .

At this time factoryClassName equivalent whether a key corresponding to the acquired properties inside "org.springframework.context.ApplicationContextInitializer" a value corresponding to any, added to the result

To finally be obtained are, i.e., 1.2 FIG.

Obtaining factory instance (class name)

Then obtaining factory instance operation, steps are simple, it is to generate the constructor and specified by the class name Inializer , the present process is very simple.

Paste code, not interpreted the

private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) {
        List<T> instances = new ArrayList(names.size());
        Iterator var7 = names.iterator();

        while(var7.hasNext()) {
            String name = (String)var7.next();

            try {
                Class<?> instanceClass = ClassUtils.forName(name, classLoader);
                Assert.isAssignable(type, instanceClass);
                Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
                T instance = BeanUtils.instantiateClass(constructor, args);
                instances.add(instance);
            } catch (Throwable var12) {
                throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, var12);
            }
        }

        return instances;
    }


Get all the listeners Initializer.class

Similar to the above procedure, the results of the listener as follows: Figure 1.3

to sum up

(1) Remember those attributes do SpringApplication.class

public class SpringApplication{
    private List<ApplicationContextInitializer<?>> initializers; //如图1.2这个是拿6个Initializer
    private WebApplicationType webApplicationType;   //这个是true
    private List<ApplicationListener<?>> listeners;   //这和是图1.3的10个Listener
    private Class<?> mainApplicationClass;  //结果就是DemoApplication
    //另外还有构造方法设置的值
    public SpringApplication(ResourceLoader resourceLoader, Object... sources) {
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.headless = true;
        this.registerShutdownHook = true;
 
        //todo -------------------------------------------------------
        this.additionalProfiles = new HashSet();
        //上面的信息都不是主要的,主要的信息在这里,在这里进行
        //(1)运行环境 (2) 实例化器 (3)监听器等的初始化过程,下面将详细解析
        this.initialize(sources);
    }
}

(2) SpringApplication.class operation class is a boot process

Examples of some of the process is to load initial parameters and information, such as monitors, instantiator, bannerMode, additionalProfiles information. The most important thing listener and an instantiation , about the listener is the most important part of springboot boot process, the mechanism is probably the startup process, with a radio, broadcast some of the event he event, then these listeners (10 ), will be based on these events, do different reactions. Listener mode you can first look.

Next Issue

The following speaks SpringApplication.run (the contents inside) the main run () of "Radio - Listener - event" the process of implementation, win first thoroughly understand and then resolve.

Reference links:
the Spring-the Boot-2.0.3 source code is not the same series of articles

Guess you like

Origin www.cnblogs.com/disandafeier/p/12081275.html