0
点赞
收藏
分享

微信扫一扫

spring-boot 之自动装配机制的原理分析

八卦城的酒 2022-09-22 阅读 207


文章目录

  • ​​1.入口类@SpringBootApplication​​
  • ​​1.1.概述​​
  • ​​1.2. @SpringBootApplication 该注解主要组合了以下注解:​​
  • ​​1.2.1.@SpringBootConfiguration​​
  • ​​1.2.1.1.概述​​
  • ​​1.2.1.2.@Configuration(通过案例介绍@Configuration)​​
  • ​​1.2.1.2.1.概述​​
  • ​​1.2.1.2.2.案例演示​​
  • ​​1.2.1.2.2.1.定义一个Bean类:ConfigurationBean​​
  • ​​1.2.1.2.2.2.定义一个Configuration类:ConfigurationDemo,扫描Bean​​
  • ​​1.2.1.2.2.3.定义一个测试类:ConfigurationMain​​
  • ​​1.2.1.3.@Configuration本质上是@Component​​
  • ​​1.2.2.@EnableAutoConfiguration​​
  • ​​1.2.2.1.概述​​
  • ​​1.2.2.2.Import​​
  • ​​1.2.2.2.1.前期准备​​
  • ​​1.2.2.2.1.1.First文件夹​​
  • ​​1.2.2.2.1.2.Second文件夹​​
  • ​​1.2.2.2.2.案例一:不使用import,只能引用当前包下的Bean​​
  • ​​1.2.2.2.2.案例二:使用import,引用别的包下面的bean​​
  • ​​1.2.2.3.ImportSelector​​
  • ​​1.2.2.3.1.UserLoginService和UserBusinessService:创建两个Bean​​
  • ​​1.2.2.3.2.EnableUserDefineService【自定义一个注解】​​
  • ​​1.2.2.3.3.UserImportSelector​​
  • ​​1.2.2.3.5.UserMain​​
  • ​​1.2.2.4.ImportBeanDefinitionRegistrar​​
  • ​​1.2.2.4.1.UserLogginDefinitionRegistrar:定义注册Registrar,实现ImportBeanDefinitionRegistrar​​
  • ​​1.2.2.4.2.UserMain:导入UserLogginDefinitionRegistrar,进行测试,看是否注入UserLoginService的bean​​
  • ​​1.2.2.5.SPI:回到@EnableAutoConfiguration的AutoConfigurationImportSelector​​
  • ​​1.2.2.5.1.源码​​
  • ​​1.2.2.5.1.1.AutoConfigurationImportSelector.selectImports()方法​​
  • ​​1.2.2.5.1.2.AutoConfigurationMetadataLoader.loadMetadata()加载spring-autoconfigure-metadata.properties​​
  • ​​1.2.2.5.1.3.加载上面Configuration中的Bean(最终在 META-INF/spring.factories)​​
  • ​​1.2.2.5.2.案例:自定义META-INF/spring.factories​​
  • ​​1.2.2.5.2.1.创建新项目demo-spring-boot-example-05​​
  • ​​1.2.2.5.2.2.创建MyBean和MyConfig类​​
  • ​​1.2.2.5.2.3.创建spring.fatories​​
  • ​​1.2.2.5.2.4.demo-spring-boot-example-04项目中引入demo-spring-boot-example-05​​
  • ​​1.2.2.5.2.5.demo-spring-boot-example-04项目创建SpiMain进行测试​​
  • ​​1.2.2.5.2.6.总结​​
  • ​​1.2.2.6.Spring条件注入​​
  • ​​1.2.2.6.1.demo-spring-boot-example-05项目中新增spring-autoconfigure-metadata.properties​​
  • ​​1.2.2.6.2.demo-spring-boot-example-05项目版本升级0.0.2​​
  • ​​1.2.2.6.3.demo-spring-boot-example-04重新引用demo-spring-boot-example-05版本的0.0.2版本​​
  • ​​1.2.2.6.4.demo-spring-boot-example-04 类SpiMain开始测试​​
  • ​​1.2.2.6.5.demo-spring-boot-example-04 创建MyTest类,再次进行测试​​
  • ​​1.2.3.@ComponentScan​​
  • ​​1.2.3.2.案例​​
  • ​​1.2.3.2.1.ComponentScanBean​​
  • ​​1.2.3.2.2.ComponentScanMain​​
  • ​​1.2.3.3.设置扫描的路径​​
  • ​​2. 关闭自动配置​​
  • ​​3.自定义Banner​​
  • ​​4.全局配置文件​​
  • ​​4.1.spring-boot 默认配置文件路径​​
  • ​​5.Starter pom​​
  • ​​6.Xml配置文件​​
  • ​​7.日志​​

1.入口类@SpringBootApplication

1.1.概述

Spring Boot的项目一般都会有*Application的入口类,入口类中会有main方法,这是一个标准的Java应用程序的入口方法。
@SpringBootApplication注解是Spring Boot的核心注解,它其实是一个组合注解:

spring-boot 之自动装配机制的原理分析_spring

1.2. @SpringBootApplication 该注解主要组合了以下注解:

1.2.1.@SpringBootConfiguration

1.2.1.1.概述

1.    @SpringBootConfiguration:这是Spring Boot项目的配置注解,这也是一个组合注解:
2. 在Spring Boot项目中推荐使用@SpringBootConfiguration替代@Configuration
所谓的替代,我们可以简单地理解,SpringBoot里面@SpringBootConfiguration就是@Configuration换了一个名字而已

spring-boot 之自动装配机制的原理分析_spring_02

1.2.1.2.@Configuration(通过案例介绍@Configuration)

源代码
​​​https://gitee.com/gaoxinfu_admin/demo-spring-boot/tree/master/demo-spring-boot-example-04/src/main/java/com/gaoxinfu/demo/springboot/componentscan​​

1.2.1.2.1.概述

1.Configuration 这个注解大家应该有用过,它是 JavaConfig形式的基于Spring IOC容器的配置类使用的一种注解。
因为SpringBoot 本质上就是一个spring 应用,所以通过这个注解来加载 IOC 容器的配置是很正常的。所以在启动类
里面标注了@Configuration,意味着它其实也是一个IoC容器的配置类。
2.传统意义上的 spring 应用都是基于 xml 形式来配置 bean的依赖关系。然后通过 spring 容器在启动的时候,把bean
进行初始化并且,如果 bean 之间存在依赖关系,则分析这些已经在 IoC 容器中的 bean 根据依赖关系进行组装。
3.直到 Java5 中,引入了 Annotations 这个特性,Spring 框架也紧随大流并且推出了基于Java代码和 Annotation元
信息的依赖关系绑定描述的方式。也就是JavaConfig。
从spring3 开始,spring 就支持了两种 bean 的配置方式,一种是基于 xml 文件方式、另一种就是 JavaConfig

1.2.1.2.2.案例演示
1.2.1.2.2.1.定义一个Bean类:ConfigurationBean

package com.gaoxinfu.demo.springboot.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 16:56
*/
public class ConfigurationBean {

public void say(){
System.out.println("say() = Hello");
}
}

1.2.1.2.2.2.定义一个Configuration类:ConfigurationDemo,扫描Bean

package com.gaoxinfu.demo.springboot.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 16:55
*/
@Configuration
public class ConfigurationDemo {

@Bean
public ConfigurationBean configurationBean(){
return new ConfigurationBean();
}
}

1.2.1.2.2.3.定义一个测试类:ConfigurationMain

package com.gaoxinfu.demo.springboot.configuration;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 16:56
*/
public class ConfigurationMain {

public static void main(String[] args) {

AnnotationConfigApplicationContext AnnotationConfigApplicationContext=new AnnotationConfigApplicationContext(ConfigurationDemo.class);
ConfigurationBean configurationBean= AnnotationConfigApplicationContext.getBean(ConfigurationBean.class);
if (configurationBean!=null){
configurationBean.say();
}else{
System.out.println("configurationBean = "+configurationBean);
}

}
}

spring-boot 之自动装配机制的原理分析_加载_03

1.2.1.3.@Configuration本质上是@Component

spring-boot 之自动装配机制的原理分析_spring_04

1.2.2.@EnableAutoConfiguration

1.2.2.1.概述

1.  @EnableAutoConfiguration:启用自动配置,
2.

例如:

我们添加了spring-boot-starter-web的依赖,项目中也就会引入SpringMVC的依赖,
Spring Boot就会自动配置tomcat和SpringMVC

spring-boot 之自动装配机制的原理分析_加载_05

EnableAutoConfiguration该注解包含两块 @AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})

spring-boot 之自动装配机制的原理分析_spring_06

1.2.2.2.Import

源代码
​​​https://gitee.com/gaoxinfu_admin/demo-spring-boot/tree/master/demo-spring-boot-example-04/src/main/java/com/gaoxinfu/demo/springboot/enableautoconfiguration/importdemo​​

1.2.2.2.1.前期准备

spring-boot 之自动装配机制的原理分析_加载_07

1.2.2.2.1.1.First文件夹

FirstBean.java

package com.gaoxinfu.demo.springboot.enableautoconfiguration.importdemo.first;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 20:40
*/
public class FirstBean {
}

package com.gaoxinfu.demo.springboot.enableautoconfiguration.importdemo.first;

import com.gaoxinfu.demo.springboot.enableautoconfiguration.importdemo.second.SecondBean;
import com.gaoxinfu.demo.springboot.enableautoconfiguration.importdemo.second.SecondConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;


**FirstConfig.java**
/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 20:40
*/
@Configuration
public class FirstConfig {

@Bean
public FirstBean firstBean(){
return new FirstBean();
}
}

FirstMain.java

package com.gaoxinfu.demo.springboot.enableautoconfiguration.importdemo.first;

import com.gaoxinfu.demo.springboot.configuration.ConfigurationBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 20:42
*/
public class FirstMain {
public static void main(String[] args) {

AnnotationConfigApplicationContext AnnotationConfigApplicationContext=new AnnotationConfigApplicationContext(FirstConfig.class);
String[] beanDefinitionNames=AnnotationConfigApplicationContext.getBeanDefinitionNames();
for (String beanDefinitionName:beanDefinitionNames){
System.out.println("BeanDefinitionName = "+beanDefinitionName);
}
}
}

1.2.2.2.1.2.Second文件夹

package com.gaoxinfu.demo.springboot.enableautoconfiguration.importdemo.second;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 20:42
*/
public class SecondBean {


}

package com.gaoxinfu.demo.springboot.enableautoconfiguration.importdemo.second;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 20:42
*/
@Configuration
public class SecondConfig {

@Bean
public SecondBean secondBean(){
return new SecondBean();
}
}

1.2.2.2.2.案例一:不使用import,只能引用当前包下的Bean

直接运行上面的FirstMain.main方法,只会出现first文件夹下的,second下面的bean不会加载进来

spring-boot 之自动装配机制的原理分析_spring_08

1.2.2.2.2.案例二:使用import,引用别的包下面的bean

FirstConfig.java

package com.gaoxinfu.demo.springboot.enableautoconfiguration.importdemo.first;

import com.gaoxinfu.demo.springboot.enableautoconfiguration.importdemo.second.SecondBean;
import com.gaoxinfu.demo.springboot.enableautoconfiguration.importdemo.second.SecondConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 20:40
*/
@Configuration
@Import(SecondConfig.class)
public class FirstConfig {

@Bean
public FirstBean firstBean(){
return new FirstBean();
}
}

spring-boot 之自动装配机制的原理分析_加载_09

再次运行FirstMain.main()方法,second文件夹bean引入

spring-boot 之自动装配机制的原理分析_java_10

1.2.2.3.ImportSelector

源代码
​​​https://gitee.com/gaoxinfu_admin/demo-spring-boot/tree/master/demo-spring-boot-example-04/src/main/java/com/gaoxinfu/demo/springboot/enableautoconfiguration/importselectordemo​​

1.2.2.3.1.UserLoginService和UserBusinessService:创建两个Bean

package com.gaoxinfu.demo.springboot.enableautoconfiguration.importselectordemo;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 22:05
*/
public class UserLoginService {
}

package com.gaoxinfu.demo.springboot.enableautoconfiguration.importselectordemo;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 22:06
*/
public class UserBusinessService {
}

1.2.2.3.2.EnableUserDefineService【自定义一个注解】

package com.gaoxinfu.demo.springboot.enableautoconfiguration.importselectordemo;

import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

/**
* @Description: 启动用户定义的Service
* @Author: gaoxinfu
* @Date: 2020-04-18 22:07
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({UserImportSelector.class})
public @interface EnableUserDefineService {

Class<?>[] exclude() default {};

}

1.2.2.3.3.UserImportSelector

package com.gaoxinfu.demo.springboot.enableautoconfiguration.importselectordemo;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import java.util.Map;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 22:06
*/
public class UserImportSelector implements ImportSelector {

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
Map<String,Object> attributes=
annotationMetadata.getAnnotationAttributes(EnableUserDefineService.class.getName());
//动态注入bean :自己去实现判断逻辑实现动态配置
Class<?>[] excludeCLass= (Class<?>[]) attributes.get("exclude");

//TODO 这里可以做判断,拉出UserBusinessService和UserLoginService等所有的(匹配到)
//根据exclude 然后删除UserLoginService

return new String[]{UserBusinessService.class.getName()}; //返回的是一个固定的UserBusinessService
}
}

1.2.2.3.5.UserMain

package com.gaoxinfu.demo.springboot.enableautoconfiguration.importselectordemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 22:11
*/
@SpringBootApplication
@EnableUserDefineService(exclude = {UserLoginService.class})
public class UserMain {

public static void main(String[] args) {
ConfigurableApplicationContext configurableApplicationContext
=SpringApplication.run(UserMain.class,args);

System.out.println(configurableApplicationContext.getBean(UserBusinessService.class));
}
}

1.2.2.4.ImportBeanDefinitionRegistrar
1.2.2.4.1.UserLogginDefinitionRegistrar:定义注册Registrar,实现ImportBeanDefinitionRegistrar

package com.gaoxinfu.demo.springboot.enableautoconfiguration.ImportBeanDefinitionRegistrarDemo;

import com.gaoxinfu.demo.springboot.enableautoconfiguration.importselectordemo.UserLoginService;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.StringUtils;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-19 11:16
*/
public class UserLogginDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

Class beanClass= UserLoginService.class;
RootBeanDefinition beanDefinition=new RootBeanDefinition(beanClass);
String beanName= StringUtils.uncapitalize(beanClass.getSimpleName());
registry.registerBeanDefinition(beanName,beanDefinition);
}
}

1.2.2.4.2.UserMain:导入UserLogginDefinitionRegistrar,进行测试,看是否注入UserLoginService的bean

package com.gaoxinfu.demo.springboot.enableautoconfiguration.ImportBeanDefinitionRegistrarDemo;

import com.gaoxinfu.demo.springboot.enableautoconfiguration.importselectordemo.EnableUserDefineService;
import com.gaoxinfu.demo.springboot.enableautoconfiguration.importselectordemo.UserBusinessService;
import com.gaoxinfu.demo.springboot.enableautoconfiguration.importselectordemo.UserLoginService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 22:11
*/
@SpringBootApplication
@Import(UserLogginDefinitionRegistrar.class)
public class UserMain {

public static void main(String[] args) {
ConfigurableApplicationContext configurableApplicationContext
=SpringApplication.run(UserMain.class,args);
System.out.println(configurableApplicationContext.getBean(UserLoginService.class));
}
}

spring-boot 之自动装配机制的原理分析_java_11

1.2.2.5.SPI:回到@EnableAutoConfiguration的AutoConfigurationImportSelector
1.2.2.5.1.源码

spring-boot 之自动装配机制的原理分析_加载_12

1.2.2.5.1.1.AutoConfigurationImportSelector.selectImports()方法

spring-boot 之自动装配机制的原理分析_java_13

1.2.2.5.1.2.AutoConfigurationMetadataLoader.loadMetadata()加载spring-autoconfigure-metadata.properties

spring-boot 之自动装配机制的原理分析_加载_14


spring-boot 之自动装配机制的原理分析_加载_15

**对应类所在的包下面的 spring-autoconfigure-metadata.properties文件 主要是一些spring中的大部分的Configuration,先扫到,后面用那个再说

**

spring-boot 之自动装配机制的原理分析_spring_16

1.2.2.5.1.3.加载上面Configuration中的Bean(最终在 META-INF/spring.factories)

spring-boot 之自动装配机制的原理分析_spring_17

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.filter(configurations, autoConfigurationMetadata);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}

spring-boot 之自动装配机制的原理分析_spring_18

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}

spring-boot 之自动装配机制的原理分析_加载_19


spring-boot 之自动装配机制的原理分析_spring_20

META-INF/spring.factories样例

spring-boot 之自动装配机制的原理分析_spring_21

1.2.2.5.2.案例:自定义META-INF/spring.factories

这里注意下,上面的key是可以进行扩展的,在别的地方定义的同样的key,其value也会被增加扩展加载进来

1.2.2.5.2.1.创建新项目demo-spring-boot-example-05

源码地址
​​​https://gitee.com/gaoxinfu_admin/demo-spring-boot/tree/master/demo-spring-boot-example-05​​

1.2.2.5.2.2.创建MyBean和MyConfig类

package com.gaoxinfu.demo.spring.boot.example05.bean;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-19 14:19
*/
public class MyBean {
}

package com.gaoxinfu.demo.spring.boot.example05.bean;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-19 14:19
*/
@Configuration
public class MyConfig {

@Bean
public MyBean myBean(){
return new MyBean();
}
}

1.2.2.5.2.3.创建spring.fatories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.gaoxinfu.demo.spring.boot.example05.bean.MyConfig

spring-boot 之自动装配机制的原理分析_加载_22

1.2.2.5.2.4.demo-spring-boot-example-04项目中引入demo-spring-boot-example-05

spring-boot 之自动装配机制的原理分析_加载_23

1.2.2.5.2.5.demo-spring-boot-example-04项目创建SpiMain进行测试

package com.gaoxinfu.demo.springboot.enableautoconfiguration.spi;

import com.gaoxinfu.demo.spring.boot.example05.bean.MyBean;
import com.gaoxinfu.demo.spring.boot.example05.bean.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-19 14:24
*/
@SpringBootApplication
public class SpiMain {

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

spring-boot 之自动装配机制的原理分析_spring_24

1.2.2.5.2.6.总结

1.可以看得出来,demo-spring-boot-example-05中的spring.factories中我们配置的MyBean这个类已经被加载IOC容器中了

1.2.2.6.Spring条件注入
1.2.2.6.1.demo-spring-boot-example-05项目中新增spring-autoconfigure-metadata.properties

spring-boot 之自动装配机制的原理分析_java_25

spring-autoconfigure-metadata.properties配置内容
即当com.gaoxinfu.demo.springboot.enableautoconfiguration.spi.MyTest这个类存在的时候,
才会加载MyConfig中的相关bean到IOC中

ConditionalOnClass

com.gaoxinfu.demo.spring.boot.example05.bean.MyConfig.ConditionalOnClass=com.gaoxinfu.demo.springboot.enableautoconfiguration.spi.MyTest

1.2.2.6.2.demo-spring-boot-example-05项目版本升级0.0.2

spring-boot 之自动装配机制的原理分析_java_26

1.2.2.6.3.demo-spring-boot-example-04重新引用demo-spring-boot-example-05版本的0.0.2版本

spring-boot 之自动装配机制的原理分析_java_27

1.2.2.6.4.demo-spring-boot-example-04 类SpiMain开始测试

package com.gaoxinfu.demo.springboot.enableautoconfiguration.spi;

import com.gaoxinfu.demo.spring.boot.example05.bean.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-19 14:24
*/
@SpringBootApplication
public class SpiMain {

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

spring-boot 之自动装配机制的原理分析_spring_28


因为spi文件夹下面没有MyTest类,导致MyConfig将Bean注入的IOC容器中

spring-boot 之自动装配机制的原理分析_加载_29

1.2.2.6.5.demo-spring-boot-example-04 创建MyTest类,再次进行测试

package com.gaoxinfu.demo.springboot.enableautoconfiguration.spi;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-19 16:48
*/
public class MyTest {
}

再次运行SpiMain中的Main方法,成功

spring-boot 之自动装配机制的原理分析_加载_30

1.2.3.@ComponentScan

@ComponentScan:默认扫描@SpringBootApplication所在类的同级目录以及它的子目录。

1.2.3.2.案例
1.2.3.2.1.ComponentScanBean

package com.gaoxinfu.demo.springboot.componentscan;

import org.springframework.stereotype.Service;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 16:56
*/
@Service
public class ComponentScanBean {

public void say(){
System.out.println("say() = Hello");
}
}

1.2.3.2.2.ComponentScanMain

package com.gaoxinfu.demo.springboot.componentscan;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

/**
* @Description:
* @Author: gaoxinfu
* @Date: 2020-04-18 16:56
*/
@ComponentScan
public class ComponentScanMain {

public static void main(String[] args) {

AnnotationConfigApplicationContext AnnotationConfigApplicationContext=new AnnotationConfigApplicationContext(ComponentScanMain.class);
String[] definitionNames= AnnotationConfigApplicationContext.getBeanDefinitionNames();
for(int i=0;i< definitionNames.length;i++){
System.out.println("definitionName = "+definitionNames[i]);
}

}
}

会自动扫面到@Service的类ComponentScanBean

spring-boot 之自动装配机制的原理分析_java_31

1.2.3.3.设置扫描的路径

1.也可以通过
@ComponentScan(basePackages = "com.gaoxinfu.demo.springboot.componentscan")

spring-boot 之自动装配机制的原理分析_spring_32

多个路径的话,可以用逗号分隔开

@ComponentScan(basePackages = "com.gaoxinfu.demo.springboot.componentscan,com.gaoxinfu.demo.springboot.configuration")

spring-boot 之自动装配机制的原理分析_java_33

2. 关闭自动配置

通过上述,我们得知,Spring Boot会根据项目中的jar包依赖,自动做出配置,
Spring Boot支持的自动配置如下(非常多):

spring-boot 之自动装配机制的原理分析_java_34

如果我们不需要Spring Boot自动配置,想关闭某一项的自动配置,该如何设置呢?
比如:我们不想自动配置Redis,想手动配置。

spring-boot 之自动装配机制的原理分析_spring_35

3.自定义Banner

启动Spring Boot项目后会看到这样的图案:

spring-boot 之自动装配机制的原理分析_加载_36

这个图片其实是可以自定义的:

​​ http://patorjk.com/software/taag/#p=display&f=Graffiti&t=Type%20Something%20​​

spring-boot 之自动装配机制的原理分析_java_37

拷贝生成的字符到一个文本文件中,并且将该文件命名为banner.txt
将banner.txt拷贝到项目的resources目录中:

spring-boot 之自动装配机制的原理分析_java_38

重新启动程序,查看效果,会有新的图案显示

如果不想看到任何的banner,也是可以将其关闭的:

spring-boot 之自动装配机制的原理分析_spring_39

4.全局配置文件

4.1.spring-boot 默认配置文件路径

xxxx-autoconfigure-xxx.jar包下

有可能多个,下面是其中一个 spring-boot-autoconfigure-xxx.jar

spring-boot 之自动装配机制的原理分析_加载_40

5.Starter pom

spring-boot 之自动装配机制的原理分析_spring_41

spring-boot 之自动装配机制的原理分析_java_42


spring-boot 之自动装配机制的原理分析_spring_43


spring-boot 之自动装配机制的原理分析_加载_44

6.Xml配置文件

spring-boot 之自动装配机制的原理分析_java_45

7.日志

Spring Boot对各种日志框架都做了支持,我们可以通过配置来修改默认的日志的配置:

#设置日志级别
logging.level.org.springframework=DEBUG

格式:
logging.level.*= # Log levels severity mapping. For instance `logging.level.org.springframework=DEBUG`


举报

相关推荐

0 条评论