0


springboot是如何工作的

一、前言

现在java后端开发框架比较多的使用springboot框架,springboot是在以前的springMVC进行封装和优化,最大的特点是简化了配置和内置Tomcat。本节通过阅读源码理解springboot是如何工作的。

二、springboot是如何工作的

1、从启动类开始

/**
  *服务启动类
  * @author: 
  * @Description:
  * @Company: 
  * @date: 
  */
@SpringBootApplication(scanBasePackages = {"cn.xxx.common","cn.xxx.admin.*","cn.xxx.interceptor.*"})
@EnableEurekaClient
@EnableApolloConfig
@EnableFeignClients(basePackages = {"cn.xxx.interceptor.*"})
@EnableDiscoveryClient
@MapperScan("cn.xxx.admin.dao")
@EnableSwagger2
@EnableTransactionManagement 
public class BaseAdminApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(BaseAdminApplication.class,args);
    }

}

从代码上可以看出spring通过main方法启动,关键代码是这一句:SpringApplication.run(BaseAdminApplication.class,args);

和注解 @SpringBootApplication(scanBasePackages = {"cn.xxx.common","cn.xxx.admin.","cn.xxx.interceptor."})

通过调用SpringApplication的run方法

    public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
        return run(new Class<?>[] { primarySource }, args);
    }

可以看出传入的参数是 类 BaseAdminApplication.class

我们平时的方法很少参数传入一个类,这里传入一个类,就是为了获取这个类的属性,就是它上面的注解之类的

这里就要理解一下java的反射。

接着往下看 run(new Class<?>[] { primarySource }, args);

调用的run方法传入的是 类的数组 Class<?>[] { primarySource },数组中的元素是 BaseAdminApplication.class

继续往下调用

    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        return new SpringApplication(primarySources).run(args);
    }

这一段东西又怎么理解?

new SpringApplication(primarySources).run(args);

这个是构造函数SpringApplication(primarySources),就是初始化出SpringApplication的一个实例对象,它传的值就是 BaseAdminApplication.class ,然后调用run的方法。

先看构成函数里都进行那些初始化

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        this.bootstrapRegistryInitializers = new ArrayList<>(
                getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
        setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = deduceMainApplicationClass();
    }

这里其实就是封装了配置信息

接下来看看如何运行配置文件和上下文信息

public ConfigurableApplicationContext run(String... args) {
        long startTime = System.nanoTime();
        DefaultBootstrapContext bootstrapContext = createBootstrapContext();
        ConfigurableApplicationContext context = null;
        configureHeadlessProperty();
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting(bootstrapContext, this.mainApplicationClass);
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            configureIgnoreBeanInfo(environment);
            Banner printedBanner = printBanner(environment);
            context = createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            refreshContext(context);
            afterRefresh(context, applicationArguments);
            Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
            }
            listeners.started(context, timeTakenToStartup);
            callRunners(context, applicationArguments);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, listeners);
            throw new IllegalStateException(ex);
        }
        try {
            Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
            listeners.ready(context, timeTakenToReady);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, null);
            throw new IllegalStateException(ex);
        }
        return context;
    }

这段代码还是很复杂的,因为里面嵌套了很多模块和方法,它表示的就是如何处理配置信息和上下文。

三、扩展,java的反射

Java中的反射机制是指在运行时动态地获取一个类的信息,包括类的方法、属性、构造函数等,而不需要事先知道这个类的具体实现。通过反射机制,可以在程序运行时获取类的信息,并且可以在运行时调用类的方法、创建对象等。

反射机制主要包含以下几个核心类:

一:Class类:表示一个类的类型,可以通过它获取类的构造函数、方法、字段等信息。Class类是反射机制的核心类之一。它代表了一个类的类型,可以用来获取该类的构造函数、方法、字段等信息,也可以用来创建该类的对象。以下是Class类的一些常用方法:

  1. forName(String className):根据类的全限定名获取对应的Class对象。
  2. newInstance():创建该类的一个实例对象。
  3. getConstructor(Class<?>... parameterTypes):获取该类的指定构造函数。
  4. getDeclaredConstructor(Class<?>... parameterTypes):获取该类的指定构造函数,不考虑其访问权限。
  5. getMethod(String name, Class<?>... parameterTypes):获取该类的指定公共方法。
  6. getDeclaredMethod(String name, Class<?>... parameterTypes):获取该类的指定方法,不考虑其访问权限。
  7. getField(String name):获取该类的指定公共字段。
  8. getDeclaredField(String name):获取该类的指定字段,不考虑其访问权限。

在使用反射机制时,通常需要先获取对应的Class对象,然后再通过该对象获取需要的信息或者创建对象。

二:Constructor类:表示一个类的构造函数,可以通过它创建对象。在Java反射机制中,Constructor类表示一个类的构造函数,可以用来创建该类的实例对象。以下是Constructor类的一些常用方法:

  1. newInstance(Object... initargs):使用指定的参数创建该构造函数所表示的类的新实例。
  2. getParameterTypes():获取该构造函数的参数类型。
  3. getModifiers():获取该构造函数的修饰符。
  4. isVarArgs():判断该构造函数是否支持可变参数。
  5. isAccessible():判断该构造函数是否可以被访问。
  6. setAccessible(boolean flag):设置该构造函数的可访问标志。

使用Constructor类可以通过反射机制来创建一个类的实例对象,可以方便地调用私有构造函数等。

三:Method类:表示一个类的方法,可以通过它调用类的方法。Method类是用于表示类或接口的方法的反射机制类。它包含有关方法名称,参数类型,返回类型,访问修饰符等信息的元数据。

使用Method类,可以在运行时动态地调用类的方法,而无需在编译时知道类的确切类型。可以使用以下方法之一获取Method对象:

1.getMethod(String name, Class<?>... parameterTypes):返回具有指定名称和参数类型的公共方法。

2.getDeclaredMethod(String name, Class<?>... parameterTypes):返回具有指定名称和参数类型的方法,无论是否为公共方法。

一旦获得了Method对象,就可以使用invoke()方法调用它来执行方法,需要提供目标对象和方法的参数。如果方法是静态的,则可以将目标对象设置为null。

四:Field类:表示一个类的字段,可以通过它获取和设置类的属性值。Field类代表类或接口的字段,即类或接口中的变量。Field类提供了访问和操作字段的方法,包括获取字段的名称、类型、修饰符、值等。

Field类是通过Java反射机制来实现的,反射机制是一种在运行时分析和操作类、接口、方法、字段等程序构件的机制。使用反射机制,可以在运行时获取一个类的信息,包括其方法、字段、注解、泛型类型等,并可以动态地创建对象、调用方法、访问字段等

标签: spring boot 后端 java

本文转载自: https://blog.csdn.net/dongjing991/article/details/134117997
版权归原作者 奋力向前123 所有, 如有侵权,请联系我们删除。

“springboot是如何工作的”的评论:

还没有评论