小不的笔记

时间之外的往事

Java多线程并发操作ArrayList

给公司一个业务系统做性能优化时,有个地方需要在循环内实现对外交互。有网络IO的地方很容易出现性能瓶颈,就打算通过parallelStream实现并发操作,

1
2
3
4
5
6
List resultList = new ArrayList();
xxxList.forEach(item -> {
result = doSomethingWithRemoteServer()
resultList.add(result)
});
return resultList;

如果直接把forEach改为parallelStream().forEach,就会引发新的问题,因为业务代码里使用了 arraylist.add 方法收集计算结果,ArrayList 是非线程安全的使用一个线程安全的容器。 Java里线程安全的集合容器,可以通过如下方法: Vector * 古老且线程安全的List, 每次扩容一倍空间,而ArrayList扩容50%。 * 在这个场景下因为集合需要返回上层做额外操作,如果使用Vector会有不必要的锁开销,当然这点儿性能影响可以忽略不计,如果不想有额外的锁开销就需要在返回时多了一层转换,把Vector转化为ArrayList。 CopyOnWriteArrayList * 每次添加新元素时创建一个新的List,适合读多写少的场景。该场景基本没并发读的场景,完全没必要使用。 Collections.synchronizedList * 返回一个包装类SynchronizedList,对被包装的真实List的所有场景加锁。 其他 * 因为我这里这个场景比较简单也可以使用ConcurrentHashMap等集合容器来实现线程安全。 我现在的这个场景挺适合Collections.synchronizedList

1
2
3
4
5
6
7
8
9
List resultList = new ArrayList();
List syncResultList = Collections.synchronizedList(resultList)

List resultList = new ArrayList();
xxxList.parallelStream().forEach(item -> {
result = doSomethingWithRemoteServer()
syncResultList.add(result)
});
return resultList;

全部改完之后,又想到我只用到了 arraylist.add 其实只需要同步这一方法就行了。

1
2
3
4
5
6
7
8
List resultList = new ArrayList();
xxxList.parallelStream().forEach(item -> {
result = doSomethingWithRemoteServer()
synchronized(resultList){
resultList.add(result)
}
});
return resultList;

这样没有一句废话的实现了多线程环境下,给ArrayList下添加元素。如果还在学生时代,估计我会直接写出最后这种代码,但是随着工作时间久了,习惯于使用各种工具包来实现各种功能,渐渐的忘记最初的样子, 习惯于把简单的问题复杂化。 Keep it simple and stupid.

Ubuntu切换国内镜像(通用版)

镜像模式

使用镜像模式,apt 命令会自动根据选择服务器所在的国家的镜像。如下脚本默认源使用镜像协议并备份原始文件sources.list到sources.list.backup`

1
sudo sed -E -i.backup 's#^(debdeb-src) ([^ ]*) (.*)#\1 mirror://mirrors.ubuntu.com/mirrors.txt \3#' /etc/apt/sources.list

手动模式

我的服务器阿里云机房,所以希望固定使用阿里云镜像。如下脚本修改默认源为阿里云并备份原始文件sources.listsources.list.backup

1
sudo sed -E -i.backup 's#^(debdeb-src) ([^ ]*) (.*)#\1 https://mirrors.aliyun.com/ubuntu \3#' sources.list

国内常用镜像源

根据自己需要,选择自己最快的源。

名称

地址

阿里镜像源

https://mirrors.aliyun.com/ubuntu

清华大学镜像源

https://mirrors.tuna.tsinghua.edu.cn/ubuntu/

网易镜像源

https://mirrors.163.com/ubuntu/

查看更多的镜像

1
wget -qO - mirrors.ubuntu.com/mirrors.txt

我这里返回值是

http://mirrors.aliyun.com/ubuntu/ https://mirrors.hit.edu.cn/ubuntu/ http://mirrors.huaweicloud.com/repository/ubuntu/ http://mirrors.sohu.com/ubuntu/ http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ http://linux.xjtuns.cn/ubuntu/ http://mirrors.cqu.edu.cn/ubuntu/ https://mirror.bjtu.edu.cn/ubuntu/ http://mirrors.nju.edu.cn/ubuntu/ http://mirrors.ustc.edu.cn/ubuntu/ http://mirrors.yun-idc.com/ubuntu/ https://mirrors.bfsu.edu.cn/ubuntu/ http://mirror.lzu.edu.cn/ubuntu/ http://mirrors.dgut.edu.cn/ubuntu/ http://ftp.sjtu.edu.cn/ubuntu/ http://mirrors.njupt.edu.cn/ubuntu/ http://archive.ubuntu.com/ubuntu/

解决邮箱关闭导致的邮件无法发送问题 550 5.1.1 recipient is not exist javax.mail

业务方反馈系统的定时邮件没有收到。排查日志后发现,是人员离职后,其工作邮箱关闭,与其相关的业务系统的定时邮件通知的收件人列表内没有移除其邮箱,会导致邮件通知发送失败报”550 5.1.1 recipient is not exist”异常,导致整个邮件通知都没办法发出。 经过查阅文档发现可以设置允许发送部分邮件。可以通过设置属性mail.smtp.sendpartial或者通过SMTPMessagesendPartial属性来实现。

方案一 mail.smtp.sendpartial

设置构造属性mail.smtp.sendpartial

1
2
3
4
5
6
7
8
9
10
Properties prop = new Properties();
prop.put("mail.smtp.sendpartial", "true");
// ... prop.put(xxx, xxx);

Session session = Session.getInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});

方案二 SMTPMessage

SMTPMessage有sendPartial属性。把默认的mimeMessage使用SMTPMessage包装一下,然后设置 sendPartial 属性为true。

1
2
3
4
Message message = new MimeMessage(session);
// ... message.set(xxx,xxx);
SMTPMessage smtpMessage = new SMTPMessage(message);
smtpMessage.setSendPartial(true);

即使开启了sendPartial属性,如果遇到有无效收件人时,依旧会抛出一个SMTPSendFailedException异常。需要处理一下这个异常,根据STMP的定义返回码在2xx的时候都可以认为是成功,所以返回码不为2xx时,把异常再次抛出, 同时在异常内可以通过e.getInvalidAddresses()获取无效的邮件地址,做进一步处理。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Send message
try {
Transport.send(smtpMessage);
System.out.println("Sent message successfully....");
} catch (SMTPSendFailedException e) {
if (e.getReturnCode() >= 200 && e.getReturnCode() < 300) {
Address[] addresses = e.getInvalidAddresses();
for (Address address : addresses) {
doSth(address);
}
} else {
throw e;
}
} catch (MessagingException mex) {
mex.printStackTrace();
}

cron使用示例

后台自动运行维护任务对Linux系统管理员是非常重要的。Linux Cron工具是一个有效的方式去安排后台定时任务。

Linux Crontab格式

1
MIN HOUR DOM MON DOW CMD

字段

描述

MIN

分钟

0 to 59

HOUR

小时

0 to 23

DOM

1-31

MON

1-12

DOW

0-6

CMD

命令

要执行的命令

指定时间执行任务

cron的最基本用法就是如下所示的在指定时间运行任务。这将在6月10上午8点30执行完整备份的脚本。 请注意时间字段使用24小时制。因此早上8点就是8,晚上8点是20. 30 08 10 06 * /home/ramesh/full-backup 30 – 30分 08 – 上午8点 10 – 10号 06 – 6月 * – 周的每天

指定任务执行多次(比如一天执行两次)

如下的脚本每天两次的执行一个增量的备份 这个示例每天11:00和16:00执行指定的增量备份脚本。如果某个时间段需要执行多个,那么使用逗号分割,那么每个时间都会执行。 00 11,16 * * * /home/ramesh/bin/incremental-backup 00 – 0分 11,16 – 11:00和16:00 * – 每天 * – 每月 * – 周的每天

指定任务在某个时间区域执行

如果你希望任务在指定的时间段每小时执行一次可以使用下面的配置。

每天的工作时间

这个例子在每天(包括周六周日)的早上9点到下午6点检查数据库状态。 00 09-18 * * * /home/ramesh/bin/check-db-status 00 – 0分 09-18 – 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 * – 每天 * – 每月 * – 周的每天

工作日的工作时间

这个例子在每天(不包括周六周日)的早上9点到下午6点检查数据库状态。 00 09-18 * * 1-5 /home/ramesh/bin/check-db-status 00 – 0分 09-18 – 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 * – 每天 * – 每月 1-5 – 周一到周五

如何查看 crontab 条目

查看当前登录用户的 crontab 条目

使用 crontab -l 去查看当前账号的 crontab 条目

查看其它用户的 crontab 条目

要查看其它用户的 crontab 条目,需要有 root 权限然后使用 -u {username} -l

如何编辑 Crontab 条目

编辑当前用户的 crontab 条目

使用 crontab -e 去编辑 crontab 条目,默认情况下会编辑当前登录用户的 crontab.

1
2
3
4
5
6
7
8
ramesh@dev-db$ crontab -e
@yearly /home/ramesh/centos/bin/annual-maintenance
*/10 * * * * /home/ramesh/debian/bin/check-disk-space
~
"/tmp/crontab.XXXXyjWkHw" 2L, 83C

[Note: This will open the crontab file in Vim editor for editing.
Please note cron created a temporary /tmp/crontab.XX... ]

当你使用:wq保存上面的临时文件后,它会保存 crontab 并显示下面的信息表明 crontab 已经成功地修改了。

1
2
3
~
"crontab.XXXXyjWkHw" 2L, 83C written
crontab: installing new crontab

修改 root 用户的Crontab 条目

先使用 root 用户登录(su - root) 然后再使用 crontab -e 去编辑.

1
root@dev-db# crontab -e

修改其它用户的 Crontab 条目

要修改其它用户的 crontab 条目,需要有 root 权限然后使用 -u {username} -l

1
2
3
4
5
6
7
root@dev-db# crontab -u sathiya -e
@monthly /home/sathiya/fedora/bin/monthly-backup
00 09-18 * * * /home/sathiya/ubuntu/bin/check-db-status
~
~
~
"/tmp/crontab.XXXXyjWkHw" 2L, 83C

每分钟执行一次任务

正常情况下,你可能不需要一个每分钟都执行一次的任务。但是理解这个例子将会帮助你理解后面的例子。

1
* * * * * CMD

星号 * 表示所有有可能的值,每一分钟、每一小时、每一天。除了直接使用星号,你还可以使用以下非常有用的场景: 当你在分钟字段指定 */5 意味着每5分钟 当你在分钟字段指定 0-10/2 意味着在前10分钟里,每两分钟 以上两种写法,在其它字段也是适用的。

每10分钟执行一次任务

如果你想每10分钟检查一次硬盘空间状态,可以使用下面的配置 ```*/10 * * * * /home/ramesh/check-disk-space``` 除了配置这五个字段,我们也可以指定一个关键字。 有几个特殊的场景来替代这五个字段,你可以使用@+关键字例如 reboot,midnight, yearly, hourly. 关键字清单

关键字

等同于

@yearly

0 0 1 1 *

@daily

0 0 * * *

@hourly

0 * * * *

@reboot

开机后执行

使用 @year 在每年开始的时候执行任务

如果你希望一个任务在每年开始的时候执行,那么你就可以使用 @year 关键字。 这个将会执行系统年检通过年检脚本在每年的1月1号00:00. ```@yearly /home/ramesh/red-hat/bin/annual-maintenance```

使用 @monthly 在每月开始的时候执行任务

如果你希望一个任务在每月开始的时候执行,那么你就可以使用 @monthly 关键字。 这个将会在每月的1号00:00执行备份脚本.

1
@monthly /home/ramesh/suse/bin/tape-backup

使用 @daily 在每天开始的时候执行任务

如果你希望一个任务在每天开始的时候执行,那么你就可以使用 @daily关键字。 这个将会在每月的1号00:00执行清理日志脚本. ```@daily /home/ramesh/arch-linux/bin/cleanup-logs “day started”


### 使用 @reboot 在每次重启后执行任务 如果你希望一个任务在每次重启后执行,那么你就可以使用 @reboot 关键字。 这个将会在每次服务器重启后执行. ```@reboot CMD

如何通过MAILTO关键字禁用或重定向Crontab的邮件输出

默认情况下crontab会把任务的输出给配置定时任务的用户. 如果你希望重定向输出给一个指定的用户,只需要在crontab里添加或者修改 MAILTO 变量就可以了。

1
2
3
4
5
6
7
ramesh@dev-db$ crontab -l
MAILTO="ramesh"

@yearly /home/ramesh/annual-maintenance
*/10 * * * * /home/ramesh/check-disk-space

[Note: Crontab of the current logged in user with MAIL variable]

如果你不希望发送邮件,把这个变量置空就可以了.

1
MAILTO=""

如何每秒执行一次任务

你不能设置每秒执行的任务。 因为 cron 的可以配置的最小单位是分钟。在正常的业务场景下,也没有理由在系统里设置每秒都执行的任务。

在Crontab里设置PATH变量

上面所有的例子里我们都是指定了Linux命令或脚本的绝对路径。 如果你希望使用相对路径,那么就需要把在crontab 里把程序所在文件夹路径添加到PATH变量里。

1
2
3
4
5
6
7
8
ramesh@dev-db$ crontab -l

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/home/ramesh

@yearly annual-maintenance
*/10 * * * * check-disk-space

[Note: Crontab of the current logged in user with PATH variable]

从一个Cron文件里安装Crontab

除了直接编辑crontab 文件, 你也可以创建一个cron文件然后在里面添加需要的条目, 然后再把这个文件安装进 crontab。

1
2
3
4
5
6
7
8
9
10
11
12
ramesh@dev-db$ crontab -l
no crontab for ramesh

$ cat cron-file.txt
@yearly /home/ramesh/annual-maintenance
*/10 * * * * /home/ramesh/check-disk-space

ramesh@dev-db$ crontab cron-file.txt

ramesh@dev-db$ crontab -l
@yearly /home/ramesh/annual-maintenance
*/10 * * * * /home/ramesh/check-disk-space

安装cron-file.txt时,也会移除所有的旧cron条目, 所以在安装cron文件时,要特别小心。

每个月最后一天执行

cron原生不支持每个月的最后一天执行,但是可以通过判断明天是不是1号,来决定今天是不是这个月的最后一天。

1
55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh

每个月最后一个工作日执行

cron 法定节假日,每年会都变化,每个月的最后一个工作日也会不一样,需要能够动态的更新法定节假日。考虑到一年只有12个月也就是12个工作日期,我把每月工作日写入 lastworkingday.txt 然后对比当天是不是在这个文件内,如果在就执行。同时把 lastworkingday.txt 文件上传到 github 定期去摘取这个文件。如果法定节假日发生变化,我只需要提交对 lastworkingday.txt的修改就好了。

1
2
3
00 00 * * * git -C /opt/mycrontabdb pull
00 12 20-31 * * grep $(date +%F)
/opt/mycrontabdb/lastworkingday.txt && myjob.sh

lastworkingday.txt sample

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
20201030
20201130
20201231
20210129
20210226
20210331
20210430
20210531
20210630
20210730
20210831
20210930
20211029
20211130
20211231

NodeJS 镜像配置 npm yarn 淘宝镜像

下载npm包经常下载不下来,还好淘宝提供了npm的镜像站,配置好之后,再使用npm或yarn就可以通过淘宝镜像站下载npm包,不用使用cnpm。

配置镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
npm config set registry https://registry.npm.taobao.org/
npm config set disturl https://npm.taobao.org/dist
npm config set electron_mirror https://npm.taobao.org/mirrors/electron/
npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
npm config set phantomjs_cdnurl https://npm.taobao.org/mirrors/phantomjs/
npm config set chromedriver_cdnurl https://cdn.npm.taobao.org/dist/chromedriver/
npm config set operadriver_cdnurl https://cdn.npm.taobao.org/dist/operadriver
npm config set fse_binary_host_mirror https://npm.taobao.org/mirrors/fsevents

yarn config set registry https://registry.npm.taobao.org -g
yarn config set disturl https://npm.taobao.org/dist -g
yarn config set electron_mirror https://npm.taobao.org/mirrors/electron/ -g
yarn config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/ -g
yarn config set phantomjs_cdnurl https://npm.taobao.org/mirrors/phantomjs/ -g
yarn config set chromedriver_cdnurl https://cdn.npm.taobao.org/dist/chromedriver -g
yarn config set operadriver_cdnurl https://cdn.npm.taobao.org/dist/operadriver -g
yarn config set fse_binary_host_mirror https://npm.taobao.org/mirrors/fsevents -g

在线更新 dorado 规则RequestRejectedException

使用在线更新 dorado 规则时,项目报错org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL contained a potentially malicious String "//". 这个是由Spring Security 5提供的一个HTTP防火墙,拦截可疑访问导致的。在项目中注册如下的bean,即可替换系统默认的防火墙。该实现没有任何防范作用,建议仅仅再更新Dorado规则时临时打开,一定不能发布到生产环境。

1
2
3
4
5
6
@Bean
public HttpFirewall looseHttpFirewall() {
StrictHttpFirewall firewall = new StrictHttpFirewall();
firewall.getEncodedUrlBlacklist().clear();
return firewall;
}

node-sass Error: EACCES: permission denied, mkdir 'xxx/node_modules/node-sass/vendor'

Unable to save binary //node_modules/node-sass/vendor/linux-x64-64 : { Error: EACCES: permission denied, mkdir ‘xxx/node_modules/node-sass/vendor’ at Object.mkdirSync (fs.js:752:3) 使用npm打包时,发现node-sass无法安装成功,但是用yarn可以。 原来是因为 npm 为了安全禁止使用root用户或者sudo来安装node-sass,切换到普通用户就可以了,或者添加 --unsafe-perm 参数。

1
sudo npm install --unsafe-perm -g node-sass

Running with sudo or as root

MacOS 下切换默认 Java (JDK)

TLDR

如果同时安装了 adoptopenjdk 11 和 adoptopenjdk 8,同时希望 8 做为默认 JDK,只需要把 /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Info.plist里的JVMVersion的值由1.8.0_222改为 x1.8.0_222(大概第42行)。这样我们的MacOS默认JDK就成为adoptopenjdk-8了。

查看 JDK 相关信息

macOS下 JDK 默认安装在 /Library/Java/JavaVirtualMachines目录下,同时提供了一个小工具/usr/libexec/java_home 帮助我们快速的查看 JDK 相关的信息。 默认情况下 MacOS 会自动的选择 /Library/Java/JavaVirtualMachines目录下版本号最高的 JDK 做为默认 JDK 。

查看当前 JDK 版本

1
2
3
4
➜  ~ java -version
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_222-b10)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.222-b10, mixed mode)

查看当前 JDK 的安装目录

1
2
➜  ~ /usr/libexec/java_home
/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home

查看已安装的 JDK 版本及目录

查看所有

1
2
3
4
5
➜  ~ /usr/libexec/java_home -V
Matching Java Virtual Machines (3):
1.8.0_222, x86_64: "AdoptOpenJDK 8" /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home
1.8.0_201, x86_64: "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home
1.7.0_80, x86_64: "Java SE 7" /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home

查看指定版本 可以通过/usr/libexec/java_home -v <version>来过滤版本号。 返回前缀匹配到的最新 JDK。

1
2
3
4
5
6
7
8
➜  ~  /usr/libexec/java_home -v 1
/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home
➜ ~ /usr/libexec/java_home -v 1.7
/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home
➜ ~ /usr/libexec/java_home -v 1.8.0_201
/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home
➜ ~ /usr/libexec/java_home -v 1.8
/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home

切换 JDK

使用指定的 JDK 执行单次命令

可以通过java_homeexec选项来执行单次任务。 /usr/libexec/java_home -v version –exec command

1
2
3
4
➜  ~ /usr/libexec/java_home -v 1.7 --exec java -version
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)

切换 Shell 的 JDK到指定版本

Shell 环境只需要指定一下JAVA_HOME环境变量就可以。

1
2
3
4
5
➜  ~ export JAVA_HOME=`/usr/libexec/java_home -v 1.7`
➜ ~ java -version
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)

为了方便切换把以下别名配置粘到对应的 Shell 的配置文件 .bashrc 或 .zshrc,然后就可以方便的切换 JDK 版本了。 别名配置 需要根据自己实际已安装 JDK 做增减。

1
2
3
4
5
6
alias j12="export JAVA_HOME=`/usr/libexec/java_home -v 12`; java -version"
alias j11="export JAVA_HOME=`/usr/libexec/java_home -v 11`; java -version"
alias j10="export JAVA_HOME=`/usr/libexec/java_home -v 10`; java -version"
alias j9="export JAVA_HOME=`/usr/libexec/java_home -v 9`; java -version"
alias j8="export JAVA_HOME=`/usr/libexec/java_home -v 1.8`; java -version"
alias j7="export JAVA_HOME=`/usr/libexec/java_home -v 1.7`; java -version"

使用效果

1
2
3
4
5
6
7
8
9
10
11
12
➜  ~ j7
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)
➜ ~ j8
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
➜ ~ j11
openjdk version "11.0.4" 2019-07-16
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.4+11)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.4+11, mixed mode)

切换 GUI 程序的默认 JDK

GUI 程序使用的默认 Java 也是 /usr/libexec/java_home -V 中看到的最高版本。

指定全局环境变量

创建setenv.javahome.plist并通过launchctl指定设置环境变量JAVA_HOME,需要注销再登录才生效。而且有些程序不兼容该方式。使用该方式之后,/usr/libexec/java_home的显示跟实际执行也会出现不一致。 生成 setenv.javahome.plist 并加载的脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cat > ~/Library/LaunchAgents/setenv.javahome.plist <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>setenv.javahome</string>
<key>ProgramArguments</key>
<array>
<string>/bin/launchctl</string>
<string>setenv</string>
<string>JAVA_HOME</string>
<string>/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>ServiceIPC</key>
<false/>
</dict>
</plist>
EOF
launchctl load ~/Library/LaunchAgents/setenv.javahome.plist
修改 JDK 版本号

我们还可以通过修改版本号实现指定版本的JDK做为默认JDK, 我目前正在使用该方式。 /usr/libexec/java_home是通过/Library/Java/JavaVirtualMachines/<JDK>/Contents/Info.plist里的JVMVersion值来获取版本号的,所以只需要修改这个值为当前最大版本号即可实现指定默认 JDK。经过测试这个还是即时生效。 像我安装过adoptopenjdk 11 ,但还是希望 adoptopenjdk 8做为默认 JDK,只需要把 /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Info.plist里的JVMVersion的值由1.8.0_222改为 x1.8.0_222(大概第42行)。这样我们的adoptopenjdk-8.jdk就变成最新版本的 JDK 了。

排序是通过 ASCII 值来排的,版本号只要改的比最新的 11 大都行,字符’x’的ASCII值远大于字符’1’, 为了方便版本区分我只加了一个字符 x

修改完成之后再查看 JDK 信息,就会发现我们修改的x1.8.0_222会排到第一位,同时 Java version 是 1.8。

1
2
3
4
5
6
7
8
9
10
11
12
13
➜  ~ /usr/libexec/java_home -V
Matching Java Virtual Machines (4):
x1.8.0_222, x86_64: "AdoptOpenJDK 8" /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home
11.0.4, x86_64: "AdoptOpenJDK 11" /Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home
1.8.0_201, x86_64: "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home
1.7.0_80, x86_64: "Java SE 7" /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home

➜ ~ java -version
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_222-b10)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.222-b10, mixed mode)

操作流程: 备份原始文件并打开,并使用 vim 编辑.

1
2
sudo cp /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Info.plist /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Info.plist.bak
sudo vim /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Info.plist

修改后的Info.plist文件差异

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
➜  ~ diff -c  /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Info.plist /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Info.plist.bak
*** /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Info.plist 2019-10-27 14:01:10.000000000 +0800
--- /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Info.plist.bak 2019-10-27 14:17:36.000000000 +0800
***************
*** 39,45 ****
<key>JVMVendor</key>
<string>AdoptOpenJDK</string>
<key>JVMVersion</key>
! <string>x1.8.0_222</string>
</dict>
</dict>
</plist>
--- 39,45 ----
<key>JVMVendor</key>
<string>AdoptOpenJDK</string>
<key>JVMVersion</key>
! <string>1.8.0_222</string>
</dict>
</dict>
</plist>

macOS 下 java 的真身

通过简单的探索,就能发现我们使用的 java 其实是软链到 /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java

1
2
➜  ~ greadlink -f `which java`
/System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java

greadlink 需要安装coreutils brew install coreutils

/System/Library/Frameworks/JavaVM.framework/Versions/A/Commands 目录下的文件多是固定 38k 大小。猜测这些文件应该只是包装器,根据系统配置把命令转发给相应的 JDK 的对应命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
➜  ~ ll /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands
total 1200
-rwxr-xr-x 1 root wheel 38K Sep 30 04:28 appletviewer
-rwxr-xr-x 1 root wheel 38K Sep 30 04:28 apt
-rwxr-xr-x 1 root wheel 38K Sep 30 04:28 extcheck
-rwxr-xr-x 1 root wheel 38K Sep 30 04:28 idlj
-rwxr-xr-x 1 root wheel 38K Sep 30 04:28 jar
-rwxr-xr-x 1 root wheel 38K Sep 30 04:28 jarsigner
-rwxr-xr-x 1 root wheel 38K Sep 30 04:28 java
-rwxr-xr-x 1 root wheel 47K Sep 30 04:28 java_home
-rwxr-xr-x 1 root wheel 38K Sep 30 04:28 javac
-rwxr-xr-x 1 root wheel 38K Sep 30 04:28 javadoc
...

MySQL 记录所有SQL和慢SQL

通过配置文件配置日志

my.cnf 位置

查看自己版本 MySQL 默认读取配置文件的路径

1
mysql --help  grep my.cnf

我的这个版本的 MySQL 会以以下顺序读配置文件 1. /etc/my.cnf 2. /etc/mysql/my.cnf 3. /usr/local/etc/my.cnf 4. ~/.my.cnf 如果使用了自定义位置可以通过查看进程启动参数 --defaults-file

1
ps aux  grep mysqld

日志配置

通用SQL日志 (General Query Log) 记录所有mysqld做的事,连接、断开、查询。

1
2
3
# 通用SQL日志
general_log_file = /var/log/mysql/mysql.log
general_log = 1

慢SQL日志 (Slow Query Log) 记录慢SQL long_query_time 默认10,单位秒;SQL执行时间比long_query_time长的都会被记录。

1
2
3
4
5
# 慢SQL日志
log_slow_queries = /var/log/mysql/mysql-slow.log
long_query_time = 10
log-queries-not-using-indexes = ON

在运行时开启日志

开启日志,登录 mysql client (mysql -u root -p) 然后执行:

1
2
SET GLOBAL general_log = 'ON';
SET GLOBAL slow_query_log = 'ON';

关闭日志,登录 mysql client (mysql -u root -p) 然后执行:

1
2
SET GLOBAL general_log = 'OFF';
SET GLOBAL slow_query_log = 'OFF';

即时生效,不需要重启。 查看日志文件位置

1
show variables like '%log_file';

Spring Boot接入 apollo 后启动 dubbo 报错

某Spring Boot项目接入 apollo 后启动 dubbo 报错Caused by: java.lang.IllegalStateException: ApplicationConfig.application == null.

TLDR

  1. apollo-client 版本>= 1.2.0。 点击查看Apollo Client最新版本
  2. application.properties内添加配置apollo.bootstrap.eagerLoad.enabled=true

解决步骤复盘

根据异常猜测是 dubbo 启动时未读取到 apollo 内的配置。

0x01

先Google关键字 dubbo 2.6.2 apollo, 第二条 “继承dubbo配置不生效…”.

0x02

点开第二条之后发现跟我们的问题毫无关系,但是里面提到 apollo use cases.

0x03

使用 SourceTree 下载 apollo-use-cases,并在本机跑起来,发现没问题。

0x04

对比支付系统与其中的spring-boot-dubbo-consumer项目的异同。 1. dubbo 版本一致 2. dubbo-spring-boot-starter版本差 0.0.1 3. 支付系统启动类上多@EnableJpaRepositories, @EnableCaching,@EnableSwagger2。 4. 发现支付系统启动类里上还多一个@ImportResource(value = {"classpath*:commons-dubbo-api.xml"}.

0x05

在发现的异同里,跟 dubbo 关系最大的就是第四条。给spring-boot-dubbo-consumer的添加commons-dubbo-api-balcony 依赖,然后在启动类上添加注解 @ImportResource(value = {"classpath*:commons-dubbo-api.xml"}问题复现。可以肯定这个问题是 apollo 与 dubbo 的兼容性问题。

0x06

访问 appollo issues, 以 dubbo 作为关键字搜索。结果差不多一页,⌘ + F 用浏览器的查找配置.在第三个高亮项里找到跟我一模一样的问题。 1.2.0版本已经发布,支持把Apollo配置加载提到初始化日志系统之前,可以解决此issue中提到的问题。 ,升级 apollo 到 1.2.0 问题依旧存在。

0x07

回顾该 issue, 之前提到 不过测试了一下,#1614 合并后就可以解决这个问题。,进入#1614 发现配置apollo.bootstrap.eagerLoad.enabled项,把 apollo.bootstrap.eagerLoad.enabled=true放入项目application.properties,可成功启动项目。


相关截图

0x01

1.png

0x02

2.png

0x04

3.png

0x06

4.png

0x07

5.png 解决问题总耗时 30 分钟左右。

完整异常

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'alipayController': Unsatisfied dependency expressed through field 'payService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'payServiceImpl': Unsatisfied dependency expressed through field 'commandInvokeService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'commandInvokeServiceImpl': Unsatisfied dependency expressed through method 'setCommandMap' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'alipayBatchPayCommand': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'alipayServiceImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dubbo.balconyService': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: ApplicationConfig.application == null
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1378) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:575) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) [spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at com.ezhiyang.pay.PayApplication.main(PayApplication.java:22) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_144]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_144]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_144]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.1.2.RELEASE.jar:2.1.2.RELEASE]
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'payServiceImpl': Unsatisfied dependency expressed through field 'commandInvokeService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'commandInvokeServiceImpl': Unsatisfied dependency expressed through method 'setCommandMap' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'alipayBatchPayCommand': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'alipayServiceImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dubbo.balconyService': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: ApplicationConfig.application == null
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1378) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:575) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1244) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1164) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
... 24 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'commandInvokeServiceImpl': Unsatisfied dependency expressed through method 'setCommandMap' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'alipayBatchPayCommand': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'alipayServiceImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dubbo.balconyService': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: ApplicationConfig.application == null
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:676) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1378) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:575) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1244) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1164) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
... 37 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'alipayBatchPayCommand': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'alipayServiceImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dubbo.balconyService': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: ApplicationConfig.application == null
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:324) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1378) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:575) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1460) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1424) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1315) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1202) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1164) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:668) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
... 50 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'alipayServiceImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dubbo.balconyService': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: ApplicationConfig.application == null
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:324) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1378) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:575) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1244) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1164) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:518) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:496) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:630) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:180) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:321) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
... 64 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dubbo.balconyService': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: ApplicationConfig.application == null
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:178) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:101) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1674) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1216) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:257) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:525) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:496) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:630) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:180) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:321) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
... 80 common frames omitted
Caused by: java.lang.IllegalStateException: ApplicationConfig.application == null
at com.alibaba.dubbo.config.AbstractConfig.appendParameters(AbstractConfig.java:246) ~[dubbo-2.6.2.jar:2.6.2]
at com.alibaba.dubbo.config.AbstractConfig.appendParameters(AbstractConfig.java:181) ~[dubbo-2.6.2.jar:2.6.2]
at com.alibaba.dubbo.config.ReferenceConfig.init(ReferenceConfig.java:303) ~[dubbo-2.6.2.jar:2.6.2]
at com.alibaba.dubbo.config.ReferenceConfig.get(ReferenceConfig.java:163) ~[dubbo-2.6.2.jar:2.6.2]
at com.alibaba.dubbo.config.spring.ReferenceBean.getObject(ReferenceBean.java:66) ~[dubbo-2.6.2.jar:2.6.2]
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:171) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
... 91 common frames omitted
Caused by: java.lang.IllegalStateException: ApplicationConfig.application == null
at com.alibaba.dubbo.config.AbstractConfig.appendParameters(AbstractConfig.java:231) ~[dubbo-2.6.2.jar:2.6.2]
... 96 common frames omitted