SpringBoot_1

1.微服务(Microservice)是什么?

     SOA(面向服务的架构)

     微服务,是与之前的服务化思路和实践相比较而来的。

     早些年的服务实现和实施思路是将很多功能从开发到交付都打包成一个很大的服务单元(一般称为 Monolith),而微服务实现和实施思路则更强调功能趋向单一,服务单元小型化和微型化。如

果用“茶壶煮饺子”来打比方的话,原来我们是在一个茶壶里煮很多个饺子,现在(微服务化之后)则基本上是在一个茶壶煮一个饺子,而这些饺子就是服务的功能,茶壶则是将这些服务功能打包

交付的服务单元,如图 1 所示。

     所以,从思路和理念上来讲,微服务就是要倡导大家尽量将功能进行拆分,将服务粒度做小,使之可以独立承担对外服务的职责,沿着这个思路开发和交付的软件服务实体就叫作“微服务”,

而围绕着这个思路和理念构建的一系列基础设施和指导思想,笔者将它称为“微服务体系”。

2.微服务是怎么来的?

     微服务的概念我们应该大体了解了,那么微服务又是怎么来的?原来将很多功能打包为一个很大的服务单元进行交付的做法不能满足需求吗?

     实际上,并非原来“大一统”(Monolith)的服务化实践不能满足要求,也不是不好,只是,它有自己存在的合理场景。对于 Monolith 服务来说,如果团队不大,软件复杂度不高,那么,使用

Monolith 的形式进行服务化治理是比较合适的,而且,这种方式对运维和各种基础设施的要求也不高。但是,随着软件系统的复杂度持续飙升,软件交付的效率要求更高,投入的人力以及各项

资源越来越多,基于 Monolith 的服务化思路就开始“捉襟见肘”。

     在开发阶段,如果我们遵循 Monolith 的服务化理念,通常会将所有功能的实现都统一归到一个开发项目下,但随着功能的膨胀,这些功能一定会分发给不同的研发人员进行开发,造成的后果

就是,大家在提交代码的时候频繁冲突并需要解决这些冲突,单一的开发项目成为了开发期间所有人的工作瓶颈。为了减轻这种苦恼,我们自然会将项目按照要开发的功能拆分为不同的项目,

从而负责不同功能的研发人员就可以在自己的代码项目上进行开发,从而解决了大家无法在开发阶段并行开发的苦恼。

     到了软件交付阶段,如果我们遵循 Monolith 的服务化理念,那么,我们一定是将所有这些开发阶段并行开发的项目集合到一起进行交付。这就涉及服务化早期实践中比较有名的“火车模型”,

即交付的服务就像一辆火车,而这个服务相关的所有功能对应的项目成果,就是要装上火车车厢的一件件货物,交付的列车只有等到所有项目都开发测试完成后才可以装车出发,完成整个服务

的交付。很显然,只要有一个车厢没有准备好货物(即功能项目未开发测试完成),火车就不能发车,服务就不能交付,这大大降低了服务的交付效率。如果每个功能项目可以各自独立交付,

那么就不需要都等同一辆火车,各自出发就可以了。顺着这个思路,自然而然地,大家逐渐各自独立,每一个功能或者少数相近的功能作为单一项目开发完成后将作为一个独立的服务单元进行

交付,从而在服务交付阶段,大家也能够并行不悖,各自演化而不受影响。

     所以,随着服务和系统的复杂度逐渐飙升,为了能够在整个软件的交付链路上高效扩展,将独立的功能和服务单元进行拆分,从而形成一个一个的微服务是自然而然发生的事情。这就像打不

同的战役一样,在双方兵力不多、战场复杂度不高的情况下,Monolith 的统一指挥调度方式是合适的。而一旦要打大的战役(类似于系统复杂度提升),双方一定会投入大量的兵力(软件研发

团队的规模增长),如果还是在狭小甚至固定的战场上进行厮杀,显然施展不开!

     所以,小战役有小战役的打法,大战役有大战役的战法,而微服务实际上就是一种帮助扩展组织能力、提升团队效率的应对“大战役”的方法,它帮助我们从软件开发到交付,进而到团队和组

织层面多方位进行扩展。

     总的来说,一方面微服务可以帮助我们应对飙升的系统复杂度;另一个方面,微服务可以帮助我们进行更大范围的扩展,从开发阶段项目并行开发的扩展,到交付阶段并行交付的扩展,再到

相应的组织结构和组织能力的扩展,皆因微服务而受惠。

     早期我们从开发到交付,都是单一应用结构,所有功能都集中在一个项目中,统一管理和开发。【雕版印刷】

     微服务就是一个项目中的功能,独立的分成多个子项目,并行开发。【活字印刷】

     微服务其实是一种架构风格,提倡一个应用应该是一组小型服务组成;可以通过HTTP的方式进行互通。

     在没有微服务之前我们软件架构方式称为单体应用:ALL IN ONE。就是所有的内容统一集中在一个应用程序中。

     这种单体应用的优点:开发测试简单,不会涉及多个应用之间的互联互调,应用部署也简单,只需要一个war包就OK,不会对运维造成太大负担,还有就是应用程序的水平扩展也简单,就是新

增模块简单。当并发量高的时候,我们可以将这个单体应用多复制几份部署在多个服务器上,通过负载均衡机制控制运行,可以提高并发访问。

     他的缺点也很明显:那就是到我们需要对程序进行修改的时候就需要重新打包,重新部署,重新运行,这就是一个牵一发动全身的情况,当然更大的挑战是来自于日益增长的软件需求。

     目前我们随便做一个软件都需要提供很多更能,不管这些功能有用没有都得实现,这个一个小应用就都成一个大型应用。而大型应用我们不可能将所有功能全部都写在一个应用中,因为分工

合作麻烦,维护量大,而且这个应用到时候可能谁都不知道这个应用会有多大。所以我们才要学习使用微服务开发,来避免这样的问题。

     可以这样理解:单体应用就是雕版印刷;

                               微服务就是活字印刷。

     微服务:每一个功能元素最终都是一个可独立替换和独立升级的软件单元;

     那么利用微服务搭建起来的项目长什么样?

     这种类似于神经网络一样的结构就是最终微服务构建起来的项目,每一个圆圈就是服务,服务于服务之间通过http协议访问连接。

     那么这种庞大微服务应用程序如何构建和部署整合呢,这时我们的SPringBoot就有用武之地。

     通过SpringBoot快速构建微服务应用,通过SpringCloud进行分布式互联互调,形成分布式结构,通过SpringCloudDataFlow进行流式数据运算和批处理操作。

3.Spring Boot简介

     SpringBoot是Spring团队在2014年,伴随Spring4.0版本推出的一个新的框架。 https://spring.io/

     主要作用:

     SpringBoot使创建独立的、生产级的、基于Spring的应用程序变得容易,您可以“只运行”。

     就是帮助我们快速的创建出基于Spring的应用程序。

     想一想在你没有SpringBoot的时候我们使用Spring创建应用程序,或者是整合SpringMVC、MyBatyis,往往都需要先导入很多的依赖包,然后编写大量的配置文件,然后开发业务逻辑,最后测

试,接下来就是打war包,部署到服务器,部署之前还得配置好服务器环境,这样才完成工作。所以在以前没有SpringBoot的时候,我们对java EE程序的开发都是比较笨重的开发,需要繁多的配

置,带来低下的开发效率和复杂的部署流程,还有第三方技术集成难度大。因此上SpringBoot的出现实际上就是用来简化我们对java EE程序的开发,帮助我们快速的创建出基于Spring的应用程

序。SpringBoot的底层实际上还是使用的Spring技术,他其实就是通过整合Spring提供的针对不同领域的开发框架来达到简化Java EE 程序的开发步骤的

     Spring提供的针对不同领域的开发框架:

            Spring Framework:提供IOC容器

            Spring Cloud:分布式框架

            Spring Data:数据库访问框架

            Spring Security:安全校验框架

            等等......

 

      SpringBoot--帮助我们快速的创建出基于Spring框架的应用程序的一个框架。利用SpringBoot创建的Spring应用程序,可以很轻松的实现Spring各种子框架的应用和整合。

     SpringBoot的优点:

            3.1快速创建独立运行的Spring项目以及与主流框架集成

            3.2使用嵌入式的Servlet容器,应用无需打成WAR包

            3.3 starters自动依赖与版本控制

            3.4大量的自动配置,简化开发,也可修改默认值

            3.5无需配置XML,无代码生成,开箱即用

            3.6准生产环境的运行时应用监控

            3.7 与云计算的天然集成

     在学习使用的SpringBoot之前我们需要我一下的一些基本内容:

           1.熟练使用Spring框架

           2.熟练使用Maven进行项目的构建和依赖包的管理

           3.熟练使用Eclipse或者IDEA

     约束环境:

          1.jdk1.8

          2.maven3.x

          3.IntelliJ IDEA 2017

          4.Spring Boot 1.5.9.RELEASE

4.Spring Boot HelloWorld

     需求:浏览器发送hello请求,服务器接受请求并处理,响应Hello World字符串。

     1. 创建一个maven工程;(jar)

        一路next直至项目创建成功!

      3.pom文件配置

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

           可以帮助我们将开发基于Spring的web应用程序的所有依赖包全部自动导入

      4.在src/main/java下创建控制器类

package com.wangxing.springboot.controller;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class TestController {
    @RequestMapping(value = "/test")
    @ResponseBody
    public String  testController(){
      String info="hello,网星";
      return info;
    }
}

     5.由于我们自己创建的控制器类与SpringBoot的主类不在同一个包中,所以我们需要给主类上添加@ComponentScan(basePackages = "com.wangxing.springboot"),如果我们自己创建的控

制器类与SpringBoot的主类在同一个包中,那么这个注解不用加。

package com.wangxing.springboot.springbootdemo1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackages = "com.wangxing.springboot")
public class Springbootdemo1Application {
    public static void main(String[] args) {
        SpringApplication.run(Springbootdemo1Application.class, args);
    }
}

     6.运行主类中的主方法,应用程序自动部署,内嵌的Servlet容器自动启动

      7.打开浏览器访问         http://localhost:8080/test

       8.将上面的用户程序打成jar包,通过java -jar xxxxx.jar命令来执行

         成功以后会在当前项目的target中生成对应的jar包

            将这个jar包复制出去,编写一个与之对应的批处理文件,双击就可运行。

         打开浏览器访问

5.Spring JavaConfig

      Java 5 的推出,加上当年基于纯 Java Annotation 的依赖注入框架 Guice 的出现,推出并持续完善了基于 Java 代码和 Annotation 元信息的依赖关系绑定描述方式,即 JavaConfig 项目。

基于 JavaConfig 方式的依赖关系绑定描述基本上映射了最早的基于 XML 的配置方式,比如:

      1)表达形式层面

<?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="stubean" class="com.wangxing.javaconfigdemo1.StudentBean"></bean>
</beans>

          而基于 JavaConfig 的配置方式是这样的:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class StudentConfig {
    @Bean
    public StudentBean stubean(){
        return new StudentBean();
    }
}

     任何一个标注了 @Configuration 的 Java 类定义都是一个 JavaConfig 配置类。

     任何一个标注了 @Bean 的方法,其返回值将作为一个 bean 定义注册到 Spring 的 IoC 容器,方法名将默认成为该 bean 定义的 id。

package com.wangxing.javaconfigdemo1;

import static org.junit.Assert.assertTrue;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppTest {
    @Test
    public void test1() {
        ApplicationContext context = new AnnotationConfigApplicationContext(StudentConfig.class);
        StudentBean studentBean=(StudentBean)context.getBean("stubean");
        studentBean.testStudent();
    }
}

      1)构造方法注入

package com.wangxing.javaconfigdemo1;
public class PersonBean {
    public void  testPerson(){
        System.out.println("PersonBean类的testPerson方法");
    }
}
package com.wangxing.javaconfigdemo1;

public class StudentBean {

    private PersonBean personBean;

    public  StudentBean(PersonBean personBean) {
        this.personBean = personBean;
    }
    public void  methodStudent(){
        personBean.testPerson();
        System.out.println("Student类的methodStudent方法");
    }
}

     在 XML 形式中一般是这样的:

<bean id="perbean" class="com.wangxing.javaconfigdemo1.PersonBean" /> 
<bean id="stubean" class="com.wangxing.javaconfigdemo1.StudentBean">
   	<!-- 构造方法注入配置  -->
</bean>

         而在 JavaConfig 中则是这样的:

@Configuration
public class StudentConfig {
    @Bean
    public PersonBean perbean(){
        return new PersonBean();
    }
    @Bean
    public StudentBean stubean(){
        return new StudentBean(perbean());
    }
}

     2)set方法注入

package com.wangxing.javaconfigdemo1;
public class PersonBean {
    public void  testPerson(){
        System.out.println("PersonBean类的testPerson方法");
    }
}
package com.wangxing.javaconfigdemo1;
public class StudentBean {
    private PersonBean personBean;

    public void setPersonBean(PersonBean personBean) {
        this.personBean = personBean;
    }
    public void  methodStudent(){
        personBean.testPerson();
        System.out.println("Student类的methodStudent方法");
    }
}

       在 XML 形式中一般是这样的:

<bean id="perbean" class="com.wangxing.javaconfigdemo1.PersonBean" /> 
<bean id="stubean" class="com.wangxing.javaconfigdemo1.StudentBean">
   	<!-- set方法注入配置  -->
</bean>

      而在 JavaConfig 中则是这样的:

package com.wangxing.javaconfigdemo1;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class StudentConfig {
    @Bean
    public PersonBean perbean(){
        return new PersonBean();
    }
    @Bean
    public StudentBean stubean(){
        StudentBean studentBean=new StudentBean();
        studentBean.setPersonBean(perbean());
        return studentBean;
    }
}

     测试:

@Test
public void test1() {
    ApplicationContext context = new AnnotationConfigApplicationContext(StudentConfig.class);
    StudentBean studentBean=(StudentBean)context.getBean("stubean");
    //studentBean.testStudent();
    studentBean.methodStudent();
}

     如果一个 bean 的定义依赖其他 bean,则直接调用对应 JavaConfig 类中依赖 bean 的创建方法就可以了。

在 JavaConfig 形式的依赖注入过程中,我们使用方法调用的形式注入依赖,如果这个方法返回的对象实例只被一个 bean 依赖注入,那也还好,如果多于一个 bean 需要依赖这个方法调用返回

的对象实例,那是不是意味着我们就会创建多个同一类型的对象实例?

     从代码表述的逻辑来看,直觉上应该是会创建多个同一类型的对象实例,但实际上最终结果却不是这样,依赖注入的都是同一个 Singleton 的对象实例,那这是如何做到的?

     一开始以为 Spring 框架会通过解析 JavaConfig 的代码结构,然后通过解析器转换加上反射等方式完成这一目的,但实际上 Spring 框架的设计和实现者采用了另一种更通用的方式,这在

Spring 的参考文档中有说明。即通过拦截配置类的方法调用来避免多次初始化同一类型对象的问题,一旦拥有拦截逻辑的子类发现当前方法没有对应的类型实例时才会去请求父类的同一方法来

初始化对象实例,否则直接返回之前的对象实例。

       所以,原来 Spring IoC 容器中有的特性(features)在 JavaConfig 中都可以表述,只是换了一种形式而已,而且,通过声明相应的 Java Annotation 反而“内聚”一处,变得更加简洁明了了

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值