SpringBoot-helloWord!
首先让当前的工程作为Springboot的子工程
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.9.RELEASE</version>
</parent>
然后导入要开发的依赖信息
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
编写主程序类
@SpringBootApplication默认加载当前包和其下所有的子包
主程序类
/**
* 告诉SpringBoot这是一个主程序类
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
编写处理器类
/*
@ResponseBody//表示返回值是写给浏览器的,写在类上表示这个类的所有方法都是如此
@Controller*/
@RestController//这个就是简化的上面的两个注解的合体
public class Hello {
@RequestMapping("/hello")
public String handle01(){
return "hello world!!";
}
}
点击主程序让他跑起来然后去访问就好了
在Springboot里为了简化配置只有一个固定名字的文件application.properties
可以修改默认的配置例如端口号
为了简化部署springboot还提供了插件打包方式为jar
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
然后用Maven进行打包
进入文件目录
然后用Java -jar 命令执行就好了
Springboot自动装配原理
1.1 依赖管理
父项目做依赖管理
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.9.RELEASE</version>
</parent>
他的父项目几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.9.RELEASE</version>
</parent>
开发导入starter场景启动器
1、见到很多 spring-boot-starter-* : *就某种场景 2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入 3、SpringBoot所有支持的场景 https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter 4、见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。 5、所有场景启动器最底层的依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.3.4.RELEASE</version> <scope>compile</scope> </dependency>
可以修改默认版本号
因为在spring-boot-dependencies里面已经做了很多的依赖信息当我们要修改默认的行为的时候我们应该在去spring-boot-dependencies里找对应的版本控制信息然后在自己的pom.xml里面自定义自己的版本控制信息
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
然后导入依赖就可以了
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
1.2自动装配
• 自动配好SpringMV
• 引入SpringMVC全套组件
• 自动配好SpringMVC常用组件(功能)
• 自动配好Web常见功能,如:字符编码问题
• SpringBoot帮我们配置好了所有web开发的常见场景
• 默认的包结构
主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
无需以前的包扫描配置`` 想要改变扫描路径,@SpringBootApplication(scanBasePackages="com.atguigu") 或者@ComponentScan 指定扫描路径
@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(“com.atguigu.boot”)
• 各种配置拥有默认值
• 默认配置最终都是映射到某个类上,如:MultipartProperties
• 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
• 按需加载所有自动配置项
• 非常多的starter
• 引入了哪些场景这个场景的自动配置才会开启
• SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面
Full模式下通过方法调用指向的仍旧是原来的Bean,lite模式下,直接返回新实例对象。
public @interface Configuration {
@AliasFor(
annotation = Component.class
)
String value() default “”;
boolean proxyBeanMethods() default true;
}
proxyBeanMethods表示的是这个配置类是否会被代理增强如果设置为false的话就不会增强代理里面这个类返回的里面的@Bean注解的方法也就是普通方法了
1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
2、配置类本身也是组件
3、proxyBeanMethods:代理bean的方法
Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
组件依赖必须使用Full模式默认。其他默认是否Lite模式
当@Configuration(proxyBeanMethods = true)的时候 Pet pet = run.getBean("pet", Pet.class); Conf bean = run.getBean(Conf.class); Pet pet1 = bean.pet(); System.out.println(pet); System.out.println(pet1); 返回的是同一个对象 当@Configuration(proxyBeanMethods = false)的时候就不是同一个了
@Import()标注在组件上就可以了
@Import({User.class, DBHelper.class})
给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
原生配置文件引入
1、@ImportResource
======================beans.xml=========================
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="haha" class="com.atguigu.boot.bean.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="18"></property>
</bean>
<bean id="hehe" class="com.atguigu.boot.bean.Pet">
<property name="name" value="tomcat"></property>
</bean>
</beans>
测试@ImportResource导入Spring配置文件
@ImportResource("classpath:beans.xml")
public class MyConfig {}
======================测试=================
boolean haha = run.containsBean("haha");
boolean hehe = run.containsBean("hehe");
System.out.println("haha:"+haha);//true
System.out.println("hehe:"+hehe);//true
2、@ConfigurationProperties
第一种方式
prefix 的字符串首字母必须小写,底层是用get set 方法设置值的所有要有set 方法
/**
* 只有在容器中的组件,才会拥有SpringBoot提供的强大功能
*/
@Component
@ConfigurationProperties(prefix = "mycar")
这里的application.xml里面有mycar.brand=BYD mycar.price=10000
这些键值对
public class Car {
private String brand;
private Integer price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", price=" + price +
'}';
}
}
第二种方式@EnableConfigurationProperties
在配置类上面使用@EnableConfigurationProperties(Car.class)
,在Car类上面使用@ConfigurationProperties(prefix = "mycar")
这样的话这个配置类就会为我们自动装配Car对象,名字是这个类的全类名mycar-cn.lf.boot.conterlloer.Ca
r这个时候要是还使用@Component注解的话就会创建两个Bean对象了所以在Car类上面使用一个@ConfigurationProperties(prefix = "mycar")
就好了
自动配置原理入门
SpringBootApplication
@SpringBootApplication三个注解合成
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication{}
@SpringBootConfiguration
底层就是包装后的@Configuration。代表当前是一个配置类
@ComponentScan
默认的扫描路径就是当前包和其所以子包
@EnableAutoConfiguration又由两个注解合成
@AutoConfigurationPackage
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件
public
3.1AutoConfigurationPackage
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}
//利用Registrar给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来?MainApplication 所在包下。
AutoConfigurationPackages.Registrar.class
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0])); }
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件
public @interface AutoConfigurationPackage {}
//利用Registrar给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来?MainApplication 所在包下。
3.2@Import(AutoConfigurationImportSelector.class)
1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2、调用List configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
3、利用工厂加载 Map<String, List> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件
4、从META-INF/spring.factories位置来加载一个文件。
默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
文件里面写死了spring-boot一启动就要给容器中加载的所有配置类
spring-boot-autoconfigure-2.3.4.RELEASE.jar/META-INF/spring.factories
#Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\等等127个
按需开启自动配置项
虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration
按照条件装配规则(@Conditional),最终会按需配置。
例:
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
在DispatcherServletAutoConfiguration中有@EnableConfigurationProperties(WebMvcProperties.class)
在WebMvcProperties.class里面有@ConfigurationProperties(prefix = "spring.mvc")
例:MultipartResolver
防止用户命名的不规范
总结
总结:
• SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
• 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
• 生效的配置类就会给容器中装配很多组件
• 只要容器中有这些组件,相当于这些功能就有了
• 定制化配置
• 用户直接自己@Bean替换底层的组件
• 用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration —> 组件 —> xxxxProperties里面拿值 ----> application.properties
所以可以用application.xml修改默认的行为eg:
server.servlet.encoding.charset=utf-8
server.servlet.encoding.force-request=true
server.servlet.encoding.force-response=true
最佳实战
最佳实践
• 引入场景依赖
• https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
• 查看自动配置了哪些(选做)
• 自己分析,引入场景对应的自动配置一般都生效了
• 配置文件中debug=true开启自动配置报告。Negative(不生效)\Positive(生效)
• 是否需要修改
• 参照文档修改配置项
• https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties
• 自己分析。xxxxProperties绑定了配置文件的哪些。
• 自定义加入或者替换组件
• @Bean、@Component。。。
• 自定义器 XXXXXCustomizer;
• …