文章目录
- 1.入口类@SpringBootApplication
- 1.1.概述
- 1.2. @SpringBootApplication 该注解主要组合了以下注解:
- 1.2.1.@SpringBootConfiguration
- 1.2.2.@EnableAutoConfiguration
- 1.2.2.1.概述
- 1.2.2.2.Import
- 1.2.2.3.ImportSelector
- 1.2.2.4.ImportBeanDefinitionRegistrar
- 1.2.2.5.SPI:回到@EnableAutoConfiguration的AutoConfigurationImportSelector
- 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
- 2. 关闭自动配置
- 3.自定义Banner
- 4.全局配置文件
- 5.Starter pom
- 6.Xml配置文件
- 7.日志
1.入口类@SpringBootApplication
1.1.概述
Spring Boot的项目一般都会有*Application的入口类,入口类中会有main方法,这是一个标准的Java应用程序的入口方法。
@SpringBootApplication注解是Spring Boot的核心注解,它其实是一个组合注解:
1.2. @SpringBootApplication 该注解主要组合了以下注解:
1.2.1.@SpringBootConfiguration
1.2.1.1.概述
1. @SpringBootConfiguration:这是Spring Boot项目的配置注解,这也是一个组合注解:
2. 在Spring Boot项目中推荐使用@SpringBootConfiguration替代@Configuration
所谓的替代,我们可以简单地理解,SpringBoot里面@SpringBootConfiguration就是@Configuration换了一个名字而已
1.2.1.2.@Configuration(通过案例介绍@Configuration)
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);
}
}
}
1.2.1.3.@Configuration本质上是@Component
1.2.2.@EnableAutoConfiguration
1.2.2.1.概述
1. @EnableAutoConfiguration:启用自动配置,
2. 该注解会使Spring Boot根据项目中依赖的jar包自动配置项目的配置项:
例如:
我们添加了spring-boot-starter-web的依赖,项目中也就会引入SpringMVC的依赖,
Spring Boot就会自动配置tomcat和SpringMVC
EnableAutoConfiguration该注解包含两块 @AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
1.2.2.2.Import
1.2.2.2.1.前期准备
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不会加载进来
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();
}
}
再次运行FirstMain.main()方法,second文件夹bean引入
1.2.2.3.ImportSelector
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));
}
}
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
**对应类所在的包下面的 spring-autoconfigure-metadata.properties文件 主要是一些spring中的大部分的Configuration,先扫到,后面用那个再说
**
1.2.2.5.1.3.加载上面Configuration中的Bean(最终在 META-INF/spring.factories)
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);
}
}
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;
}
META-INF/spring.factories样例
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
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进行测试
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));
}
}
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-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
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开始测试
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));
}
}
因为spi文件夹下面没有MyTest类,导致MyConfig将Bean注入的IOC容器中
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方法,成功
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
1.2.3.3.设置扫描的路径
1.也可以通过
@ComponentScan(basePackages = "com.gaoxinfu.demo.springboot.componentscan")
设置扫描的路径
多个路径的话,可以用逗号分隔开
@ComponentScan(basePackages = "com.gaoxinfu.demo.springboot.componentscan,com.gaoxinfu.demo.springboot.configuration")
2. 关闭自动配置
通过上述,我们得知,Spring Boot会根据项目中的jar包依赖,自动做出配置,
Spring Boot支持的自动配置如下(非常多):
如果我们不需要Spring Boot自动配置,想关闭某一项的自动配置,该如何设置呢?
比如:我们不想自动配置Redis,想手动配置。
3.自定义Banner
启动Spring Boot项目后会看到这样的图案:
这个图片其实是可以自定义的:
http://patorjk.com/software/taag/#p=display&f=Graffiti&t=Type%20Something%20
拷贝生成的字符到一个文本文件中,并且将该文件命名为banner.txt
将banner.txt拷贝到项目的resources目录中:
重新启动程序,查看效果,会有新的图案显示
如果不想看到任何的banner,也是可以将其关闭的:
4.全局配置文件
4.1.spring-boot 默认配置文件路径
xxxx-autoconfigure-xxx.jar包下
有可能多个,下面是其中一个 spring-boot-autoconfigure-xxx.jar
5.Starter pom
6.Xml配置文件
7.日志
Spring Boot对各种日志框架都做了支持,我们可以通过配置来修改默认的日志的配置:
#设置日志级别
logging.level.org.springframework=DEBUG
格式:
logging.level.*= # Log levels severity mapping. For instance `logging.level.org.springframework=DEBUG`