SpringBoot高级

SpringBoot起步依赖原理分析

spring-boot-starter-parent:在这里定义了各种技术的版本信息,组合了一套最优搭配的技术版本,在各种starter中,定义了完成该功能需要的坐标合集,其中大部分版本信息来自于父工程,我们的工程继承parent,引入starter后,通过以来传递,就可以简单方便获得需要的jar包,并且不会存在版本冲突问题

SpringBoot读取配置内容

1.@Value(“${name}”)
2.Environment:通过@Autowired注入private Environment env直接可以通过env.getProperty(“name”)获取配置内容
3.@ConfigurationProperties(prefix=“person”)可以作用在实体类上

SpringBoot整合test

引入pom依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
@SpringBootTest(classes = SpringbootInitApplication.class)
class SpringbootInitApplicationTests {

    @Autowired
    private TestService testService;
    @Test
    void contextLoads() {
        testService.test();
    }
}

SpringBoot原理分析

Condition: Condition是在Spring4增加的条件判断功能,通过这个功能可以实现选择性的创建Bean操作
通过自定义注解的方式代码演示:
首先自定义注解

package com.rlw.springbootinit.condition;

import org.springframework.context.annotation.Conditional;

import java.lang.annotation.*;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
//绑定自定义的ClassConditional
@Conditional(ClassConditional.class)
public @interface MyConditionOnClass {
    String[] value();
}

自定义逻辑

package com.rlw.springbootinit.condition;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

import java.util.Map;

public class ClassConditional implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获取这个注解标注的map
        Map<String, Object> map = metadata.getAnnotationAttributes(MyConditionOnClass.class.getName());
        //得到类路径
        String[] value = (String[])map.get("value");
        boolean flag = true;
        for (String s : value) {
            try {
                //通过路径判断是否可以获取到值
                Class<?> aClass = Class.forName(s);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                flag = false;
            }
        }
        return flag;
    }
}

应用

@Configuration
public class ConfigCondition {

    @Bean
    @MyConditionOnClass("com.rlw.springbootinit.service.TestService")
    public User user() {
        return new User();
    }
}

小结:

自定义条件:(1)定义条件类:自定义类实现Condition接口,重写matches方法,在matches方法中进行逻辑判断,返回boolean值,matches方法两个参数一个是context可获取上下文对象、可以获取属性值、可以获取类加载器、获取BeanFactory等;另一个是metaBean可以获取元数据对象,用于获取注解属性(2)判断条件:在初始化Bean时,使用@Conditionall(条件类.class)注解

SpringBoot自动配置

@Enable**注解

SpringBoot中包含很多的@Enable开头的注解,这些都是用于动态启用某些功能的,而其底层原理是使用@Import注解导入一些配置类,实现Bean的动态加载

思考Springboot中是否可以直接获取jar包中的Bean?

答案是不可以的,原因是@SpringBootApplication注解中的@ComponentScan注解只能扫到同级别或子包下
解决方案: (1)可以使用@ComponentScan加载启动类上指定扫描扫不到的包路径;(2)也可以使用@Import引入并且会被直接放入IOC容器中
定义注解并importUser

package com.rlw.springbootinit.condition;

import com.rlw.springbootinit.bean.User;
import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(User.class)
public @interface EnableUser {

}

把注解放在启动类上

@SpringBootApplication
@EnableUser
public class SpringbootInitApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootInitApplication.class, args);
        System.out.println(context.getBean("user"));
    }

}
@Import注解

@Enable*注解依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IOC容器中,而@Import提供4种用法:(1)导入Bean,导入一个(2)导入配置类,根据配置的Bean导入多个(3)导入ImportSelector实现类,一般用于加载配置文件中的类(4)导入ImportBeanDefinitionRegistat实现类
导入ImportSelector实现类

public class MyImport implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.rlw.springbootinit.bean.User"};
    }
}
@SpringBootApplication
@Import(MyImport.class)
public class SpringbootInitApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootInitApplication.class, args);
        System.out.println(context.getBean(User.class));
    }

}

SpringBoot自动配置 @EnableAutoConfiguration

1.@EnableAutoConfiguration注解内部使用了@Import({AutoConfigurationImportSelector.class})来加载配置类
2.配置文件位置:META-INF/spring.factories(多数以.autoconfigure结尾),该配置文件中定义了大量的配置类,当SpringBoot应用启动时,会自动加载这些配置类,初始化Bean
3.并不是所有的Bean都会被初始化,在配置类中使用@ConditionOn注解来判断是否需要加载

自定义stater

要求当导入redis坐标的时候,SpringBoot地洞创建Jedis的bean
(1)创建autoconfig
(2)创建starter模块,依赖autoconfig的模块
(3)在autoconfig模块中初始化Jedis的Bean,并定义META-INF/spring.factories文件
(4)在测试模块中引入自定义的starter依赖,测试获取Jedis的Bean,操作redis
在这里插入图片描述

SpringBoot监听机制

SpringBoot的监听事件,其实是对java提供的事件监听机制的封装
java事件监听机制定义了以下几个角色(1)事件:Event,继承java.util.EventObject类的对象(2)事件源:Source,任意对象Object(3)监听器:Listener,实现java.util.EventListener接口的对象

/**
 * 需要在META-INF/spring.factories中配置好键值对信息
 */
@Component
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println("ApplicationContextInitializer");
    }
}
@Component
public class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("ApplicationRunner");
    }
}
@Component
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("CommandLineRunner");
    }
}
/**
 * 需要在META-INF/spring.factories中配置好键值对信息
 */
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
    public MySpringApplicationRunListener(SpringApplication application, String[] args) {
    }

    @Override
    public void starting(ConfigurableBootstrapContext bootstrapContext) {
        System.out.println("starting...项目启动中");
    }

    @Override
    public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
        System.out.println("environmentPrepared...环境对象开始准备");
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        System.out.println("contextPrepared...上下文对象开始准备");
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        System.out.println("contextLoaded...上下文对象开始加载");
    }

    @Override
    public void started(ConfigurableApplicationContext context, Duration timeTaken) {
        System.out.println("contextLoaded...上下文对象加载完成");
    }

    @Override
    public void ready(ConfigurableApplicationContext context, Duration timeTaken) {

    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        System.out.println("contextLoaded...项目启动失败");
    }
}

SpringBoot启动流程分析

初始化:从配置文件中获取初始化的信息进行赋值

1.首先创建一个新的SpringApplication对象源,构造这个对象初始化流程,然后调用他的run方法
2.初始化一些成员变量信息,判断有没有主类
3.通过WebApplicationType.deduceFromClasspath()判断是否是Web环境
在这里插入图片描述
4.紧接着set一系列监听器Initializers与Listenersthis.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));

调用run方法启动
public ConfigurableApplicationContext run(String... args) {
		//1.首先监控耗时
        long startTime = System.nanoTime();
        //2.创建引导上下文
        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
        //3.定义ioc容器变量
        ConfigurableApplicationContext context = null;
        //4.注册表示运行在服务器端
        this.configureHeadlessProperty();
        //5.获取运行监听器
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        //6.启动监听器
        listeners.starting(bootstrapContext, this.mainApplicationClass);

        try {
        	//7.默认应用程序参数,将args封装为 ApplicationArguments 对象
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //8.prepareEnvironment根据运行监听器和参数准备spring环境
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            //9.加载BeanInfo
            this.configureIgnoreBeanInfo(environment);
            //10.输出图标
            Banner printedBanner = this.printBanner(environment);
            //11.接着调用createApplicationContext方法创建应用上下文
            context = this.createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            //12.准备Context
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            //13.真正的去刷新容器,根据配置去初始化Bean
            this.refreshContext(context);
            //14.内部什么都没有做,留给我们自己去扩展
            this.afterRefresh(context, applicationArguments);
            Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup);
            }

            listeners.started(context, timeTakenToStartup);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var12) {
            this.handleRunFailure(context, var12, listeners);
            throw new IllegalStateException(var12);
        }

        try {
            Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
            listeners.ready(context, timeTakenToReady);
            //最后返回容器
            return context;
        } catch (Throwable var11) {
            this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var11);
        }
    }

SpringBoot监控

SpringBoot自带的监控功能Actuator,可以帮助实现对程序内部运行情况监控,比如监控状况、Bean加载情况、配置属性、日志信息等
<dependency>
	<groupld>org.springframeworkboot</groupld>
	<artifactld>spring-boot-starter-actuator</artifactld>
</dependency>
SpringBoot Admin,图形化界面

待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值