你看这篇文章可以学习如下:
-
首先这篇文章要有一定的基础才可以看,如果你是入门,我建议你还是跟着一个视频或者一本书先入门。
-
第二你可以从这篇文章知道SpringBoot的配置原理
-
另外后续会陆陆续续写完SpringBoot文章了
首先了解一下什么是bean配置
-
bean配置就是对我们自己编写代码入到Spring容器的一个过程
-
Spring有三种配置Bean的方式
- 基于java的
- 基于XMl的
- 基于组件扫描的
-
回顾一下:Spring控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI
- 怎么说呢,我们以前写java代码是要new的,现在不用啦,然后(DI)注入就之后就可以用了
- SpringBoot则是自动配置(自动扫描componentscan)和自动注入(Autowired),不理解这句话不要紧,后面会懂的。
- 使用@Configuration注解将类声明为一个配置类,
- 再使用@Bean注解将方法返回的实例对象添加到容器的上下文中
- @Bean注解的bean的ID默认是方法名,如果要指定名称,可以通过name属性来设置
@Configuration public class WebConfig { @Bean public User user() { return new User("Hello world"); } }2、基于Xml的配置
- 不适用任何注解,自己配置
3、组件扫描的类型
从两个方面对其进行配置:
- 组件扫描(使用Component注解将普通类配置成Bean)
- 自动装配(使用@Autowired(自动注入)使Spring满足Bean的依赖)
- 另外还要注意一些配置扫描的@ComponentScan(“路径”)
1、使用Component注解将普通类配置成Bean
@Component public class Hello { public void HelloWorld(String name){ System.out.println("Hello" + name); } }
2、使用@Autowired(自动注入)使Spring满足Bean的依赖
@Component public class User { @Autowired private Hello hello; public void hello() { hello.HelloWorld(); } }二、来看看SpringBoot实现一个配置
下面这几句话要背下来:
- SpringBoot本质还是一个Spring容器,只是它通过导入依赖实现了不同的功能
- 我们编写的代码就称为组件:通常可以用如下的注解将它入到SpringBoot容器里面:通过注解将它们编写好
- @Component:泛指各种组件
- @Component。
- @Controller:控制层
- @Service:业务层
- @Repository:数据访问层
- 还有如下SpringBoot
- @Autowired,先不解释
- @SpringBootConfiguration先不解释
- 还有等等---------
- 然后通过@ComponentScan手动入容器或者@AutoConfigurationPackage自动的包扫描的时候它来配置
- 然后我们就可以通过@Autowired来用,而Spring要通过一系列的xml哦或者其他的配置
随便你创建一个什么样子的项目,这里重点在于理解其中的原理,而不是重点在于项目。
- 我用我之前创建的一个项目
- 重点就是这个依赖了
(3)小总结一下org.springframework.boot spring-boot-dependencies2.5.6
- 这里才是真正管理SpringBoot应用里面所有依赖版本的地方,SpringBoot的版本控制中心; - 以后我们导入依赖默认是不需要写版本;但是如果导入的包没有在依赖中管理着就需要手动配置版本了;3、启动器:spring-boot-starter
我们导入的依赖就是启动器
- 比如点artifactId:这个就是jwt的启动器
4、启动类分析io.jsonwebtoken jjwt0.9.0
重点看这里,重点看这里,重点看这里:首先可能目路搞的有点乱,但是我建议还是好好的认认真真的看每一个字
@SpringBootApplication @MapperScan("com.xxxx.server.mapper") public class yebApplication { public static void main(String[] args) { SpringApplication.run(yebApplication.class,args); } }(1)点这个SpringBootApplication注解看
看见上面又有这几个注解
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} )
- @ComponentScan
-
这个注解在Spring中很重要 ,它对应XML配置中的元素。
-
作用:自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中
-
- @SpringBootConfiguration:点进去看
- 作用:SpringBoot的配置类 ,标注在某个类上 , 表示这是一个SpringBoot的配置类;
- 我们继续进去这个注解查看:
- 这里的 @Configuration,说明这是一个配置类 ,配置类就是对应Spring的xml 配置文件;
- 里面的 @Component 这就说明,启动类本身也是Spring中的一个组件而已,负责启动应用!
- @EnableAutoConfiguration注解:开启自动配置功能
- 这里要记住一点:以后我们要开启什么功能就要EnableXXX(记住,不理解不要紧)
- 再点EnableAutoConfiguration进去看,比较重要的有下面几个
- 1)@AutoConfigurationPackage
- (1)点@AutoConfigurationPackage进去看:暴露; 如下
@import({Registrar.class})
public @interface AutoConfigurationPackage {
} - (2)@import :Spring底层注解@import , 给容器中导入一个组件:Registrar.class 作用:将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器 ;
- (1)点@AutoConfigurationPackage进去看:暴露; 如下
- 2)再来看@import({AutoConfigurationimportSelector.class}):AutoConfigurationimportSelector :自动配置导入选择器,那么它会导入哪些组件的选择器呢?我们点击去这个类看源码:
- (1)这个类中有一个这样的方法:getCandidateConfigurations
- (2)这个方法又调用了 SpringFactoriesLoader 类的静态方法!我们进入SpringFactoriesLoader类loadFactoryNames() 方法
- (3)我们继续点击查看 loadSpringFactories 方法
- (4)发现一个多次出现的文件:spring.factories,全局搜索它
- 1)@AutoConfigurationPackage
protected ListgetCandidateConfigurations(Annotationmetadata metadata, AnnotationAttributes attributes) { //这里的getSpringFactoriesLoaderFactoryClass()方法 //返回的就是我们最开始看的启动自动导入配置文件的注解类;EnableAutoConfiguration List 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; }
public static ListloadFactoryNames(Class> factoryClass, @Nullable ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); //这里它又调用了 loadSpringFactories 方法 return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList()); }
private static Map> loadSpringFactories(@Nullable ClassLoader classLoader) { //获得classLoader , 我们返回可以看到这里得到的就是EnableAutoConfiguration标注的类本身 MultiValueMap result = (MultiValueMap)cache.get(classLoader); if (result != null) { return result; } else { try { //去获取一个资源 "meta-INF/spring.factories" Enumeration urls = classLoader != null ? classLoader.getResources("meta-INF/spring.factories") : ClassLoader.getSystemResources("meta-INF/spring.factories"); linkedMultiValueMap result = new linkedMultiValueMap(); //将读取到的资源遍历,封装成为一个Properties while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); Iterator var6 = properties.entrySet().iterator(); while(var6.hasNext()) { Entry, ?> entry = (Entry)var6.next(); String factoryClassName = ((String)entry.getKey()).trim(); String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue()); int var10 = var9.length; for(int var11 = 0; var11 < var10; ++var11) { String factoryName = var9[var11]; result.add(factoryClassName, factoryName.trim()); } } } cache.put(classLoader, result); return result; } catch (IOException var13) { throw new IllegalArgumentException("Unable to load factories from location [meta-INF/spring.factories]", var13); } } }
spring.factories文件:在这个位置,我们根据源头打开spring.factories , 看到了很多自动配置的文件;这就是自动配置根源所在!
总结一下:通过@EnableAutoConfiguration实现完成自动扫描,然后原理是里面的@import({AutoConfigurationimportSelector.class}):这个类在起作用,去找到了配置下的文件spring.factories进行了自动配置
- 如果你用的idea的话,可以用Ctrl + n实现全局搜索:WebMvcAutoConfiguration然后进行查看
里面全是Bean的配置 - 在这里面有很多配置:比如重定向呀,控制器等的配置,接下来对这个输入的讲解
-
分析该方法主要分两部分,一部分是SpringApplication的实例化,二是run方法的执行
-
SpringApplication这个类主要做了以下四件事情:
-
推断应用的类型是普通的项目还是Web项目
-
查找并加载所有可用初始化器 , 设置到initializers属性中
-
找出所有的应用程序监听器,设置到listeners属性中
-
推断并设置main方法的定义类,找到运行的主类
-
-
看一下方法
对我们前面的内容大致有了理解后,接下来要深入的了解了
下面以:HttpEncodingAutoConfiguration(Http编码自动配置)为例分析,以他标准方便分析(你可以以ThymeleafAutoConfiguration为例子呀)等
//表示这是一个配置类,和以前编写的配置文件一样,也可以给容器中添加组件; @Configuration //启动指定类的ConfigurationProperties功能; //进入这个HttpProperties查看,将配置文件中对应的值和HttpProperties绑定起来; //并把HttpProperties加入到ioc容器中 @EnableConfigurationProperties({HttpProperties.class}) //Spring底层@Conditional注解 //根据不同的条件判断,如果满足指定的条件,整个配置类里面的配置就会生效; //这里的意思就是判断当前应用是否是web应用,如果是,当前配置类生效 @ConditionalOnWebApplication( type = Type.SERVLET ) //判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器; @ConditionalOnClass({CharacterEncodingFilter.class}) //判断配置文件中是否存在某个配置:spring.http.encoding.enabled; //如果不存在,判断也是成立的 //即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的; @ConditionalOnProperty( prefix = "spring.http.encoding", value = {"enabled"}, matchIfMissing = true ) public class HttpEncodingAutoConfiguration { //他已经和SpringBoot的配置文件映射了 private final Encoding properties; //只有一个有参构造器的情况下,参数的值就会从容器中拿 public HttpEncodingAutoConfiguration(HttpProperties properties) { this.properties = properties.getEncoding(); } //给容器中添加一个组件,这个组件的某些值需要从properties中获取 @Bean @ConditionalOnMissingBean //判断容器没有这个组件? public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); filter.setEncoding(this.properties.getCharset().name()); filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST)); filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE)); return filter; } //。。。。。。。 }
明天再来了有点累了
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)