Я хотел бы создать синглтон, содержащий MAC-адрес системы, в которой он работает, на основе предоставленного сетевого интерфейса.
Я написал следующий код:
public class NodeMac {
private static final String INSTANCE = getMacAddress();
private static String networkInterfaceName;
@Value("${machine.network.interface}")
public void setNetworkInterfaceName(String networkInterfaceName) {
NodeMac.networkInterfaceName = networkInterfaceName;
}
private NodeMac() { }
public static String getInstance() {
return INSTANCE;
}
private static String getMacAddress() {
try {
NetworkInterface network = NetworkInterface.getByName(networkInterfaceName);
byte[] mac = network.getHardwareAddress();
System.out.print("Current MAC address : ");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mac.length; i++) {
sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
}
return sb.toString();
} catch (SocketException | NullPointerException e) {
throw new RuntimeException(
"Failed to extract MAC address for network interface with name " + networkInterfaceName, e);
}
}
}
И в application.properties:
machine.network.interface=eno1
Однако я не могу найти способ получить значение свойства, содержащее имя сетевого интерфейса. Он всегда равен нулю, независимо от того, как я пытаюсь получить к нему доступ.
Как правильно это сделать? Наличие свойства в синглтоне - это антипаттерн?




Редактировать
Итак, вы изо всех сил пытаетесь создать класс pojo с одним экземпляром с введенным @Value. Если вы умеете работать с bean-компонентами, то это правильный путь:
@Component // This will default give you a single ton bean
public class NodeMac {
@Value("${machine.network.interface}")
private String networkInterfaceName;
public String getMacAddress() {
try {
NetworkInterface network = NetworkInterface.getByName(networkInterfaceName);
byte[] mac = network.getHardwareAddress();
System.out.print("Current MAC address : ");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mac.length; i++) {
sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
}
return sb.toString();
} catch (SocketException | NullPointerException e) {
throw new RuntimeException(
"Failed to extract MAC address for network interface with name " + networkInterfaceName, e);
}
}
}
СТАРЫЙ
Как вы пришли к этому выражению:
String key = System.getProperty("machine.network.interface");
Маловероятно, что машина имеет только один сетевой интерфейс, поэтому не может быть возвращен ни один ключ.
Действительно, оракул уже пишет учебник здесь
public static void main(String args[]) throws SocketException {
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
for (NetworkInterface netint : Collections.list(nets))
displayInterfaceInformation(netint);
}
static void displayInterfaceInformation(NetworkInterface netint) throws SocketException {
out.printf("Display name: %s\n", netint.getDisplayName());
out.printf("Name: %s\n", netint.getName());
Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
for (InetAddress inetAddress : Collections.list(inetAddresses)) {
out.printf("InetAddress: %s\n", inetAddress);
}
out.printf("\n");
}
Ты не можешь. Поскольку ваш метод static будет запущен до автоподключения bean-компонентов
Я не знал, что синглтон по умолчанию, спасибо. Мне нужно было только удалить модификатор static из инъекции значения в приведенном выше коде, и теперь он работает.
Да, Spring bean-компонент по умолчанию - singleton, если вы не указали, что он не является одноэлементным. Рад, что помог.
Свойство содержит имя сетевого интерфейса. В данном случае
eno1. Я хотел проверить, доступен ли ключ таким образом, поскольку аннотация Springs@Valueвсегда дает мне нулевое значение.