1. 首页 > 科技快讯 >

springboot面试题 redis面试必会6题经典

spring boot 怎么实现集群

//根据订单id List获取订单

这个问题比较模糊,集群本身就是一个复杂的话题,你想在那一层实123456789现集群(web?servs?data?等等),你要达到的目的是什么?(负载均衡?宕机会话?性能要求?等等)

springboot面试题 redis面试必会6题经典springboot面试题 redis面试必会6题经典


springboot面试题 redis面试必会6题经典


这个应该是我们用的最多的。首先说优先级,文件可以放在以下4个位置,相同文件从上到下覆盖。外部指的是启动应用程序的目录,例如gradle用application插件打包后,运行的脚本目录就是 ./ :

那么我只能就一些常见的场景,简单介绍Spring boot相关的集群技术

你的微服务如果是无状态的,你可以将它们部署在多个实例上,在前端使用负载均衡器(例如nginx)。

如果你需要session,针对动态容错和部署,你可以看看spring-session

如果需要数据库集群,请参考数据库集群的相关技术,mongoDB,reddis都有自己的方案,

如果是数据缓存集群,也有很多参考,如memcache,Hazelcast等等,

如果你喜欢更不动脑子的套餐,可以看看spring cloud

为什么选择spring boot作为微服务

1. Spring Boot是什么,解决哪些问题

jstl

1) Spring Boot使编码变简单

2) Spring Boot使配置变简单

3) Spring Boot使部署变简单

4) Spring Boot使变简单

5) Spring Boot的不足

2. Spring Boot在平台中的定位,相关技术如何融合

1) SpringBoot与SE在Validation框架中 ,还有其它许多注解,用于进行不同格式的验证,例如:DA +MicroServ + RESTful

2) SpringBoot与Mock

3. 采用了SpringBoot之后,技术管理应该如何进行

首先,我们来看一下spring boot是什么,它帮助我们解决了哪些问题:

从字面理解,Boot是的意思,因此SpringBoot帮助开发者快速搭建Spring框架;

SpringBoot帮助开发者快速启动一个Web容器;

SpringBoot继承了原有Spring框架的基因;

SpringBoot简化了使用Spring的过程。

Spring Boot更多的是采用Ja Config的方式,对Spring进行配置。

可以看到,采用了spring-boot-start-actuator之后,直接以REST的方式,获取进程的运行期性能参数。

当然这些metrics有些是有敏感数据的,spring-boot-start-actuator为此提供了一些Basic Authentication认证的方案,这些方案在实际应用过程中也是不足的。

spring Boot必用依赖框架

Spring Boot系统启动时默认会读取的配置文件,支持properties\yml格式。也就是说,会先加载 application.properties ,根据 spring.profile.active 的设置加载相应的 application-XX.properties 配置,然后按优先级合并配置文件。

使用Lombok框架

在使用Slf4j时,通过`log`调用的每种级别的方法都被重载了多次(各级别对应除了方法名称不同,重载的次数和参数列表均相同),使用的方法是参数列表为`(String format, Object... arguments)`的,例如:

在编写POJO类型(包括实体类、VO、DTO等)时,都有统一的编码规范 ,例如:

由于以上作方式非常固定,且涉及的代码量虽然不难,但是篇幅较长,并且,当类中的属性需要修改时(包括修改原有属性、或增加新属性、删除原有属性),对应的其它方法都需要修改(或重新生成),管理起来比较麻烦。

在Spring Boot中, 添加Lombok依赖 ,可以在创建项目时勾选,也可以后期自行添加,依赖项的代码为:

完成后,在各POJO类型中,将不再需要在源代码添加Setters & Getters、`equals()`、`hashCode()`、`toString()`这些方法, 只需要在POJO类上添加 `@Data` 注解即可 !

当添加`@Data`注解,且删除相关方法后,由于源代码中没有相关方法,则调用了相关代码的方法可能会报错,但是,并不影响程序运行!

为了避免InliJ IDEA判断失误而提示了和错误, 安装Lombok插件 ,可参考:

【注】: 无论是否安装插件,都不影响代码的编写和运行!

Slf4j日志框架

在开发实践中, 不允许 使用` System.out.println() `或类似的输出语句来输出显示关键数据( 核心数据、敏感数据等 ),因为,如果是这样使用,无论是在开发环境,还是测试环境,还是生产环境中,这些输出语句都将输出相关信息,而删除或添加这些输出语句的作成本比较高,作可行性低。

的做法是使用日志框架来输出相关信息!

在Slf4j日志框架中,将日志的可显示级别根据其重要程度( 程度 )由低到高分为:

在配置文件中,可以通过`logging.ll.包名.类名`来设置当前类的日志显示级别,例如:

当设置了显示的日志级别后,仅显示设置级别和更重要的级别的日志,例如,设置为``时,只显示``、`warn`、`error`,不会显示`debug`、`trace`级别的日志!

当输出日志时,通过`log`变量调用`trace()`方法输出的日志就是`trace`级别的,调用`debug()`方法输出的日志就是`debug()`级别的,以此类推,可调用的方法还有`()`、`warn()`、`error()`。

在开发实践中, 关键数据和敏感数据都应该通过`trace()`或`debug()`进行输出 ,在开发环境中,可以将日志的显示级别设置为`trace`,则会显示所有日志,当需要交付到生产环境中时,只需要将日志的显示级别调整为``即可!

默认情况下,日志的显示级别是``,所以,即使没有在配置文件中进行正确的配置,所有、warn、erro别的日志都会输出显示。

以上方法中, 第1个参数是将要输出的字符串的模式(模版) ,在此字符串中,如果需要包含某个变量值,则 使用`{}`表示 ,如果有多个变量值,均是如此,然后,再通过第2个参数(是可变参数)依次表示各`{}`对应的值,例如:

使用这种做法,可以避免多变量时频繁的拼接字符串,另外,日志框架会将第1个参数进行缓存,以此提高后续每一次的执行效率。

在开发实践中,应该对程序执行 关键位置添加日志 的输出,通常包括:

其实, Slf4j日志框架只是 日志 的一种 标准 ,并不是具体的实现(感觉上与Ja中的接口有点相似),常见有具体实现了日志功能的框架有log4j、logback等,为了统一标准,所以才出现了Slf4j,同时,由于log4j、logback等框架实现功能并不统一,所以,Slf4j提供了对主流日志框架的兼容,在Spring Boot工程中,`spring-boot-starter`就已经依赖了`spring-boot-starter-logging`,而在此依赖下,通常包括Slf4j、具体的日志框架、Slf4j对具体日志框架的兼容。

密码加密( 额外知识点 )

【这并不是Spring Boot框架的知识点】

对密码进行加密,可以有效的保障密码安全,即使出现数据库泄密,密码安全也不会受到影响! 为了实现此目标,需要在对密码进行加密时, 使用不可逆的算法进行处理!

通常,不可以使用加密算法对密码进行加密码处理,从严格定义上来看,所有的加密算法都是可以逆向运算的,即同时存在加密和解密这2种作,加密算法只能用于保证传输过程的安全,并不应该用于保证需要存储下来的密码的安全!

哈希算法都是不可逆的,通常,用于处理密码加密的算法中,典型的是一些 消息摘要算法 ,例如 MD5、SHA256 或以上位数的算法。

在消息摘要算法中,以MD5为例,其运算结果是一个128位长度的二进制数,通常会转换成十六进制数显示,所以是32位长度的十六进制数,MD5也被称之为128位算法。理论上,会存在2的128次方种类的摘要结果,且对应2的128次方种不同的消息,如果在未超过2的128次方种消息中,存在2个或多个不同的消息对应了相同的摘要,则称之为:发生了碰撞。一个消息摘要算法是否安全,取决其实际的碰撞概率,关于消息摘要算法的,也是研究其碰撞概率。

存在穷举消息和摘要的对应关系 ,并利用摘要在此对应关系进行查询,从而得知消息的做法,但是,由于MD5是128位算法,全部穷举是不可能实现的,所以,只要原始密码(消息)足够复杂,就不会被收录到所记录的对应关系中去!

为了进一步提高密码的安全性,在使用 消息摘要算法 进行处理时, 通常还会加盐! 盐值可以是任意的字符串,用于与密码一起作为被消息摘要算法运算的数据即可,例如:

加盐的目的 是使得被运算数据变得更加复杂,盐值本身和用法并没有明确要求!

甚至,在某些用法或算法中,还会使用随机的盐值,则可以使用完全相同的原消息对应的摘要却不同!

> 了解:预计算的 哈希链 、 彩虹表 、 雪花算法 。

为了进一步保证密码安全,还可以使用多重加密,即反复调用消息摘要算法。

除此以外,还可以使用安全系数更高的算法,例如SHA-256是256位算法,SHA-384是384位算法,SHA-512是512位算法。

Validation框架

当客户端向提交请求时,如果 请求数据出现 明显的问题(例如关键数据为`null`、字符串的长度不在可接受范围内、其它 格式错误 ),应该直接响应错误,而不是将明显错误的请求参数传递到Serv!

> 关于判断错误,只有涉及数据库中的数据才能判断出结果的,都由Serv进行判断,而基本的格式判断,都由Controller进行判断 。

在Spring Boot项目中,需要添加`spring-boot-starter-validation` 依赖项 ,例如:

在中,首先,对需要检查数据格式的请求参数添加 `@Valid` 或 `@Validated` 注解(这2个注解没有区别),例如:

真正需要检查的是 `AdminAddNewDTO`中各属性的值 ,所以,接下来需要在此类的各属性上通过注解来配置检查的规则,例如:

重启项目,通过不提交用户名的URL(例如: IDEA的控制台会出现以下:

从信息中可以看到,当验证失败时(不符合所使用的注解对应的规则时),会出现`org. spr随机数配置大多用于测试,支持的类型如下:ingframework.validation.BindException `异常,则自行处理此异常即可!

首先,在`State`中添加新的枚举:

然后,在`GlobalExceptionHandler`中添加新的处理异常的方法:

关于错误提示信息,以上内容中出现了`不能为null`的字样,是默认的提示文本,可以通过` @NotNull`注解的 `message` 属性进行配置 ,例如:

然后,在处理异常时,通过异常信息获取自定义的提示文本:

再次运行,在不提交用户名和密码的情况下,会随机的提示用户名或密码验证失败的提示文本中的某1条。

以上注解,包括`@NotNull`是 允许叠加使用 的,即允许在同一个参数属性上添加多个注解!

以上注解均可以配置 `message` 属性,用于指定验证失败的提示文本。

通常:(开发中)

Spring Boot 配置的优先级

本文主要参考 Externalized Configuration

为了能让应用在不同的环境下运行,Spring Boot允许自定义配置文件,如properties文件、yaml文件、系统环境变量参数、命令行参数。配置文件的覆盖优先级如下

Dloper Tools 提供了一些开发帮助工具,在build.g @RequestMapping("/") 和 @RequestMapping 是有区别的radle添加依赖后启用。

Spring Boot会读取在计算机用户的home目录下的 .spring-boot-devtools.properties 文件里的配置参数到该计算级的所有Spring Boot应用中作为顶层配置,如Linux环境下root用户下 ~/.spring-boot-devtools.properties 文件。开发过程中,可以将一些个人参数记录在这个配置文件中,例如ip地址,机器uuid,datasource参数等。在该配置文件中的定义的配置环境并不会影响到应用配置的读取,原话是:

但要注意,该配置优先级,设置的时候需要做好记录否则会出现"原因不明的bug",不过应该很少人会用到这个功能。分析下源码,就是加了一个配置切面,并把其设置为顶层配置:

在测试的时候,可能会使用另一套测试专用的配置,该套配置的优先级高于系统环境变量、ja系统参数、程序内部参数, @TestPropertySource 注解就是用来指定这一类配置的。该注解一共有5个参数可以设置:

如果使用注解的时候没有任何参数,那么会从标注了注解的测试类的包中尝试读取配置文件import org.springframework.web.bind.annotation.RequestMapping;,例如测试类 com.spring.test.DemoTest ,那么相应的默认配置文件为 com.spring.test.DemoTest.properties ,如果没有找到默认的配置文件则抛出非法状态异常。

AbstractTestContextBootstrapper 在初始化上下文的时候会调用一个读取、合并配置的方法 buildMergedContextConfiguration ,该方法通过工具类 TestPropertySourceUtils 读取类的注解信息。 TestPropertySourceUtils 从类的注解解析配置信息后返回一个可合并的配置源。

@SpringBootTest 的value\properties属性用于注入一些自定义的注解,语法要求和 @TestPropertySource 的properties一样,这里就不详细展开了。

运行:

ja -jar .\springbootconfiguraiton.jar --cl.name="Spring Boot Arguments"

从输出的结果中可以看到可以读取到命令行中的配置。

可以在环境变量中定义一个key为SPRING_APPLICATION_JSON的参数,值为json字符串,Spring Boot会解析该json字符串作为参数注入到系统中。SPRING_APPLICATION_JSON可以定义在环境变量、系统配置中,命令行也是可以的,例如命令行参数中用到的demo,执行以下的命令也应该能得到相同的参数结果。

ja -jar .\springbootconfiguraiton.jar2017-04-25 22:45:57.349 INFO 7864 --- [ main] j.LocalContainerEntityMarFactoryBean : Closing JPA EntityMarFactory for persistence unit 'default' SPRING_APPLICATION_JSON='{"cl":{"name"="Spring Boot Arguments"}}'

结果输出是undefined,不知道原因,这个配置方式用的应该也很少,放弃研究。。。

优先级是 ServletConfig > ServletContext ,可以在application.yml中设置:

其中long\int可以限制数据范围,[]是闭区间,()是开区间。

文件的命名为 application-[当前激活的环境名].[yml/properties] ,当前激活的配置可以用 spring.profile.active=[当前激活的环境名] 定义,多个环境名用逗号分隔,未设置时用 default 标识。关于如果修改默认的加载路径和文件名,后面会继续讨论。

不同文件目录下application.properties的优先级和 自定义配置文件 的顺序是一样的。

类似 @TestPropertySource注解 ,在项目中可以方便的注入自定义的配置文件,注解一共有5个参数:

基于sprig boot构建web前端页面采用什么技术实现

当然,牺牲一致性,并不是完全不管数据的一致性,否则数据是混乱的,那么系统可用性再高分布式再好也没有了价值。

spring-boot适合开发web应用的静态资源访问在我们开发Web应用的时候,需要引用大量的js、css、等静态资源。默认配置SpringBoot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则:/static/public/resources/META-INF/resources举例:我们可以在src/main/resources/目录下创建static,在该位置放置一个文件。启动程序后,尝试访问页面的时候,要如何实现呢?模板引擎在动态HTML实现上SpringBoot依然可以完美胜任,并且提供了多种模板引擎的默认配置支持,所以在的模板引擎下,我们可以很快的上手开发站。SpringBoot提供了默认配置的模板引擎主要有以下几种:ThymeleafFreeMarkerVelocityGroovyMustacheSpringBoot建议使用这些模板引擎,避免使用JSP,若一定要使用JSP将无法实现SpringBoot的多种特性,具体可见后文:支持JSP的配置当你使用上述模板引擎中的任何一个,它们默认的模板配置路径为:src/main/resources/templates。当然也可以修改这个路径,具体如何修改,可在后续各模板引擎的配置属性中查询并修改。ThymeleafThymeleaf是一个XML/XHTML/HTML5模板引擎,可用于Web与非Web环境中的应用开发。它是一个开源的Ja库,基于ApacheLnse2.0许可,由DanielFernández创建,该作者还是Ja加密库Jasypt的作者。Thymeleaf提供了一个用于整合SpringMVC的可选模块,在应用开发中,你可以使用Thymeleaf来完全代替JSP或其他模板引擎,如Velocity、FreeMarker等。Thymeleaf的主要目标在于提供一种可被浏览器正确显示的、格式良好的模板创建方式,因此也可以用作静态建模。你可以使用它创建经过验证的XML与HTML模板。相对于编写逻辑或代码,开发者只需将标签属性添加到模板中即可。接下来,这些标签属性就会在DOM(文档对象模型)上执行预先制定好的逻辑。

index.jsp

使用freemarker是最方便的

model.addAttribute("content", hello + "(第二种)");

org.springframework.boot

spring-boot-starter-freemarker

然后直接在src\main\resources\templates,写.ftl文件作为前端页面就行了

spring boot启动不扫描创建bean怎么回事

@return

这几天一直被这个问题困扰,Spring boot启动没报错,就是扫描不到需要注册的类。今天终于发现,Spring boot的启动类需要放在需要扫描类的上层目录,这样才能扫描到同级或者子类需要注册的类。 但是在网上我发现一个其他问题,有人说用 @ComponentScan直接写需要扫描类的路径,但是我试验一直没成功。不知道为什么,麻烦帮忙看下! 刚接触spring boot 先谢谢各位了 。

下图是我要扫描的dao和serv,但是启动后一直报错。报的错一看就是没扫描到类ReadingListReitory,这个类继承JpaReitory

2017-04-25 22:45:57.349 WARN 7864 --- [ main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'readingListController': Unsatisfied dependency expressed through field 'readingListReitory'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.dawn.oket.dao.ReadingListReitory' ailable: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

2017-04-25 22:45:57.349 INFO 7864 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000227: Running hbm2ddl schema export

2017-04-25 22:45:57.349 INFO 7864 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000230: Schema export complete

2017-04-25 22:45:57.359 INFO 7864 --- [ main] o.apache.catalina.core.StandardServ : Stopping serv Tomcat

2017-04-25 22:45:57.399 INFO 7864 --- [ main] utoConfigurationReportHTML、XHTML、CSS、JAVAScript、FLASHLoggingInitializer :

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.

2017-04-25 22:45:57.681 ERROR 7864 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :

APPLICATION FAILED TO START

Description:

Field readingListReitory in org.dawn.oket.serv.ReadingListController required a bean of type 'org.dawn.oket.dao.ReadingListReitory' that could not be found.

Action:

Consider defining a bean of type 'org.dawn.oket.dao.ReadingListReitory' in your configuration.

Disconnected from the target VM, address: '127.0.0.1:52934', transport: 'socket'

Process finished with exit code 1

纯手写:

我也遇到了这个问题,接下来是解决的方法

步:确保application在项目的根目录,这样就可以解决,如果不行,可以使用@ComponentScan或者@ComponentScans,@ComponScans的使用方法可查看源码。

如果步不行,

解@RequestMapping("/page2")决的方法:用

org.mybatis.spring.boot

mybatis-spring-boot-starter

1.3.0

取代pom文件中的artifactId 为mybatis的dependency

=。=

谈谈对spring boot分层中各层的理解

spring.mvc.view.prefix=/WEB-INF/jsp/

1 Dao层:持久层,主要是和数据库进行交// 本例为 /WEB-INF/jsp/index.jsp互

用命令行方式启动Spring Boot应用程序的时候,可以注入一些配置参数,参数的格式是 --key=name 。举个简单的例子,程序直接输出一个参数,然后打成jar包后运行。

dao层首先胡创建dao接口,接着就可以在配置文件中定义该接口的实现类;接着就可以在模块中调用dao的接口进行数据业务的处理,而不用关注此接口的具体实现是哪一个类,dao层的数据源和数据库实在配置文件中进行配置的。

2 Entity层:实体层,数据库在项目中的类

主要用于定义与数据库对象的属性,提供get/set方法,带参和无参的构造方法。

3 Serv层:业务层控制业务

业务模块的逻辑应用设计,和DAO层一样都是先设计接口,再创建要实现的类,然后在配置文件中进行配置其实现的关联。接下来就可以在serv层调用接口进行业务逻辑应用的处理。

好处:封装Serv层的业务逻辑有利于业务逻辑的性和重复利用性。

4.Controller层:控制层 控制业务逻辑

具体的业务模块流程的控制,controller层主要调用Serv层里面的接口控制具体的业务流程,控制的配置也要在配置文件中进行。

Controller和Serv的区别是:Controller负责具体的业务模块流程的控制;Serv层负责业务模块的逻辑应用设计

总结:具体的一个项目中有:controller层调用了Serv层的方法,Serv层调用Dao层的方法,其中调用的参数是使用Entity层进行传递的。

补充:5、View层 此层与控制层结合比较紧密,需要二者结合起来协同工发。View层主要负责前台jsp页面的表示

spring boot单元测试spring context重复加载问题

POST oms/order/updateOrderCollectionStatusInBatch

在使用spring boot框架进行单元测试时对这个context初始化,refrm.addObject("content", hello);esh方法,笔者遇到一个问题,每次执行单元测试类时都会重复加载spring上下文,而加载过程通常都非常耗时,这大大增加了整个单元测试的执行时间,加载过程类似下面的日志:

Spring boot Batch 的启动原理- Configuration

SOA的提出是在企业计算领域,就是要将紧耦合的系统,划分为面向业务的,粗粒度,松耦合,无状态的服务。服务发布出来供其他服务调用,一组互相依赖的服务就构成了SOA架构下的系统。

Spring boot 整合了web 和batch ,但是他们肯定不是同一条路, 在spring boot 中,会推断当前的运行环境。 this.webApplicationType = WebApplicationType.deduceFromClasspath();

Validation框架是专门用于解决 检查数据基本格式有效性 的,最早并不是Spring系列的框架,目前,Spring Boot提供了更好的支持,所以,通常结合在一起使用。

从上文可以看出,Spring 尝试从classpath 里找到特征类,来判断当前app 是什么类型。当然这种判断是有局限性的,有可能是transitive 带进来一个带有servlet 的类被当成了 WebApplicationType.SERVLET, 实际上是个WebApplicationType.NONE;。如果不想以web 运行就是想运行batch 可以在application.properties 强行指定WebApplicationType

具体发生作用的请看下面的stack tr @create 2016年1月5日ace

当一个batch application需要启动,需要 配置JobReitory, Datasource 等等,所有的开始都来自一个annotation @EnableBatchProcessing

当加入@EnableBatchProcessing 时, BatchConfigurationSelector 开始启动,怎么启动的大家可以参考下面的stack trace。

import 类主要是由ConfigurationClassPostProcessor 来实现的。 当BatchConfigurationSelector 被调用的时候,我们可以看到他有两条支路。

那么这两条路有啥不同呢。 主要是job 定义的方式不同。

modular = true 的情况下,下面是一个例子

可以有多个子ApplicationContextFactory ,这样好处是在除了job 大家不可以重复,因为是在不同的context 里,其他的step,reader, writer,processor,mapper ,以及所有的bean等等都可以重名。

那为什么Job 不可以重复,是因为虽然可以重复,但是如果job 也重复,对用户来讲太不友好了。用户可能不知道自己配的是哪个context 的job。具体为什么可以重名要看看GenericApplicationContextFactory 的实现。

当GenericApplicationContextFactory::createApplicationContext, 会触发 ApplicationContextHelper 的构造函数 从而调用 loadConfiguration(config) 把定义的bean 加入到context 里。那么有个问题,parent 在哪里设置,createApplicationContext 是什么时候调用的。

我们继续看ModularConfiguration

从Modular 的角度来看 首先他可以外部注入一个Configurer,如果没有就选择DefaultBatchConfigurer, 如果有多个选择则会抛出。

当然Datasource也可以选择外部注入,或者由 DefaultBatchConfigurer::initialize 方法 SimpleJobLauncher , JobReitory 和 JobExplorer 都是 由FactoryBean 的方式实现的。

在这个DefaultBatchConfigurer 中可以看到JobLauncher 的类型是

initialize 里MapJobReitoryFactoryBean 这个可以重点读一下。 首先用FactoryBean的模式实现了一个ProxyBean,如果想了解FactoryBean 的用法,这是个典型的例子。但是这个FactoryBean 是以api 行为直接调用的,并没有注册到Spring 的context 中。

配置好job 需要的 jobReitory ,jobLauncher等 那么重点来了,下面的AutomaticJobRegistrar 就是来处理ApplicationContextFactory

这个逻辑是把所有的ApplicationContextFactory 的bean instance 放入到AutomaticJobRegistrar 里去。 这就回到了个问题,parent context 是什么时候放进去的。就是在

context.getBeansOfType(ApplicationContextFactory.class) 请看下面的调用栈,在ApplicationContextAwareProcessor 里会自动把parent context 注入。

但是放进去啥时候用呢?我们看一下AutomaticJobRegistrar

原来AutomaticJobRegistrar 是个Smartlifecycle, 从Smartlifecycle的细节可以从 Springboot Smartlifecycle 来得知。它就是在所有bean都初始化结束后开始进行的一个阶段。在这个start 方法中,开始遍历所有的ApplicationContextFactory, 来进行加载。 从上文这个jobLoader 是DefaultJobLoader。

那么可以看看DefaultJobLoader::doLoad 方法

这里有几个关键调用 个是createApplicationContext, 把context 里定义的全部加载到Spring context里去,这就满足了GenericApplicationContextFactory 工作的两个条件。第二个是doRegister(context, job) 里 jobRegistry.register(jobFactory);

我们看一下JobReitory的实现MapJobRegistry::register 方法,在这里就把jobname 和jobFactory 的键值对存储起来了。

这样就可以通过JobReitory 这个bean 拿到所有注册的job 了。

咱们再回来看@EnableBatchProcessing 这个annotation,当没有设定modular 的时候是比较简单的,只是实现了一个proxy based 的Job的bean。

同样也只有BatchConfigurer 来配置。 这个逻辑和Modular 是一样的。从这两个配置知道, Modular 注册了在子context的配置,并且加载。 但是当以正常bean 的方式存在的,是怎么读进来的呢。这时候就要看 JobRegistryBeanPostProcessor

这个 tProcessAfterInitialization 方法里, 对每个job 类型的bean, jobRegistry 加入了ReferenceJobFactory。 这样所有的以bean 的方式定义的都可以通过jobRegistry获得。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至836084111@qq.com 举报,一经查实,本站将立刻删除。

联系我们

工作日:9:30-18:30,节假日休息