“约定优于配置”的理念。
SpringBoot 是Spring 社区发布的一个开源项目,用来简化新 Spring 应用的初始搭建以及开发过程的。是Spring组件一站式解决方案,主要是简化了使用Spring 的难度,节省了繁重的配置,提供了各种启动器。
特性
- 独立运行的Spring项目;可以以jar 包形式独立运行,java -jar xx.jar。
- 内嵌servlet容器;SpringBoot 可选择内嵌Tomcat,Jetty或Undertow,无须以war包形式部署项目。
- 提供starter起始依赖简化了maven的配置;
- 自动装配Bean;SpringBoot 会根据再类路径中的jar包、类,为jar包里面的类自动配置Bean。
- 准生产的应用监控;比如安全、指标、健康检查等。基于http、ssh、telnet对运行时的项目进行监控。
- 无代码生成和无需xml配置;SpringBoot 通过条件注解来实现。
优点
- 快速构建项目;
- 对主流开发框架的无配置集成;
- 项目可独立运行,无须外部依赖Servlet容器;
- 提供运行时的应用监控;
- 极大地提高了开发、部署效率(自动化部署);
- 与云计算的天然集成。
缺点
- 由于不熟悉底层的原理和配置,报错时比较难定位;
- 缺少服务注册发现,外围监控等外围集成方案;
- 缺少REST落地的URI规划方案。
自动装配
- 获取传入的工厂类名、类加载器;
- 通过类加载器,获取指定的META-INF/spring.factories文件;
- 获取文件中工厂类的全限定类名路径;
- 通过类路径反射得到工厂的class对象、构造方法;
- 生成工厂类实例返回。实例化为对应标注了@Configuration 的JavaConfig 形式的配置类,然后汇总并将其都加载到IOC容器中。
SpringFactoriesLoader.loadFactoryNames(type, classLoader);
//第一步
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
//第二步
private static Map<String, List<String>> loadSpringFactories(
@Nullable ClassLoader classLoader)
{
MultiValueMap<String, String> result
= (MultiValueMap)cache.get(classLoader);
if (result != null) {
return result;
} else {
try {
// 根据spring.factories 文件中类的全路径类名,加载类进来
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
....
}
cache.put(classLoader, result);
return result;
} catch (IOException var13) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
}
}
}
// 第三步,实例化对象,并加载到容器中
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList(names.size());
Iterator var7 = names.iterator();
while(var7.hasNext()) {
String name = (String)var7.next();
try {
// 通过反射,实例化对象
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
T instance = BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
} catch (Throwable var12) {
}
}
return instances;
}
常用注解
- @SpringBootApplication: 核心注解,应用在主类上。由以下三个注解构成:
- @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制;
- @ComponentScan:
- 自动扫描并加载被@Component,@Service,@Controller 注解的Bean,将其加载到IOC 容器中。
- 默认是从声明@ComponentScan 所在类的包下进行扫描。也可通过basePackages等属性来指定自动扫描的范围。
- @Configuration:
- 允许在Spring 上下文中注册额外的 Bean 或导入其他配置类。或通过@ImportResource({"classpath:spring/applicationContext.xml"}) 导入外部配置类;
- 任何一个标注了@Configuration 的Java类定义的都是一个JavaConfig 配置类。
-
@ Import
- 用于引入其它配置类或Bean的注解,将配置类或Bean注册到Spring容器。
- @Import 注解一般和@Configuration注解一起使用。其实现原理涉及到Spring的组件扫描,Bean注册和依赖注入等机制:
- 组件扫描:Spring会通过组件扫描机制,自动扫描并加载带有@Configuration 注解或其它指定注解的配置类,并将其识别为配置类。
- 注册配置类:当一个配置类被识别后,Spring会将其注册到容器中。
- 处理@Import注解:当在配置类上使用@Import注解时,Spring会解析注解的参数,根据参数的不同类型进行处理:
- @Import的参数是其它配置类:Spring会将导入的配置类也加入到容器中;
- @Import的参数是普通类:Spring会将该类实例化为一个Bean,并注册到容器中。
- @Import的参数是实现了ImportSelector接口的类:Spring会调用ImportSelector接口中的selectImports()方法,根据返回的类名数组将相应的类注册为Bean。@EnablAutoConfiguration 中import引入的AutoConfigurationImportSelector.class;
- selectImports()方法实现功能:
- 获取META-INF/spring.factories中EnableAutoConfiguration所对应的Configuration类列表;
- 由@EnableAutoConfiguration注解中的exclude/excludeName参数过滤;
- 再由私有内部类ConfigurationClassFilter筛选一遍,即不满足@Condition的配置类。
- @Import的参数是实现了ImportBeanDefinitionRegistrar接口的类:Spring会调用ImportBeanDefinitionRegistrar接口的registerBeanDefinitions()方法,通过编程方式注册Bean到容器中。这样,可以通过自定义的逻辑来注册额外的Bean。
- @Autowired注解:
- byType按类型进行自动注入;但存在多种同类型时,则会抛异常。
- 结合@Qualifier注解,指定对应的类名,进行byName 按类名注入。
- 当应用在Collection 集合上时,会将所声明类的所有实现类都放在哪个指定的Collection中。如果@Autowired 和Map 集合一起使用,则将它的bean名称作为key,所有的bean 作为value;
@Autowired @Qualifier(name="userDao") private UserDao userDao;
@Autowired private Map<String, IStrategy> stg;
- @Resource:
- 默认是byName 按名称进行自动注入。有两个属性:name 和 type。
- 同时指定了name和type, 则从Spring 上下文中找到唯一匹配的Bean 进行装配,找不到则抛出异常。
- 指定了name,则从上下文中查找名称(Id)匹配的Bean 进行匹配,找不到则抛出异常;
- 指定了type,则从上下文中找到类型匹配的唯一Bean进行装配,找不到或者多个,都会抛出异常。
- name和type都没指定,则自动按照byName 方式进行装配;如果没有匹配,则根据byType 方式进行装配。
- @Value和@ConfigurationProperties
- 读取appliation.yml或配置文件中的参数配置信息;
- @ConfigurationProperties 将配置属性与bean 的属性进行绑定。
@Component @ConfigurationProperties(prefix = "前缀") class LibraryProperties { }