쉽게 쉽게

[Spring] static 변수에 autowired 설정 방법 본문

개발공부/Spring

[Spring] static 변수에 autowired 설정 방법

곱마2 2024. 7. 29. 16:28
반응형

 

▤ 목차

    1. 이슈

    공통적으로 사용하는 CommonService에서 모든 컨트롤러에서 사용될 public static void 메서드가 하나 있을 때, 이 static void 필드에 @Autowired된 빈을 사용해야 하는 상황이 발생했다.

    그러나 그냥 static에 @Autowired된 빈을 사용하면 NullpointerException이 발생하게 된다.

    @Service
    public class CommonService {
    
        @Autowired
        private MyBean myBean; 
    
        public static void commonMethod() {
            myBean.doSomething();  // myBean이 주입되지 않으므로 NPE 발생
        }
    }

    그 이유는 @Autowired인스턴스 필드나 메서드, 생성자에 주입되도록 설계되어 있으며, static 컨텍스트에서는 인스턴스에 종속된 빈을 주입할 수 있는 방법이 없다.

    더보기

    사용할 수 없는 이유

    @Autowired 애노테이션은 Spring이 해당 필드, 생성자, 또는 메서드에 주입할 객체를 자동으로 찾아서 주입해주는 기능을 제공한다. 이는 주로 객체의 인스턴스 필드나 메서드에서 사용된다.

    static은 클래스 레벨에서 공유되는 변수를 정의한다. 즉, static 변수나 메서드는 해당 클래스를 통해 직접 접근할 수 있으며, 클래스의 인스턴스와는 무관하게 존재한다.

    1. @Autowired는 Spring 컨테이너가 관리하는 빈 인스턴스의 필드에 의존성을 주입하는 반면, static 변수나 메서드는 클래스 레벨에서 존재하며, 특정 인스턴스와 연결되지 않는다.
    2. Spring의 빈은 애플리케이션 컨텍스트에 의해 관리되며, 그 생명주기는 애플리케이션 컨텍스트에 의해 제어되는 반면 static 필드는 클래스 로딩 시점에 초기화되며, 애플리케이션 컨텍스트와는 별개로 존재한다.

    때문에 @Autowired된 빈을 static 메서드에서 직접 사용할 수 없다.

    원래라면  Spring에서 @Autowired된 빈을 static 메서드에서 직접 사용할 수 없지만 몇 가지 방법을 통해 static 메서드에서 빈을 사용하는 방법을 알아봤다.

    2. 해결방법

    1. setter 사용

    @Service
    public class CommonService {
    	public static MyBean MyBean;
    
        // MyBean의 setter 메서드를 사용
        @Autowired
        public void setMyBean(MyBean Object) {
            this.MyBean = Object;
        }
        
        public static void commonMethod() {
            myBean.doSomething(); 
        }
    }

    2. 생성자 사용

    @Service
    public class CommonService {
    	public static MyBean MyBean;
    
        // MyBean의 생성자를 이용
        @Autowired
        private CommonService(MyBean Object) {
            this.MyBean = Object;
        }
        
        public static void commonMethod() {
            myBean.doSomething(); 
        }
    }

    3. @Postconstruct 사용

    @Service
    public class CommonService {
    	public static MyBean MyBean;
        @Autowired
        private MyBean Object;
       
        @PostConstruct
        private void initialize() {
            this.MyBean = Object;
        }
        
        public static void commonMethod() {
            myBean.doSomething(); 
        }
    }

    @Postconstruct란?

    스프링 빈 생명주기(Bean LifeCycle) 사이클은 아래와 같다.

    스프링 컨테이너 생성  ->  스프링 빈 생성  ->  의존 관계 주입  ->  초기화 콜백  ->  사용  ->  소멸 콜백  ->  스프링 종료

    • 초기화 콜백(init) : Bean이 생성되고, Bean의 의존성 주입이 완료된 뒤 호출된다.
    • 소멸 콜백(destroy) : 스프링이 종료되기 전, Bean이 소멸되기 직전에 호출된다.

    스프링 빈으로 등록되는 객체를 사용하기 위해서는 객체가 생성된 후 의존성 주입까지(Dependency Injection) 끝나야 해당 객체를 사용할 수 있게 된다. 

    @PostConstruct은 빈이 생성되고 의존 관계 주입이 완료된 후 실행되는 초기화 콜백을 적용할 수 있는 어노테이션이다.

    빈의 모든 의존성이 주입된 후에 추가적인 초기화 작업을 수행할 수 있다.

    또한 @PostConstructbean lifecycle에서 오직 한 번만 수행된다는 것을 보장할 수 있다. 

    그래서 @PostConstruct를 사용하면 bean이 여러 번 초기화되는 것을 방지할 수 있다. 

     

    https://madplay.github.io/post/spring-framework-static-field-injection

     

    static 변수에 autowired 설정하려면 어떻게 해야 할까?

    스프링 프레임워크에서 정적 필드(static field)에 빈을 주입(injection) 해보자.

    madplay.github.io

    https://innovation123.tistory.com/213

     

    [Spring] 빈 생명 주기 콜백 (Bean LifeCycle) @PostConstruct / @PreDestroy

    Spring Bean LifeCycle Spring DI 컨테이너는 Bean으로 등록된 객체의 생명주기 관리를 위임받아서 관리하고, 객체가 필요한 곳에서 이 Bean을 의존성 주입받아서 사용할 수 있다. 스프링 컨테이너가 생성

    innovation123.tistory.com

    잘못된 내용이 있다면 지적부탁드립니다. 방문해주셔서 감사합니다.

     

    반응형

    '개발공부 > Spring' 카테고리의 다른 글

    [Spring] Spring Security 구현 (1) - 설정  (1) 2024.10.31
    [Spring] tiles 적용  (5) 2024.09.05
    [Spring] 스케줄러 구현  (1) 2024.06.30
    [Spring] 게시글 조회수 중복방지  (1) 2024.05.30
    spring tiles 사용법  (0) 2023.06.25