先谈一下什么是Spring
Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》。Spring是为了解决企业级应用开发的复杂性而创建的,使用Spring可以让简单的JavaBean实现之前只有EJB才能完成的事情。但是Spring不仅仅局限于服务器端开发,任何Java应用都能在简单性、可测试性和松耦合性等方面从Spring中获益。
为了降低Java开发的复杂性,Spring采用了以下4种关键策略:
1、基于POJO的轻量级和最小侵入性编程;
2、通过依赖注入(DI)和面向接口实现松耦合;
3、基于切面(AOP)和惯例进行声明式编程;
4、通过切面和模版减少样式代码;
什么是SpringBoot
Spring Boot 是所有基于 Spring 开发的项目的起点。Spring Boot 的设计是为了让你尽可能快的跑起来 Spring 应用程序并且尽可能减少你的配置文件。简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架(不知道这样比喻是否合适)。
SpringBoot的四大特性
1、SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一个依赖中,这样就可以一次性添加到项目的Maven或Gradle构建中;
2、自动配置:SpringBoot的自动配置特性利用了Spring4对条件化配置的支持,合理地推测应用所需的bean并自动化配置他们;
3、命令行接口:(Command-line-interface, CLI):SpringBoot的CLI发挥了Groovy编程语言的优势,并结合自动配置进一步简化Spring应用的开发;
4、Actuatir:它为SpringBoot应用的所有特性构建一个小型的应用程序。但首先,我们快速了解每项特性,更好的体验他们如何简化Spring编程模型。
什么是场景启动器
Spring boot将所有的功能场景都抽取出来,做成一个个独立的starters启动器
只有在项目里引入了starters,这些场景的依赖就会导入到工程中
开发中需要什么样的功能,就引入什么场景启动器
如果想使用Spring和JPA进行数据库访问,只需spring-boot-starter-data-jpa在项目中包含依赖项即可。
spring-boot-starter-parent
org.springframework.boot
spring-boot-starter-parent
2.2.1.RELEASE
这是Spring Boot的父级依赖,这样当前的项目就是Spring Boot项目了。
spring-boot-starter-parent 是一个特殊的starter,它用来提供相关的Maven默认依赖。使用它之后,常用的包依赖可以省去version标签。
先来看 parent 的基本功能有哪些?
1、定义了 Java 编译版本为 1.8 。
2、使用 UTF-8 格式编码。
3、继承自 spring-boot-dependencies,这个里边定义了依赖的版本,也正是因为继承了这个依赖,所以我们在写依赖时才不需要写版本号。
4、执行打包操作的配置。
5、自动化的资源过滤。
6、自动化的插件配置。
7、针对 application.properties 和 application.yml 的资源过滤,包括通过 profile 定义的不同环境的配置文件,例如 application-dev.properties 和 application-dev.yml。
下面列举一下常用的starter
spring-boot-starter-web
spring-boot-starter-thymeleaf
spring-boot-starter-test
spring-boot-starter-security
spring-boot-starter-jdbc
spring-boot-starter-freemarker
spring-boot-starter-data-redis
spring-boot-starter-data-solr
spring-boot-starter-data-jpa
spring-boot-starter-aop
spring-boot-starter-batch
spring-boot-starter-amqp
spring-boot-starter-activemq
。。。
@SpringBootApplication
public class BootApplication {
public static void main(String[] args) {
SpringApplication.run(BootApplication.class, args);
}
}
@SpringBootApplication表示这是一个SpringBoot应用
SpringBootApplication
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}
1、@SpringBootConfiguration: Spring Boot的配置类
标注在某个类上,表示这是一个SpringBoot的配置类
其中**@Configuration**:配置类上来标注这个注解
配置类—配置文件:配置类也是容器中的一个组件,其底层是**@Component**
@Configuration
public @interface SpringBootConfiguration {
...
}
@Component
public @interface Configuration {
...
}
**2、@EnableAutoConfiguration:**开启自动配置功能
以前需要配置的东西,Spring Boot帮助我们自动配置;@EnableAutoConfiguration告诉
SpringBoot开启自动配置功能.
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
...
}
**2.1)、@AutoConfigurationPackage:**自动配置包
底层:@Import(AutoConfigurationPackages.Registrar.class)
spring的底层注解@Import,给容器中导入一个组件;
导入的组件由Registrar.class
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
//AnnotationMetadata扫描到的类上有注解的类
//PackageImport(metadata).getPackageName()获取该类的包名
//register注册
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImport(metadata).getPackageName());
}
...
}
以上:将主配置类(@SpringBootApplication标注的类)的所在包及下面所有包里面的所有组件注册到Spring容器。
2.2)、@Import(AutoConfigurationImportSelector.class):
给容器注入组件:AutoConfigurationImportSelector
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
将所有需要导入的组件以全类名的方式返回;这些组件就会被添加到容器中
会给容器中导入非常多的自动配置类(xxxAutoConfiguration),这些配置类的左右是给容器中导入这个场景需要的所有的组件,并配置好这些组件
有了自动配置类,就免去了我们手动编写配置和注入功能组件等工作。
从META-INF/spring.factories里导入EnableAutoConfiguration场景所制定的配置类
SpringBoot使用一个全局的配置文件,配置文件名是固定的
application.properties
application.yml
配置文件放在src/main/resources目录或者类路径/config下
全局配置文件可以对一个springboot的默认配置值进行修改
server:
port: 8080
key和value中间有空格,大小写敏感
k:v 字符串默认不用加单引号或者双引号;
“”:双引号;不会转义字符串里面的特殊字符
name: “zhangsan \n lisi” 输出:zhangsan 换行 lisi
‘’:单引号,会转义特殊字符,只会将其当做一个普通的字符串输出
name: “zhangsan \n lisi” 输出:zhangsan \n lisi
对象表达;
friends:
lastname: zhangsan
age: 25
##或者
friends: {lastname: zhangsan,age: 25}
数组;(用- 值表示数组中的一个元素)
pets:
- cat
- dog
- rabbit
##或者
pets: [cat,dog,rabbit]
MAP;
maps: {k1: v1,k2: v2}
@ConfigurationProperties告诉SpringBoot本类中所有属性和配置文件中相关的配置进行绑定
且只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能
person:
name: lee
age: 28
map: {k1: v1,k2: v2}
pets:
- dog
- cat
- rabbit
实体类:
@Data
@ToString
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private Integer age;
private Map<String,Object> map;
private List<String> pets;
}
同样的配置在application.properties中怎样配置呢:
person.name=lee
person.age=28
person.map.k1=v1
person.map.k2=v2
person.map.pets=dog,cat,rabbit
@ConfigurationProperties是springboot中的注解
@Value是spring中的注解
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.beans.factory.annotation.Value;
@Data
@ToString
@Component
//@ConfigurationProperties(prefix = "person")
public class Person {
@Value("${person.name}")
private String name;
@Value("${person.age}")
private Integer age;
//map
@Value("#{${person.map}}")
private Map<String,String> map;
//list
@Value("#{'${person.pets}'.split(',')}")
private List<String> pets;
}
不过yml要写成一下格式
person:
name: lee
age: 28
map: "{key1: 'value1', key2: 'value2'}"
pets: topic1,topic2,topic3
##不能写成
person:
name: lee
age: 28
map: {k1: v1,k2: v2}
pets:
- dog
- cat
- rabbit
测试:
@RunWith(SpringRunner.class)
@org.springframework.boot.test.context.SpringBootTest
public class SpringBootTest {
@Autowired
private Person person;
@Test
public void contextLoader(){
System.out.println(person);
}
}
@ConfigurationProperties:是默认加载全局配置文件中的值
@PropertySource:加载指定的配置文件
@ImportResource:导入spring的配置文件,让配置文件里面的内容生效
6.1)、@PropertySource
加载指定的配置文件
pet.properties
pet.name=dog
pet.age=5
pet.color=yellow
Pet
@Data
@ToString
@Component
@PropertySource(value = {"classpath:pet.properties"})
public class Pet {
@Value("${pet.name}")
private String name;
@Value("${pet.age}")
private Integer age;
@Value("${pet.color}")
private String color;
}
6.2)、ImportResource
导入spring的配置文件,让配置文件里面的内容生效
beans.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="helloService" class="com.lee.boot.service.HelloService">bean>
beans>
HelloService
package com.lee.boot.service;
public class HelloService {
}
测试:
@RunWith(SpringRunner.class)
@org.springframework.boot.test.context.SpringBootTest
public class SpringBootTest {
@Autowired
private ApplicationContext context;
@Test
public void containBeans(){
boolean res = context.containsBean("helloService");
System.out.println(res);
}
}
结果:false
SpringBoot里面没有spring的配置文件,我们自己编写的配置文件,也不能自动识别;想让spring的配置文件生效,加载进来;就需要将**@ImportResource**标注在一个配置类上
@ImportResource(value = {"classpath:beans.xml"})
@SpringBootApplication
public class BootApplication {
public static void main(String[] args) {
SpringApplication.run(BootApplication.class, args);
}
}
//标注在启动类上也是可以的,因为启动类本身也是一个配置类,其底层也
//注解了@Configuration
结果:true
其实springboot不推荐使用配置文件的方式添加组件,而是推荐使用全注解的方式。
//configuration指明当前类是一个配置类,就是来替代之前的
//spring配置文件
@Configuration
public class MyAppConfig {
//使用@Bean给容器添加组件
//将方法的返回值添加到容器中
//容器中这个组件默认的ID就是方法名
@Bean
public HelloService helloService(){
return new HelloService();
}
}