SpringBoot从入门到放弃,第一章

原创
2019/11/12 14:46
阅读数 194

SpringBoot从入门到放弃,第一章

一、简单概述

先谈一下什么是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编程模型。

二、SpringBoot的场景启动器

什么是场景启动器

Spring boot将所有的功能场景都抽取出来,做成一个个独立的starters启动器

只有在项目里引入了starters,这些场景的依赖就会导入到工程中

开发中需要什么样的功能,就引入什么场景启动器
如果想使用Spring和JPA进行数据库访问,只需spring-boot-starter-data-jpa在项目中包含依赖项即可。

spring-boot-starter-parent

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.1.RELEASE</version>
</parent>

这是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
。。。

三、SpringBoot的启动类

@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场景所制定的配置类

四、YAML配置文件

4.1)、全局配置文件

SpringBoot使用一个全局的配置文件,配置文件名是固定的

application.properties
application.yml

配置文件放在src/main/resources目录或者类路径/config下

全局配置文件可以对一个springboot的默认配置值进行修改

4.2)、默认语法:

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}

4.3)、yaml文件值获取

@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和@Value

@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);
    }
}

六、@PropertySource和@ImportResource

@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

<?xml version="1.0" encoding="UTF-8"?>
<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();
    }
}

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部