복붙노트

[SPRING] 스윙은 스프링 부트 아래에서 헤드리스라고 생각하지만 스프링이나 일반 자바에서는 그렇지 않다고 생각하는 이유는 무엇입니까?

SPRING

스윙은 스프링 부트 아래에서 헤드리스라고 생각하지만 스프링이나 일반 자바에서는 그렇지 않다고 생각하는 이유는 무엇입니까?

다음 코드가 작동합니다.

import javax.swing.*;

public class HeadlessExceptionDemo {

   public static void main(String[] args) {

      JFrame frame = new JFrame("HeadlessExceptionDemo");
      frame.setSize(800, 600);
      frame.setLocationRelativeTo(null);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);

   }
}

다음 코드도 작동합니다.

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.swing.*;

@Configuration
public class HeadlessExceptionDemo {

   @Bean
   public JFrame frame() {
      JFrame frame = new JFrame("HeadlessExceptionDemo");
      frame.setSize(800, 600);
      frame.setLocationRelativeTo(null);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      return frame;
   }

   public static void main(String[] args) {

      AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(HeadlessExceptionDemo.class);
      JFrame frame = ctx.getBean(JFrame.class);
      frame.setVisible(true);

   }
}

다음 코드는 그렇지 않습니다.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;

import javax.swing.*;

@SpringBootApplication
public class HeadlessExceptionDemo {

    @Bean
    public JFrame frame() {
        JFrame frame = new JFrame("HeadlessExceptionDemo");
        frame.setSize(800, 600);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        return frame;
    }

    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = SpringApplication.run(HeadlessExceptionDemo.class, args);
        JFrame frame = ctx.getBean(JFrame.class);
        frame.setVisible(true);
    }
}

아래에서 예외가 발생합니다.

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.swing.JFrame]: Factory method 'frame' threw exception; nested exception is java.awt.HeadlessException
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    ... 23 common frames omitted
Caused by: java.awt.HeadlessException: null
    at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:207) ~[na:1.8.0_45]
    at java.awt.Window.<init>(Window.java:536) ~[na:1.8.0_45]
    at java.awt.Frame.<init>(Frame.java:420) ~[na:1.8.0_45]
    at javax.swing.JFrame.<init>(JFrame.java:233) ~[na:1.8.0_45]
    at com.inthemoon.snippets.springboot.HeadlessExceptionDemo.frame(HeadlessExceptionDemo.java:15) [classes/:na]
    at com.inthemoon.snippets.springboot.HeadlessExceptionDemo$$EnhancerBySpringCGLIB$$3680a05b.CGLIB$frame$0(<generated>) ~[classes/:na]
    at com.inthemoon.snippets.springboot.HeadlessExceptionDemo$$EnhancerBySpringCGLIB$$3680a05b$$FastClassBySpringCGLIB$$b7def9bc.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:355) ~[spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at com.inthemoon.snippets.springboot.HeadlessExceptionDemo$$EnhancerBySpringCGLIB$$3680a05b.frame(<generated>) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_45]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45]
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    ... 24 common frames omitted

왜? :)

해결법

  1. ==============================

    1.Spring Boot는 SpringApplication.java의 소스 코드에서 볼 수 있듯이 기본적으로 java.awt.headless를 true로 설정한다.

    Spring Boot는 SpringApplication.java의 소스 코드에서 볼 수 있듯이 기본적으로 java.awt.headless를 true로 설정한다.

    private boolean headless = true;
    
    ...
    
    private void configureHeadlessProperty() {
            System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, System.getProperty(
                    SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
    }
    

    왜 이렇게하는지에 관해서는 아이콘이 나타나지 않도록하는 것에 대한 setHeadless 메서드의 소스 코드에 주석이 있습니다.

        /**
         * Sets if the application is headless and should not instantiate AWT. Defaults to
         * {@code true} to prevent java icons appearing.
         * @param headless if the application is headless
         */
        public void setHeadless(boolean headless) {
            this.headless = headless;
        }
    
  2. ==============================

    2.이 선 대신에

    이 선 대신에

    SpringApplication.run (Application.class, args);

    용도

    SpringApplicationBuilder 빌더 = 새 SpringApplicationBuilder (Application.class);

        builder.headless(false);
        ConfigurableApplicationContext context = builder.run(args);
    
  3. from https://stackoverflow.com/questions/36160353/why-does-swing-think-its-headless-under-spring-boot-but-not-under-spring-or-pl by cc-by-sa and MIT license