系列文章目录

建立大型分布式服务(十九)面试官:你做过Spring结构功用拓宽吗?


@TOC


前言

群里有个小伙伴反应说,前段时间去面试被面试官问到:你做过spring结构的哪些功用上的拓宽呢?他说当时心里瞬间就凉了一截,满脑子显现的是IOC和AOP,接口和抽象类的差异spring拓宽实在想不起来是啥。为什么面试官都喜爱问spring拓优先级行列展?为什么咱们背过spring容器初始化流程仍是答复不出来呢?其实这儿主接口是什么要查询提名人对spring结构的把握程度,假设你能熟练运用spring的拓宽点,也就直接证明了你对I接口文档OC、AOPappointment了解仍是比较好的。


Spring结构的强健很大程测验纸怎么看是否怀孕度得益于它供应了完备的拓宽点面试毛遂自荐3分钟通用,网上对拓宽点的介绍材料现已接口和抽象类的差异很详细,这儿简略解释为在环境(优先级越小越优先吗Environment)、容器(ApplicationContext)、类元数据(Meta)、实例(Bean)的初始化或实例化前、中、后添加一些自定义的操作,改动或许增强结构原优先级调度算法有的逻辑。常见的优先级是什么意思拓宽方法有结束xxxInitia面试毛遂自荐lizer、xxxProcessor面试毛遂自荐、xxxAware接口,如前期xml方法整合dubbo,还有注解或许依据SPI接口文档的META-INF/spring.factories,如s测验网速pringboot的starter。

为了加深小伙伴们的了解,apple咱们假定一个业务场景:咱们需要在application.pr接口和抽象类的差异operties/application.yml优先级越小越优先吗 中自定义装备变量来获app装置下载取ipapproach,用来生成不同的日志文件称谓。其间random是spr优先级行列ingboot内优先级最高的运算符置的,myVar是咱们拓宽的。

my.log.prefix=monitor_${myVar.ip}
#approachmy.log.prefix=mopnitor_${myVar.yyyyMMddHHmmss}
#my.log.prefix=appreciatemonitor _${random.int(10)}

一、本文要害

接前文,咱们整合了Apollo,并把装备文件放在Apollo远程服务器中托管了,仔细的你肯定发现了面试技巧,Apollo面试毛遂自荐一分钟把远端装备注入springboot容器上下文何曾不就是一种Environment拓宽呢?本文咱们将模仿springboot内置random变量的处理面试毛遂自荐逻辑,结束咱们自定义装备变量的拓宽。系列文章完好目录

  • springboot 拓宽
  • springboot 自定义装备变量
  • springboot application装备文件获取服务IP
  • springboot application装备文件获取当时时间 + 格式化
  • EnvironmentPostProcessor 外置装备
  • logback 读取springboot装备

二、开发环境

  • jdk 1.8
  • maven 3.6.2
  • springboot 2.4.3
  • idea 2020

三、项目改造

1、在resources目录添加 META-INF/spring.接口是什么factories 文件,使spring结构能感知到新增的SPI,装备如下:

org.springframework.boot.env.EnvironmentPostProcessor=
com.mmc.lesson.e优先级反转nvdemo.support.MyValuePropertySourceEnvironme面试毛遂自荐简略大方ntPostProcessorappreciate

2、编写MyValuePropertyS接口的效果ourceEnappstorevironmentPostProcessor.java ,结束EnvironmentPo面试毛遂自荐一分钟stProcessor 、Order 接口,这样可以更高优先级在spring容器refresh前先结束我apple们自定义的装备的注入。

public class MyValuePropertySourceEnvironmentPostProcessor i优先级最高的运算符mplemenapplets Env接口是什么i测验纸怎么看是否怀孕ronmentPostProcessor, Orderapproached {
privatappstoree Log loggeappler;
/**
* empty.
*/
public MyValuePropertySourceEnvironmentPostPr优先级调度算法ocessor() {
logger = LogFactory.getLog(MyValuePropertySourceEnvironmen面试毛遂自荐简略大方tPostProcessor.cla面试常见问题及答复技巧ss);
}
/**
* init。
*/
public MyV优先级越小越优先吗aluePropertySourceEnvironmentPostProcessor(Log logger) {
this.logger = logger;
}
@Override
public void postProce测验你的自卑程度ssEnvi测验ronment(ConfigurableEappearancenvironment environmentapp装置下载, Spri接口ngApplication applicAPPation) {
MyValuePropertySource.addToEnvironmenappreciatet(environment, this.logger);
}
@Override
public inapplicationt getOrder() {
return Order接口测验ed.HIGHEST_PRECEDENC接口测验E + 2;
}
}

3、编写 MyValuePropertySource.java ,定义咱们在application.yml / application.properties 的变量前缀 ${myVar} 。

public class MyValuePropertySource extends PropertySource&ltapplication;MyLogV优先级反转alue> {
/**
* Name of the random {@link Pr测验手机是否被监控opertySource}.
*/
public static final String接口测验 MY_PRO面试毛遂自荐3分钟通用PERTY_SOURCE_NAMappstoreE = "myVar";
private static fi面试技巧nal String PREFIX = "myVar.";
private static final Log logger = LogFactory.getLog(MyValuePropertySource.class);
/**
* MyValuePr测验抑郁症的20道题opertySource.
*/
public MyValuePropertySource() {
this(MY_PROPERTY_SOURCE_NAME);
}
/**
* MyValuePropertySource.
*/
public MyValuePr面试毛遂自荐简略大方opertySource(String name) {
super(name, new MyLogValue());
}
/**
* 添加自定义表达式面试毛遂自荐简略大方到环境上下文.
*/
public static void addToEnvironment(ConfigurableEnvironment environment, Log logger) {
MutablePropertySources sources = environm面试技巧ent.getPropertySources();
PropertySource<?> existing = sources测验蛙.get(MY_PROPERTY_SOURCE_NAME);
if (existing != null) {
logger.traceappreciate("RandomValueProper面试问题tySource alrea面试问题dy present");
return;
}
MyValuePropertySource rando测验工程师mSource = new MyValuePropertySource(MY_P测验ROPERTY_SOURCE_NAME);
if (sources.get(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_接口是什么SOURCE_NAME) != null) {
sources.addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, randomSource);测验工程师
} else {
sources.addLast(randomSource);
}
logger.trace("MyValuePropertySource add to Enviro测验蛙nment");
}
@Override
public Object getProperty(String name) {
if (!name.startsWith(PREFIX)) {
return null;
}
logge优先级和劣后级的差异r优先级.trace(Lo面试问题gMessage测验蛙.format("Generating property for '%s'", name));
return getValue(n接口的效果ame.substring(PREFIX.len优先级gth()));
}
/**
* 现在仅支优先级排名是什么意思持ip.
*/
private Object getValue(String type) {
i面试技巧f (type.测验equalsIgnoreCase("ip"优先级反转)) {
return getSource().getIp();
}
return null;
}
}

4、编写MyLogValue.jav优先级a ,结束 ${myVar.ip} 的取值逻辑。

@Data
public c优先级排名是什么意思lass MyappleLogValue {
/**
* 获取本机Ip.
*/
p面试毛遂自荐一分钟ublic String getIp() {
return I接口和抽象类的差异pUtil.getLocalIP();
}
}
clappleass IpUtil {
/**
* 获取本机IP,只回来一个.
*/
static String getLocalIP() {
String sIP = "";
InetAddress ip = null;
try {
// 假设是Windows操作体系
if (isWindowsOS()) {
ip = In接口测验etAddress.getLocalHost();
// 假设是Linux操作体系
} else {
boolean bapproveFindIP = false;
Enumeration<NetworkInterface> netInt面试毛遂自荐简略大方erfaces = NetworapproachkInterface.getNetworkInterfaces();
while (netInterfaces.hasMoreElements())面试 {
if (bFindIP) {
break;
}
NetworkInterfaappointmentce ni = netInterfaces.nextElement();
if (ni.isL接口oopback() || napplei.isVirtual() || !ni.isUp()) {
continue;
}
// ----------特定状况,可以考虑用ni.getName判别
// 遍历一切ip
Enumeration<InetAddress> ips = ni.getInetAddresses();
while (ips.hasMoreElements()) {
ip = ips.nextElement();
if (ip.isSiteLocalAddress() &&amp面试毛遂自荐范文; !ip.isLoopbackAddress() // 127.最初的都是lookback地址
&& !ip.getHos接口类型tAddress().contains(":")) {
bFindIP = true;
break;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (null != ip) {
sIP = ip.测验网速getH接口crc过错计数ostAddress();
}
return sIP;
}
/**
* 判别是否为Windows体系.
*/
private static boolean isWappstoreindowsOS() {
boolean面试毛遂自荐简略大方 isWindowsOAPPS = false;
Strin面试技巧g osName = System.getProperty("os.name");
if (osName.toLowerCase().contains("windows")) {
isWiappointmentndowsOS = tr接口卡ue;
}
return isWindowsOS;
}
}

四、工作一下

1、批改 logback-spring.xml 装备。

    <springProperty scope="context" name="log.path" source="appstorelogging.file.path"/>
<springProperty scope="context" name="monitor.file.prefix" so面试技巧和注意事项urce="my.log.prefix"application/>
<appender name="MONITOR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppende面试毛遂自荐简略大方r">
<!-- 正在记载的日志文件的途径及文件名 -->
<fi测验工程师le>${log.path}/appear${monitor.file.prefix}.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>[%d{yyyy接口英文-MM-dd HH:mm:ss.SSS}] [%thre测验抑郁症的20道题ad] [%level] [%logger{50}:%L] - %msg%n
</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记approve载器的滚动战略,按日期,按巨细记载 -->
<rollingPolicy clas接口和抽象类的差异s="ch.qos.logback.coappearre.rolling.TimeBasedRollingPoli测验手机是否被监控cy">
<!-- 每天日志接口和抽象类的差异归档途径以及格式appearance -->
<fileNamePattern>${log.path}/monitor/monitor-%d{yyyy-MM-dd}.%i.zip</fileNamePattern>
<timeBasedFileNamingAndTrigg优先级eringPolicy
class="ch.qos.logbac测验手机是否被监控k.面试技巧和注意事项core.rolling.Si优先级调度算法zeAndTime面试毛遂自荐简略大方BasedFN接口类型ATP">
<maxFileS优先级ize>500MB</maxFileSize>
</timeBas接口测验edFileNamingAndTriggeringPolicy>
<!--日志文件保存天数-->
<maxHisto接口的效果ry>7<接口crc过错计数/maxHistory>
&lt测验怀孕的试纸图片一深一浅;totalSizeCap&g接口和抽象类的差异t;7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingappointmentPolicy>
</appende面试毛遂自荐一分钟r>

2、关键来了测验抑郁程度的问卷,批改application.properties,添加咱们自定义的变量myVar.ip

# 日志途径
logg面试常见问题及答复技巧ing.file.path=./logs
# 日志称谓前缀
my.log优先级行列.pr接口是什么efix=monitor_${myVar.ip}

3、编写测验用例。

@SpringBootTest
class EnvDemo面试技巧ApplicationTests {
@Value("${my.log.appstoreprefix}")
private String prefix;
@Test
void contextLoads() {
System.out.println("-------------接口crc过错计数---面试毛遂自荐范文------------测验怀孕的试纸图片一深一浅-");
S优先级英文ystem.out.面试毛遂自荐println(prefix);测验蛙
}
}

4、工作一下面试问题,和预期一同!可以正常获测验手机是否被监控取myVar.ip 的值。
建立大型分布式服务(十九)面试官:你做过Spring结构功用拓宽吗?

五、小结

至此,咱们就简略结束了拓宽spring结构的功用啦。课后作业,小伙伴可以自行去结束前文说到的 ${myVar.time.yyyyMMdd} 变量哦,有爱好的小伙伴还可以学习下Apollo注入远程装备的原理。下一篇《建立大型分布式服务(二十)Springboot 拓宽-定制日志组件》

加我一同交流学习!
建立大型分布式服务(十九)面试官:你做过Spring结构功用拓宽吗?