java学习day41--Spring Boot(一)入门

Spring Boot(一)--入门

Spring Boot简介

​ SpringBoot就是一个javaweb的开发框架,和SpringMVC类似,对比其他javaweb框架的好处,官方说是简化开发,约定大于配置, you can "just run",能迅速的开发web应用,几行代码开发一个http接口。

发展过程: Java企业级应用->J2EE->spring->springboot

​ Spring Boot 以约定大于配置的核心思想,默认帮我们进行了很多设置,多数 Spring Boot 应用只需要很少的 Spring 配置。

​ 现在软件市场已经形成一定的规模,系统架构的复杂度也越来越高(例如有单体架构,分布式架构,微服务架构)。软件的整个架构体系正在发生很大变化,在这种变化中,企业现在更注重技术的开箱即用,更注重技术在生态圈中的深度融合,更注重轻量级的运维。由此spring boot诞生。

Spring Boot 核心特性

​ Spring boot是一个脚手架(而非框架),构建于Spring框架(Framework)基础之上,基于快速构建理念,提供了自动配置功能,可实现其开箱即用特性(创建完一个基本的项目以后,可零配置或者少量配置即可运行我们的项目),其核心主要有如下几个方面:

起步依赖(Starter Dependency)。

自动配置(Auto Configuration)。

健康检查(Actator)-监控。

Spring Boot的主要优点:

  • 为所有Spring开发者更快的入门
  • 开箱即用,提供各种默认配置来简化项目配置
  • 内嵌式容器简化Web项目
  • 没有冗余代码生成和XML配置的要求

Spring Boot 环境配置

工具下载以及配置

下载JDK1.8,并进行环境变量配置(假如已有则无需再次下载和配置)。

下载最新maven(例如apache-maven-3.6.3,网址http://maven.apache.org/)并解压。

下载sts最新版(jar包需要java -jar命令解压或者直接双击)

创建一个新的工作区

配置maven

三个地方需要配置:

打开maven中的setting.xml文件,并对其如下选项进行配置。

配置maven本地库(从maven远程服务器下载的资源存储到的位置)

<localRepository>${user.home}/.m3/repository</localRepository>

配置maven私服(配置到mirrors标签内部)。

   <mirror>
	<id>aliyun</id>
	<name>aliyun for maven</name>
	<mirrorOf>*</mirrorOf>
	<url>https://maven.aliyun.com/repository/public</url>
   </mirror>

配置maven中的profile(配置到profiles标签内部),设置JDK编译和运行版本。

<profile>
   <id>jdk-1.8</id>
   <activation>
	<activeByDefault>true</activeByDefault>
      <jdk>1.8</jdk>
   </activation>
   <properties>
	   <maven.compiler.source>1.8</maven.compiler.source>
	   <maven.compiler.target>1.8</maven.compiler.target>
	   <maven.compiler.compilerVersion>
       1.8
     </maven.compiler.compilerVersion>
	 </properties>
</profile>

STS整合maven

两个地方需要配置:

Maven --> Installations

Maven --> User Settings

Spring Boot 快速入门

项目创建及结构分析

打开STS 集成开发工具,创建spring boot项目,其具体步骤如下:

第一步:打开项目新建窗口(快捷键ctrl+n), 搜索spring,选择spring starter 项目

第二步:填写Service URL :https://start.spring.io以及其他的基本项目信息

注:这里可能会出现超时,如果出现超时,最简单的办法就是更换一下URL为:https://start.aliyun.com

问题就可以解决,或者换一个网络

第三步:选择Spring Boot版本(可以选择最新的版本,但是不要选择测试的版本)

​ 点击finish之后,项目便开始从maven配置中指定的私服服务器(例如阿里云的maven服务器)去下载起步依赖(SpringBoot项目中默认指定了项目启动时需要的一些jar包依赖),这个过程可能会比较耗时(网络最好不要用手机网络,会导致很多资源下载不下来),假如指定版本的springboot项目以前创建过,它会默认先从本地库查找,假如本地库没有,则从远程库去下载。

​ 项目结构中,所有的类和配置文件都是创建好项目以后,由STS工具帮我们自动创建的。

项目启动过程分析(了解)

springboot项目启动的时候发生了什么?

​ SpringBoot 项目在启动时,首先基于启动入口类上的注解描述,进行自动配置并扫描指定包以及子包中的类进行加载,然后检测类上是否有Spring框架中指定的注解描述(例如@Component,@Controller,@Service 等)。假如有,则将类交给Spring框架中的BeanFactory工厂接口的实现类对象,此工厂对象会基于反射创建Bean的实例,假如此Bean指定了生命周期方法,还会调用生命周期方法。当实例创建以后,Spring框架还会基于类的作用域描述,将实例存储到不同作用域的容器中。以实现Bean对象的科学应用。

1593436571449

项目业务初步实现及测试

注意:springboot启动类:

package com.cy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 由此注解@SpringBootApplication描述的类为springboot项目的启动入口类
 * 记住: springboot的启动入口类只能有一个
 * 	spring boot项目的启动入口类需要使用@SpringBootApplication注解进行描述
 */
@SpringBootApplication
public class CgbSpringboot01Application {
    public static void main(String[] args) {
        SpringApplication.run(CgbSpringboot01Application.class, args);
    }

}

@SpringBootApplication

作用:标注在某个类上说明这个类是SpringBoot的主配置类 , SpringBoot就应该运行这个类的main方法来启动SpringBoot应用;

  • spring boot项目的启动入口类需要使用@SpringBootApplication注解进行描述
  • springboot的启动入口类只能有一个

FAQ分析

 /* FAQ:常见问题
 * 	1 这个类在启动时会做哪些事
	  	a 加载类(将类的信息从磁盘读到内存):线程+IO
	    b 创建字节码对象,(其类型为Class类型)用于存储类的字节码信息
		c 基于字节码对象获取类上的注解信息,判定此类是否要交给spring管理
		d 假如是交给spring管理的对象,spring框 架会创建其对象然后赋子其特性。
		e 基于配置文件(application.properties)以及springboot提供的自动配置对对象进行初始化应用。
	2 请问如何验证启动类在启动在启动时加载了哪些类?(借助JVM参数进行分析)
		a 类加载分析过程参数-XX:+TraceClassLoading(+代表有效参数)
		
	3 在springboot项目中自己的业务代码写到哪里?如何交给spring去管理?
		a 所有的业务代码写到src/test/java目录中启动类所在的包或者子包中
		b 将这些类使用特定注解进行描述(例如 @Commpent @Service ....)
	4 在springboot中我们自己的Java业务测试代码写到哪里?有什么特点?
		所有测试代码写到src/test/java目录中启动测试类所在包或者子包中
 		所有测试类使用@SpringBootTest注解
		所有测试方法使用import org.junit.jupiter.api.Test中的@Test注解;
	*/	

业务实现:

基于SpringBoot脚手架,通过Spring框架进行Bean对象的管理实现。

第一步:创建一个DefaultCache类然后交给spring 管理。

package  com.cy.pj.common.cache;
@Component   
public class  DefaultCache {}

其中,@Component是Spring中用于描述Bean类的一个注解。用于告诉Spring这个类的实例由Spring创建,当此对象由Spring创建和管理时,默认会将对象存储到池(Bean池)中。

第二步:添加sringboot 测试类,进行bean的获取及测试,要放在test目录中:

package com.cy.pj.common.cache;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.stereotype.Component;

//springboot项目中所有的单元测试类都使用@SpringBootTest注解来描述
@SpringBootTest
public class DefaultCacheTests {

    @Autowired
    private DefaultCache defaultCache;
    //所有单元测试方法的Test注解都使用import org.junit.jupiter.api.Test;
    @Test
    public void  testCache() {
        System.out.println(defaultCache);
    }
     /**
	  * 分析:
	  * 1.假如在16行输出defaultCache的值为null,可能的原因是什么?
	  * 1)defaultCache属性上没有使用@Autowried相关注解描述?
	  (spring不认为这个属性的值由它进行注入)
	  * 2)单元测试类上没有使用@SpringBootTest注解描述
	  * 3)Test注解类所在包检测是否有问题,测试类的位置(例如包结构)是否有问题?
	  * 
	  * 2.假如defaultCache的单元测试中出现NoSuchBeanDefinitionException异常,
	  * 其类型为com.cy.pj.common.cache.DefaultCache这个bean对象找不到,请问
	  * 原因可能是什么?
	  * 1)DefaultCache所在的包不在启动类所在包或者子包中。
	  * 2)DefaultCache类没有使用spring指定注解进行描述。
	  */

}

其中:

  • @SpringBootTest 注解用于告诉spring框架,此测试类交给spring管理。
  • @Autowired注解描述属性时,用于告诉spring框架要为此属性注入一个值?(至于注入规则,后面课程慢慢加强)

第三步:代码设计及运行分析,如图所示:

1593418782074

在图中描述了DefaultCacheTests类与DefaultCache类的关系,这两个类通过指定注解(@SpringBootTest,@Component)进行了描述,其意图是告诉spring框架这个两个类的实例的创建由Spring负责,并且由Spring框架基于@Autowired注解的描述完成DefaultCacheTests实例中有关DefaultCache类型的值的注入(DI)。

第四步:为对象设计作用域,设置延迟加载,设置生命周期方法(了解)。

Spring 管理bean对象,会为bean赋予什么特性?这些特性有什么好处?

延迟加载(按需加载,懒加载)特性-暂缓对象的创建,何时需要何时创建?

  • a)优点:可以优化资源的使用。
  • b)缺点:用时在创建可能会导致响应速度降低。
  • c)场景:资源有限,大对象,稀少用能懒加载就懒加载。
  • d)实现:在需要懒加的对象类型上使用@Lazy注解进行描述

作用域(Spring框架为对象提供的作用范围,对象的生命周期只能在指定范围有效)

  • a)优点:让对象在有效范围发挥作用,尽量控制对象的创建和销毁以保证对象的高效,低耗的运行。

  • b)缺点:框架底层设计难度会加大,应用不熟练会导致作用域冲突。

  • c)场景:不同业务,作用域的设计也不同?(例如 对象在整个项目中应用非常频繁可以考虑单例作用域。)

  • d)实现:在需要设定作用域的类上使用@Scope注解进行描述。

      d.1)**@Scope("singleton") 单例作用域**,此作用域的对象在这个内存只有一份,通过
    

    共享设计(bean池),实现对象的可重用性。此对象何时创建由懒加载(Lazy)特性

    设计决定,是否可以被销毁由spring框架决定(一般是在容器销毁时销毁)。适合

    频度应用比较高的对象。

    d.2)@Scope("prototype") 多例作用域,此作用域的对象在需要时创建(与懒加载特性无关),

    每次从容器获取都是一个新的对象,且这些对象spring框架不负责销毁。适合应用频度比

    较低的对象。

生命周期方法(每个对象都有生命周期,但不见得每个对象都会设置生命周期方法)

  • a)如何理解生命周期方法?生命周期方法是在对象生命周期过程中要执行的一些方法。
  • b)设计生命周期方法的目的?对象生命周期的不同阶段执行不同业务(例如servlet init,service,destory)
  • c)Spring如何设计Bean对象生命周期方法?spring框架中使用相关注解对象对生命周期方法进行描述。
 	   **@PostConstruct** 
 此注解描述生命周期初始化方法,在构造方法执行之后执行,用于实现一些资源的初始化操作
    **@PreDestroy** 
此注解描述生命周期销毁方法,在对象销毁之前执行,当作用域为prototype时,此方法不会执行

实例代码

package com.cy.pj.common.pool;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
//@Lazy
//@Scope("singleton") 默认,没有指定scope的时候默认就是singleton作用域
//@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
//@Scope("prototype") //多例
public class ObjectPool {//一个普通的对象池对象
	public ObjectPool() {
		System.out.println("==ObjectPool()==");
	}
	@PostConstruct 
	//此注解描述生命周期初始化方法,在构造方法执行之后执行,
	//用于实现一些资源的初始化操作
	public void init() {
		System.out.println("==init()==");
	}
	@PreDestroy //此注解描述生命周期销毁方法,在对象销毁之前执行
	public void destory() {
		System.out.println("==destory()==");
	}
}

测试方法

package com.cy.pj.common.pool;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class ObjectPoolTests {
	@Autowired
	private ObjectPool objectPool01;
	@Autowired
	private ObjectPool objectPool02;
	@Test
	void testObjectPool() {
		System.out.println(objectPool01==objectPool02);//false
	}
	
}

spring管理bean对象的好处

​ spring 是一个资源整合框架(Framework),通过spring可将很多资源(自己写的对象或第三方提供的对象,例如连接池等)整合在一起,然后进行科学应用,以便更好的对外提供服务。如左下图:

1593428220402

Spring框架可以为由它管理的对象(Bean)提供懒加载策略(对象暂时用不到,则无需加载和实例化),作用域(例如singleton-频繁用时可以考虑内存中只有一份,prototype-使用次数少时可以用时创建,不用时销毁),生命周期方法(更好实现对象的初始化和资源销毁),以实现对象对系统资源的有效使用。同时Spring框架还可以基于用户设计管理对象与对象的依赖关系,以降低对象与对象之间的直接耦合,提高程序的可维护性和可扩展性

项目业务增强实现及测试

第一步:定义业务Cache接口

package com.cy.pj.common.cache;
public interface Cache {

}

第二步:定义WeakCache实现Cache接口.

package  com.cy.pj.common.cache;
import org.springframework.stereotype.Component;
@Component 
//@Component("cache")//假如没有起名,默认为类名,然后首字母小写,例如weakCache
//如果此处起名了,那么创建该对象的实例的名字就是cache,而不是默认的
public class WeakCache implements Cache{

}

第三步:修改DefaultCache,让此类也实现Cache接口,关键代码如下:

package com.cy.pj.common.cache;
@Component
public class DefaultCache implements Cache{
//TODO
}

第四步:单元测试类

package com.cy.pj.common.cache;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import  org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest       
public class CacheTests {

        @Autowired
        @Qualifier("defaultCache")
        private Cache cache;

        @Test
       public void testCache() {
            System.out.println(cache);
        }
}

业务测试运行原理分析:

![img](file:///C:/Users/14354/Desktop/CGBIII-%E8%AF%BE%E5%89%8D%E8%B5%84%E6%96%99/DOCS/01-01-CGB-SPRINGBOOT%E5%85%A5%E9%97%A8/images/image12.png)

思考:

@Autowired注解应用规则?

规则:先基于属性类型查找对象进行注入,假如类型有多个,再基于属性名字进行注入

@Qualifier注解的作用是什么?

配合@Autowired注解使用,按bean名字进行值的注入。

详细说明:

​ @Autowired由spring框架定义,用于描述类中属性或相关方法。Spring框架在项目运行时假如发现由他管理的Bean对象中有使用@Autowired注解描述的属性或方法,可以按照指定规则为属性赋值(DI)。其基本规则是:首先要检测容器中是否有与属性或方法参数类型相匹配的对象,假如有并且只有一个则直接注入。其次,假如检测到有多个,还会按照@Autowired描述的属性或方法参数名查找是否有名字匹配的对象,有则直接注入,没有则抛出异常。最后,假如我们有明确要求,必须要注入类型为指定类型,名字为指定名字的对象还可以使用@Qualifier注解对其属性或参数进行描述(此注解必须配合@Autowired注解使用)。

出现问题以及解决方式:

问题1:不能确定唯一的bean,依赖注入失败:NoUniqueBeanDefin
itionException

Caused by:
org. springframework. beans . factory . NoUniqueBeanDefin
itionException: No qualifying bean of type
' com. cy.pj . common. cache .Cache ' available: expected
single matching bean but found 2:
defaultCache , weakCache

问题分析以及解决:

1 检查哪里对Cache进行了引用。
2 检查对Cache引用时使用的注解描述。
3 检查容器中Cache接口下实现类对象的定义(是否有多个?)。

问题2:找不到对应的bean对象

 org-springframework.beans.factory.NoSuchBeanDefinitionException:
 No bean named 'dafaultCache' available

问题分析以及解决:

1 检查你获取的这个对象实例的类型是否使用了特定注解描述
2 检查你获取的这个对象实例的类型所在的包是否正确
3 假如是基于Bean的名字进行Bean对象的获取,要检测Bean的名字是否正确。

问题3:依赖注入失败:UnsastishedDependengyException

org.springframeworkbe as.factory.UnsastishedDependengyException: Error creating bean with name 'com.cy.pj.common.cache.DefaultCachests': Unsatisfed dependengy expressed through feld '

问题分析以及解决:

1 检查错误代码中自己定义的类(例如DefaultCacheTests)中的属性
2 基于错误分析,哪个属性的值在进行依赖注入时失败了(例如DefaultCache)
3 检查注入失败的属性对应的对象是否交给了Spring管理(例如是否有特定注解描述,包结构是否正确)。
原文地址:https://www.cnblogs.com/liqbk/p/13221455.html