Spring Boot自动装配整理

首先写一个我们自己的HelloWorld配置类

1、基于"注解驱动"实现@Enable模块

@Configuration public class HelloWorldConfiguration {
@Bean
public String helloWorld() {
return "Hello,World";
}
}

再模仿Spring Cloud Feign源码解析 中的@EnableFeignClients代码写一个我们自己的标签

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented @Import(HelloWorldConfiguration.class)
public @interface EnableHelloWorld {
}

@EnableFeignClients Import的是FeignClientsRegistrar.class,而我们这里导入的是HelloWorldConfiguration.class

再编写一个引导类来看一下效果。

@EnableHelloWorld @Configuration public class EnabledHelloWorldBootstrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(EnabledHelloWorldBootstrap.class);
context.refresh();
String helloWorld = context.getBean("helloWorld", String.class);
System.out.printf("helloWorld = %s \n",helloWorld);
context.close();
}
}

运行结果(部分)

15:00:46.060 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
15:00:46.065 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
15:00:46.069 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'helloWorld'
helloWorld = Hello,World
15:00:46.069 [main] INFO org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@31a5c39e: startup date [Thu Nov 21 15:00:45 CST 2019]; root of context hierarchy
15:00:46.070 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
15:00:46.070 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5427c60c: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,enabledHelloWorldBootstrap,com.cloud.demo.config.HelloWorldConfiguration,helloWorld]; root of factory hierarchy

2、基于"接口编程"实现@Enable模块

基于ImportSelector接口实现

假设当前应用支持两种服务类型:HTTP和FTP,通过@EnableServer设置服务器类型(type)提供对应的服务

先定义一个服务接口

public interface Server {
/** * 启动服务器 */ void start();
/** * 关闭服务器 */ void stop();
/** * 服务器类型 */ enum Type {
HTTP, //HTTP服务器
FTP //FTP服务器
}
}

两个实现类

@Component public class HTTPServer implements Server {
@Override
public void start() {
System.out.println("HTTP服务器启动中...");
}

@Override

public void stop() {
System.out.println("HTTP服务器关闭中...");
}
}

@Component public class FTPServer implements Server {
@Override
public void start() {
System.out.println("FTP服务器启动中...");
}

@Override

public void stop() {
System.out.println("FTP服务器关闭中...");
}
}

实现@Enable模块驱动

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented @Import(ServerImportSelector.class)
public @interface EnableServer {
/** * 设置服务器类型 * @return */ Server.Type type(); }

实现Server ImportSelector接口

public class ServerImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//读取EnableServer中所有的属性方法,本例中仅有type()属性方法
//其中key为属性方法的名称,value为属性方法的返回对象 Map annotationAttributes = importingClassMetadata
.getAnnotationAttributes(EnableServer.class.getName());
//获取名为type的属性方法,并且强制转换成Server.Type类型
Server.Type type = (Server.Type) annotationAttributes.get("type");
//导入的类名称数组
String[] importClassNames = new String[0];
switch (type) {
case HTTP:
importClassNames = new String[]{HTTPServer.class.getName()};
break; case FTP:
importClassNames = new String[]{FTPServer.class.getName()};
break; }
return importClassNames;
}
}

标注@EnableServer到引导类EnableServerBootstrap

@Configuration @EnableServer(type = Server.Type.HTTP)
public class EnableServerBootstrap {
public static void main(String[] args) {
//构建Annotation配置驱动Spring上下文
AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext();
//注册当前引导类(被@Configuration标注)到Spring上下文
context.register(EnableServerBootstrap.class);
//启动上下文
context.refresh();
//获取Server Bean对象,实际为HttpServer
Server server = context.getBean(Server.class);
//启动服务器
server.start();
//关闭服务器
server.stop();
}
}

运行结果(部分)

16:52:08.966 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor@2fb3536e]
16:52:08.967 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
16:52:08.975 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
16:52:08.979 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'com.cloud.demo.server.HTTPServer'
HTTP服务器启动中...
HTTP服务器关闭中...

基于ImportBeanDefinitionRegistrar接口实现

替换上例中的ServerImportSelector即可

public class ServerImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//复用 {@link ServerImportSelector} 实现,避免重复劳动
ImportSelector importSelector = new ServerImportSelector();
//筛选Class名称集合
String[] selectedClassNames = importSelector.selectImports(importingClassMetadata);
//创建Bean定义
Stream.of(selectedClassNames)
//转化为BeanDefinitionBuilder对象
.map(BeanDefinitionBuilder::genericBeanDefinition)
//转化为BeanDefinition
.map(BeanDefinitionBuilder::getBeanDefinition)
//注册BeanDefinition到BeanDefinitionRegistry
.forEach(beanDefinition -> BeanDefinitionReaderUtils
.registerWithGeneratedName(beanDefinition,registry));
}
}

替换@EnableServer的@Import

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented @Import(ServerImportBeanDefinitionRegistrar.class)
public @interface EnableServer {
/** * 设置服务器类型 * @return */ Server.Type type(); }

运行结果

17:38:53.147 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
17:38:53.150 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
17:38:53.152 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'com.cloud.demo.server.HTTPServer#0'
HTTP服务器启动中...
HTTP服务器关闭中...

结束语

以往,配置和设置像数据库这样的服务可能需要数周时间,甚至更长的时间。通过使用云平台,组织可以在一个下午就建立数据库并将应用程序连接到该数据库。如引言中所述,这极大地提升了组织的敏捷性,让组织及其开发者可以专注于核心业务目标。

您在本练习中可能已经注意到一个问题,即,需要手动与 Kubernetes 进行大量交互。 尽管在这种小规模练习中这不算什么大问题,而且这对熟悉 Kubernetes 和 kubectl 很有用,但这在实际应用程序中会成为无法衡量的问题。在本系列教程的下一个教程中,我们将研究如何设置流水线以自动完成构建、测试和部署应用程序的过程。

Image placeholder
左一
未设置
  0人点赞

没有讨论,发表一下自己的看法吧

推荐文章
SpringBoot个人应用开发框架(SpringBoot版本2.1)+IDEA

前言: 此笔记为本人首个SpringBoot项目框架学习实践记录,期间参考了许多大神的笔记和心得。 参考文档如下: 项目git地址: 一、创建SpringBoot工程 1.1创建父POM工程结

再见 Spring Boot 1.X ,Spring Boot 2.X 走向舞台中心

2019年8月6日,Spring官方在其博客宣布,SpringBoot1.x停止维护,SpringBoot1.x生命周期正式结束。其实早在2018年7月30号,Spring官方就已经在博客进行过预告,

Spring-SpringAOP原理,手写Spring事务框架

一、Spring核心知识Spring是一个开源框架,Spring是于2003年兴起的一个轻量级的Java开发框架,由RodJohnson在其著作ExpertOne-On-OneJ2EEDevelopm

你知道如何自动保存 Spring Boot 应用进程号吗

1.前言 欢迎阅读SpringBoot2实战系列文章PID对于系统运维来说并不陌生,但是对于一些开发者特别是新手还是要简单介绍一下的。它是ProcessID的简称,是系统分配给一个进程的唯一标识符,

SpringBoot 整合 Dubbo

1.整合dubbo 有的人或许会说已经有spring-cloud了,你整合dubbo干什么,其实没啥意图,主要就是想整合一下,毕竟dubbo在国内使用的还是很多的,你会一点点总不至于让你显得那么尴尬。

SpringBoot 集成 JWT 实现 token 验证,token 注销

什么是JWT Jsonwebtoken(JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC7519).定义了一种简洁的,自包含的方法用于通信双方之间以JSON对象的形

springboot 多数据源,最简单的整合方式

简介 相信大家有配置过多数据源,或者即将配置多数据的朋友们,会发现网上大概有以下几种方案: 1.使用AOP切片进行动态数据源切换 2.使用MapperScan的basePackages配置不同的map

云端的生存之道,第 1 单元:将 Spring Boot 部署到 Kubernetes

初始化Kubernetes集群 第一步是初始化IBMCloud上的Kubernetes集群。IBMCloud可能需要几分钟时间来启动新的Kubernetes集群;因此,通过先执行初始化操作,可以在后台

云端的生存之道,第 2 单元:将 Spring Boot 应用程序连接到云托管的数据库

前提条件 本系列教程的第1部分,因为本教程直接以第1部分中的课程内容和完成的操作为基础。 一个IBMCloud帐户 云原生数据持久性 IBMCloud提供了许多可持久存储数据的选项。在本教程中,我

SpringBoot2.0 支持 https 访问

买了dapideng.com,自然要上https。 其实在之前的博客中,也早有提及配置证书的事儿,只不过这次变成了springboot,它内置了tomcat容器,和把项目打包放在tomcat下面不太一

SpringBoot 中的 Servlet Web 容器

1.前言 SpringBoot支持一下嵌入式Servlet容器: SpringBoot2.0.3.RELEASE需要Java8或9以及SpringFramework5.0.7.RELEASE或更高版本

Spring Boot 高效数据聚合之道

项目地址和示例代码:https://github.com/lvyahui8/spring-boot-data-aggregator 背景 接口开发是后端开发中最常见的场景,可能是RESTFul接口,也

Spring boot 如何快速的配置多个 Redis 数据源

Redis简介 redis多数据源主要的运用场景是在需要使用多个redis服务器或者使用多个redis库,本文采用的是fastdep依赖集成框架,快速集成Redis多数据源并集成lettuce连接池,

Spring Boot到底是怎么运行的,你知道吗?

导读SpringBoot方式的项目开发已经逐步成为Java应用开发领域的主流框架,它不仅可以方便地创建生产级的Spring应用程序,还能轻松地通过一些注解配置与目前比较流行的微服务框架SpringCl

Spring Boot 面试,一个问题就干趴下了!

随着SpringBoot使用越来越广泛,SpringBoot已经成为Java程序员面试的知识点,很多同学对SpringBoot理解不是那么深刻,经常就会被几个连环跑给干趴下了!比如下面这一段的Spri

SpringBoot 深度调优,让你的项目飞起来!

项目调优作为一名工程师,项目调优这事,是必须得熟练掌握的事情。在SpringBoot项目中,调优主要通过配置文件和配置JVM的参数的方式进行。一、修改配置文件关于修改配置文件application.p

使用 Docker 部署 Spring Boot 项目

Docker技术发展为微服务落地提供了更加便利的环境,使用Docker部署SpringBoot其实非常简单,这篇文章我们就来简单学习下。首先构建一个简单的SpringBoot项目,然后给项目添加Doc

Spring Boot 中关于自定义异常处理的套路!

在SpringBoot项目中,异常统一处理,可以使用Spring中@ControllerAdvice来统一处理,也可以自己来定义异常处理方案。SpringBoot中,对异常的处理有一些默认的策略,我们

Github 上 Star 最多的 Spring Boot 个人开源学习项目

2016年,在一次技术调研的过程中认识到了SpringBoot,试用之后便一发不可收拾的爱上它。为了防止学习之后忘记,就在网上连载了 SpringBoot系列文章,没想到这一开始便与SpringBoo

Spring Boot 中的响应式编程和 WebFlux 入门

Spring5.0中发布了重量级组件Webflux,拉起了响应式编程的规模使用序幕。WebFlux使用的场景是异步非阻塞的,使用Webflux作为系统解决方案,在大多数场景下可以提高系统吞吐量。Spr

SpringBoot整合RabbitMQ

SpringBoot整合RabbitMQSpringBoot框架已经提供了RabbitMQ的使用jar包,开发人员在使用RabbitMQ的时候只需要引用jar包简单的配置一下就可以使用RabbitMQ

稳定性专题 | Spring Boot 常见错误及解决方法

导读『StabilityGuide』是阿里多位阿里技术工程师共同发起的稳定性领域的知识库开源项目,涵盖性能压测、故障演练、JVM、应用容器、服务框架、流量调度、监控、诊断等多个技术领域,以更结构化的方

SpringBoot连接多RabbitMQ源

在实际开发中,很多场景需要异步处理,这时就需要用到RabbitMQ,而且随着场景的增多程序可能需要连接多个RabbitMQ。SpringBoot本身提供了默认的配置可以快速配置连接RabbitMQ,但

使用Jenkins一键打包部署SpringBoot应用,就是这么6!

SpringBoot实战电商项目mall(25k+star)地址:https://github.com/macrozheng/mall 摘要任何简单操作的背后,都有一套相当复杂的机制。本文将以Spri

搭建 Spring+SpringMVC+MyBatis 框架

SSM框架整合 pom中添加依赖 添加编辑Spring配置文件 添加编辑SpringMVC配置文件 添加编辑Mybatis配置文件 配置web.xml 1、pom中添加依赖 junit ju