打包后-JAR包名为时间戳orSNAPSHOT

一、现象

通过maven-assembly-plugin插件打包,发现lib里有的Jar包格式为artifact-demo-1.0.SNAPSHOT.jar,而有的格式为artifact-demo-1.0.20211123.202203-4.jar

有个明显的现象是执行mvn clean package命令时,所编译的module后缀皆为SNAPSHOT。

阅读更多

slf4j加载实现

一、源码

1、入口

1
2
3
4
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Logger logger = LoggerFactory.getLogger(Demo.class);
阅读更多

Maven生命周期和插件MOJO

一、插件命名

You will typically name your plugin <yourplugin>-maven-plugin.

Calling it maven-<yourplugin>-plugin (note “Maven” is at the beginning of the plugin name) is strongly discouraged since it’s a reserved naming pattern for official Apache Maven plugins maintained by the Apache Maven team with groupId org.apache.maven.plugins. Using this naming pattern is an infringement of the Apache Maven Trademark.

阅读更多

Maven常用命令

常用命令

1)只处理当前Pom,不递归处理子module

-N –non-recursive Do not recurse into sub-projects

阅读更多

HttpClient(一)连接池

一、代码示例

1)引入httpclient依赖

1
2
3
4
5
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
阅读更多

扩展接口SmartInitializingSingleton

一、调用时机

1)AbstractApplicationContext#refresh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();

// Initialize message source for this context.
initMessageSource();

// Initialize event multicaster for this context.
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
onRefresh();

// Check for listener beans and register them.
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
// 此处进行Bean实例化
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
finishRefresh();
}
}
}
阅读更多

Springboot配置文件读取顺序

一、配置读取时机

1)SpringApplication#run

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

// 此处加载配置,准备配置环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}

try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
阅读更多

ServiceLoader

一、Java SPI使用

1
2
3
4
5
6
ServiceLoader<MySpiInterface> load = ServiceLoader.load(MySpiInterface.class);
Iterator<MySpiInterface> iterator = load.iterator();
while (iterator.hasNext()) {
MySpiInterface obj = iterator.next();
obj.doSomethind();
}
阅读更多

关于Dubbo的重试机制

一、重试机制

Dubbo消费端的ClusterInvoker中,只有当异常是业务的RPC异常(isBiz() == true)时不会重试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
List<Invoker<T>> copyInvokers = invokers;
checkInvokers(copyInvokers, invocation);
String methodName = RpcUtils.getMethodName(invocation);
int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
if (len <= 0) {
len = 1;
}
// retry loop.
RpcException le = null; // last exception.
List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers.
Set<String> providers = new HashSet<String>(len);
for (int i = 0; i < len; i++) {
//Reselect before retry to avoid a change of candidate `invokers`.
//NOTE: if `invokers` changed, then `invoked` also lose accuracy.
if (i > 0) {
checkWhetherDestroyed();
copyInvokers = list(invocation);
// check again
checkInvokers(copyInvokers, invocation);
}
Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked);
invoked.add(invoker);
RpcContext.getContext().setInvokers((List) invoked);
try {
Result result = invoker.invoke(invocation);
return result;
} catch (RpcException e) {
// 只有业务异常不会重试
if (e.isBiz()) { // biz exception.
throw e;
}
le = e;
} catch (Throwable e) {
le = new RpcException(e.getMessage(), e);
} finally {
providers.add(invoker.getUrl().getAddress());
}
}
throw new RpcException(le.getCode(), "Failed to invoke");
}
}
阅读更多

使用hsdb查看运行时类

1)可选,为方便起见先创建一个JAVA_HOME的软连接

ln -s /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home jdk8

2)启动hsdb

阅读更多

RPC服务线程池大小及集群规模评估

写在前面的话

一个RPC服务在发布时不可避免的要设置其线程池大小,而我们往往却只根据经验来设置,需知不同场景不同业务下其需要配置不同的值方能使系统更稳定。以下内容是我认为应该去考虑的因素和具体的一些步骤,留待慢慢验证。

一、评估单机最佳线程数

阅读更多

Dubbo扩展点

一、Dubbo扩展点

1、Dubbo扩展点来源

Dubbo 的扩展点加载从 JDK 标准的 SPI (Service Provider Interface) 扩展点发现机制加强而来。

阅读更多

Dubbo速览

Dubbo现在是业内广泛使用的RPC框架,通过速览其架构,概念和涉及的技术,我们可以快速理解和掌握RPC的使用及原理。

一、Dubbo架构

Dubbo涉及以下几个交互组件:

阅读更多