哈喽~大家好,这篇看看springboot 项目起步讲解及自动装配原理。
🥇个人主页:个人主页
🥈 系列专栏:【Java框架】
🥉与这篇相关的文章:
【JAVAEE框架】MyBatis与Spring的整合(上)【JAVAEE框架】MyBatis与Spring的整合(上)_程序猿追的博客-CSDN博客【JAVAEE框架】浅谈 AOP 及代码实现【JAVAEE框架】浅谈 AOP 及代码实现_程序猿追的博客-CSDN博客【JAVAEE框架】浅谈 Spring 框架的两大核心思想 AOP 与 IOP【JAVAEE框架】浅谈 Spring 框架的两大核心思想 AOP 与 IOP_程序猿追的博客-CSDN博客
一、前言
1、SpringBoot 简介
SpringBoot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化 Spring 应用的初始搭建以及开发过程。
我们在学习 Spring 的时候说过 Spring 框架是为了简化开发的,而 SpringBoot 是为了简化 Spring 开发的,由此可见,使用 SpringBoot 开发将会更加的方便简捷。
二、SpringBoot 入门案例
1、准备
新建项目选择 Spring Initializr,网址填写 https://start.aliyun.com/(阿里云的网站)
选择要使用的开发工具,常用的有(Spring Web、Lombok、Mysql Driver、Oracle Driver 等)
注:
1、在创建好的工程中不需要创建配置类
2、创建好的项目会自动生成其他的一些文件,而这些文件目前对我们来说没有任何作用,所以可以将这些文件删除。
可以删除的目录和文件如下:**.mvn、.gitignore、HELP.md、mvnw、mvnw.cmd**
2、测试一下
新建实体类 User
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
private String username;
private String password;
}
新建控制层类
@Controller
@RequestMapping("/user")
public class HelloAction {
@RequestMapping("/userDetail")
@ResponseBody
public User userDetail() {
User user = new User("123", "456");
return user;
}
}
application.yml 文件配置
server:
port: 8081
servlet:
context-path: /
一个配置端口号,另一个配置应用的上下文路径。
找到我们的启动类,点击启动
访问路径
http://localhost:8081/user/userDetail
3、效果展示
三、SpringBoot 自动装配原理
1、SpringBoot 自动装配原理(自个认为)
我们创建的一个新工程,默认的 SpringApplication.run 传入启动类的class以及main方法的参数。
eg:
@SpringBootApplication
public class Text {
public static void main(String[] args) {
SpringApplication.run(Text.class,args);
}
}
按住ctrl 点击 run
首先我们从SpringApplication的run方法开始分析,在该方法中调用重载的run方法。
在重载的run方法中,创建了一个SpringApplication实例,并调用重载run方法。
点击 SpringApplication 进去
在SpringApplication构造函数中调用了重载的构造函数。
在重载的构造函数中,完成了当前环境的推断以及ApplicationContextInitializer实现类实例化以及ApplicationListener实现类的实例化等。
2、举个例子
我们建了一个web的项目,也许大家比较好奇SpringBoot是如何推断当前运行环境,这里我们就先分析这个推断运行环境逻辑。
在SpringApplication的重载的构造函数中点击 deduceFromClasspath
跳转到 deduceFromClasspath
这里判断 是什么类型默认为 SERVLET。
当然 SpringApplication 不止做了这些初始化。
明白SpringBoot是如何推断当前运行环境后,接下来我们就分析SpringBoot的核心方法 run方法。
3、**getRunListeners **
**getRunListeners **首先来分析getRunListeners方法,在该方法中,通过getSpringFactoriesInstances方法来获取classpath下META-INF/spring.factories文件中key为org.springframework.boot.SpringApplicationRunListener的value,然后并进行实例化,将结果作为参数传入到SpringApplicationRunListeners的构造函数中,最后返回该实例。
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
4、spring.factories
spring.factories用键值对的方式记录了所有需要加入容器的类,EnableAutoConfigurationImportSelector的selectImports方法返回的类名,来自spring.factories文件内的配置信息,这些配置信息的key等于EnableAutoConfiguration,因为spring boot应用启动时使用了EnableAutoConfiguration注解,所以EnableAutoConfiguration注解通过import注解将EnableAutoConfigurationImportSelector类实例化,并且将其selectImports方法返回的类名实例化后注册到spring容器。
即spring.factories文件是帮助spring-boot项目包以外的bean(即在pom文件中添加依赖中的bean)注册到spring-boot项目的spring容器中。由于@ComponentScan注解只能扫描spring-boot项目包内的bean并注册到spring容器中,因此需要@EnableAutoConfiguration注解来注册项目包外的bean。而spring.factories文件,则是用来记录项目包外需要注册的bean类名。
我们在来看看 @SpringBootApplication 注解
点击 @SpringBootApplication ,发现他其实是个复合注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
这三个不用管,这是大部分的复合注解都有的,主要看这三个。
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
5、@SpringBootConfiguration
先来看第一个:@SpringBootConfiguration
进入这个注解之后会发现
就是一个@Configuration啊,一个JavaConfig配置类
@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
@Configuration // 标记为配置类
public class MyConfig {
@Bean // 给容器添加组件,以方法名作为组件的id,返回类型就是组件的类型,返回值就是组件在容器中的实例
public Book defaultBook() {
return new Book("白夜行", "东野圭吾", "人民邮电出版社");
}
@Bean // 给容器添加组件,以方法名作为组件的id,返回类型就是组件的类型,返回值就是组件在容器中的实例
public Periodical defaultPeriodical() {
return new Periodical("时代经贸", "赵建锁", "北京财贸职业学院");
}
}
test 类
@SpringBootTest
class ConfigurationApplicationTests {
@Autowired
MyConfig myConfig;
@Test
void contextLoads() {
System.out.println(myConfig.defaultBook());
System.out.println(myConfig.defaultPeriodical());
}
}
6、@ComponentScan
这个注解相信大家都认识了,组件扫描
这个扫描的范围是:SpringBoot主启动类的同级路径及子路径
7、@EnableAutoConfiguration
@EnableAutoConfiguration 点击进去,核心:@Import(AutoConfigurationImportSelector.class)
看看AutoConfigurationImportSelector,它是实现了 DeferredImportSelector 的一个类,使用了 selectImports 这个方法,返回值类型是String[],返回的是要加载的Config配置文件的全包名,通过返回这个全包名,我们就能自动装配上这些配置文件下定义的bean对象,从而达到了自动装配的目的!
继续反推,看到 AutoConfigurationEntry 这个类,发现autoConfigurationEntry中保存着我们需要的配置信息,它是通过getAutoConfigurationEntry方法获取的,于是我们继续深入,进入getAutoConfigurationEntry方法
发现返回了两个参数 configurations, exclusions。
configurations显然使我们需要的配置文件,也是我们最关心的,而exclusions字面意思是排除,也就是不需要的,那我们接下来应该关注configurations到底是怎么来的。
方法参数里面有个 Annotation(注解) 加上configurations,确定一行代码
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
点击getCandidateConfigurations,查看
有一串英文 “No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.”,意思是“在META-INF/spring.factories中找不到自动配置类。如果您使用的是自定义打包,请确保文件正确。”
在前面看到配置文件就叫spring.factories,存放的路径是META-INF/spring.factories,很明显就是这个路径下的文件
这里的EnableAutoConfiguration注解,正是我们此行的起点啊…
到这里,自动装配到底是什么,应该比较清楚了,原来他是帮我们加载了各种已经写好的Config类文件,实现了这些JavaConfig配置文件的重复利用和组件化
自动装配笔记参考于这篇博客
五、总结
自动配置简单来说呢,就是将第三方的组件自动装载到IOC容器里面,不需要开发人员再去编写相关的配置,在SpringBoot应用里面呢只需要加上**@SpringBootApplication注解就可以实现自动配置,SpringBootApplication它是一个复合注解,真正实现自动装配的注解是@EnableAutoConfiguration注解**。自动装配的实现呢主要依靠三个核心的关键技术:
1、引入Starter,启动依赖组件的时候,这个组件里面必须包括@Configuration配置类,然后我需要通过Bean注解去声明需要装配到IOC容器里面的Bean对象
2、这个配置类是放在第三方的jar包里面,然后通过Spring Boot中约定大于配置的理念,去把配置类的全路径放在件META_INF/Spring.factories文件里面,SpringBoot就可以知道第三方jar包里面配置类的位置,它主要是依靠Spring里面的SpringFactorierLoader来完成的
3、SpringBoot拿到所有第三方jar包声明的配置类之后,再通过ImportSelector这样一个接口来实现对这些配置类的动态加载,从而去完成自动装配这样的一个动作。
4、个人理解
SpringBoot是约定优于配置这一理念下的一个产物,所以在很多的地方都会看到这一类的思想,它的出现让开发人员可以更加聚焦在业务代码的编写上,而不需要去关系和业务无关的配置,其实自动装配的思想在springframework3.x版本里面的@enable注解,就已经有了实现的一个雏形,@enable注解时候一个模块驱动的意思,就是说我们只要增加@enable注解,就可以自动打开某个功能,而不需要针对这个功能去做Bean的配置,@enable注解的底层是帮我们自动完成这样的一个模块相关bean的注入
不积跬步无以至千里,趁年轻,使劲拼,给未来的自己一个交代!向着明天更好的自己前进吧!
版权归原作者 程序猿追 所有, 如有侵权,请联系我们删除。