org.springframework.boot spring-boot-dependencies 2.7.9
依赖中的父类中的父类(最顶层): 存放着所有项目工程所能够使用的依赖版本
org.springframework.boot spring-boot-starter-web
注意:项目启动的环境有很多,只需要修改下面的xxxx内容即可
spring-boot-starter-XXXX
例如:log4j,web,jdbc,aop等等
如果导入这种依赖就会自动将该项目中使用的自动导入依赖,减少了在spring系列各种配置文件的配置流程,极大的解放了双手,通过项目中本身所搭配的环境,来实现代码的运行。
在spring boot框架中有很多很多自动配置类,他都存放在一个已经打包完成的spring jar包中,所有的自动配置类放在次jar包内,只需要进行调用即可
自动配置实现流程: 上面说的是自动配置类存放的位置,接下来我们需要去调用spring.factories中的自动配置类,将标注注解为@configuration的配置类进行反射实例化,并将这些汇总到一个IOC容器中在项目中进行使用。
@SpringBootApplication注解主配置类程序的主入口,开启项目的钥匙
打开注解,看下面三个注解,这三个注解为@SpringBootApplication提供了大部分的功能,当然这么牛逼的注解不光只有这几个注解,
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited
上面这四个注解则是生成注解必不可少的一部分,只要是注解就必不可少的一部分吧。但是对与自动装配却是无关紧要。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package org.springframework.boot;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Indexed;@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {@AliasFor(annotation = Configuration.class)boolean proxyBeanMethods() default true;
}
点进去,我们发现了一个特别熟悉的注解@Configuration ,主要实现的作用的则是,将当前类组为一个配置类相当于spring中的配置文件,将此类交给spring中ioc容器进行统一的管理
注意:在理论意义上spring boot是在spring进行的不断地框架化,它保留了在spring项目中能够使用得到大部分功能,所以注解就可以直接拿来进行用。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package org.springframework.context.annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.annotation.AliasFor;@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {@AliasFor("basePackages")String[] value() default {};@AliasFor("value")String[] basePackages() default {};Class>[] basePackageClasses() default {};Class extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;Class extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;String resourcePattern() default "**/*.class";boolean useDefaultFilters() default true;ComponentScan.Filter[] includeFilters() default {};ComponentScan.Filter[] excludeFilters() default {};boolean lazyInit() default false;@Retention(RetentionPolicy.RUNTIME)@Target({})public @interface Filter {FilterType type() default FilterType.ANNOTATION;@AliasFor("classes")Class>[] value() default {};@AliasFor("value")Class>[] classes() default {};String[] pattern() default {};}
}
@ComponentScan这个注解是不是看着有一丝熟悉,如果你学过spring或者springmvc你在看这个注解就会感到见过,在spring项目地配置文件中,你是否配置过这样的一行代码
context:component-scan 对,不错这个注解实现地就是扫描项目中配置地那些类,亦可以说添加@Component,@Service,@Controller 等注解的类。
上面的两个注解起到的环境搭配的作用,要是想要实现自动装配,靠的还是注解
打开这个注解,注解内部主要的功能代码则是上面的这两部分 ,这两行则是spring boot自动化配置的核心。
@Import:导入类,在实际开发过程中,如果你定义一个类并为这个类添加了应有的配置,那这个类就一定能够被扫描到,然后在注入吗?答案是否定的,我们并不能确定创建的类一定被到的使用,但是@Import则可以替我们保证,由它导入的实体类可以被调用。
添加这个注解主要为了导入AutoConfigurationImportSelector.class,为了确保这个类,能够被调用通过注解进行注入,那么由此可以看出,这个类在实现自动化中发挥着一个怎样的作用了!!!
看一下这个类实现的具体流程
前提我们先了解以下一些其他的信息,在进行类中代码的讲解
AnnotationMetadata
存在两个实现类分别为 StandardAnnotationMetadata
与 AnnotationMetadataReadingVisitor
。StandardAnnotationMetadata
主要使用 Java 反射原理获取元数据,而 AnnotationMetadataReadingVisitor
使用 ASM 框架获取元数据。
类中的方法一:获取数据,如果有则要自动开启自动配置如果没有数据则调用
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {private static final AutoConfigurationEntry EMPTY_ENTRY = new AutoConfigurationEntry();private static final String[] NO_IMPORTS = {};private static final Log logger = LogFactory.getLog(AutoConfigurationImportSelector.class);private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";private ConfigurableListableBeanFactory beanFactory;private Environment environment;private ClassLoader beanClassLoader;private ResourceLoader resourceLoader;private ConfigurationClassFilter configurationClassFilter;@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}
如果方法一中没有元数据,则需要调用此方法 getAutoConfigurationEntry
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}AnnotationAttributes attributes = getAttributes(annotationMetadata);List configurations = getCandidateConfigurations(annotationMetadata, attributes);configurations = removeDuplicates(configurations);Set exclusions = getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);configurations = getConfigurationClassFilter().filter(configurations);fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);}
这个方法里面就是通过调用getCandidateConfigurations 来获取候选的 Bean,并将其存为一个集合,最后经过去重,校验等一系列操作之后,被封装成 AutoConfigurationEntry 对象返回。
protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {List configurations = new ArrayList<>(SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);Assert.notEmpty(configurations,"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "+ "are using a custom packaging, make sure that file is correct.");return configurations;}
通过方法三调用方法四:
protected Class> getSpringFactoriesLoaderFactoryClass() {return EnableAutoConfiguration.class;}
自动化具体流程:
项目启动时,会从spring.factories获取EnableAutoConfiguration中的数据值➡获取自动配置数据,会将这些数据导入到容器中,自动配置类就会生效,搭配自动化环境➡jar包autoconfigure存放着自动配置,他会将配置和组件全都被添加到容器中➡当组件和配置全都被搭配好,就可以直接使用自动化无需在进行手动配置了