복붙노트

[SPRING] 싱글 톤을 Spring 빈으로 만드는 올바른 방법

SPRING

싱글 톤을 Spring 빈으로 만드는 올바른 방법

싱글 톤을 스프링 빈으로 변환하기 때문에 싱글 톤이 초기화되지 않으면 전체 웹 응용 프로그램의 스프링 컨텍스트가 제대로로드되지 않습니다.

Spring 컨텍스트가 제대로로드되지 않는 장점은 사람들이 배포 중에 구성에주의를 기울이고 수정한다는 것입니다. '비 스프링 빈 (non-spring bean)'싱글 톤을 사용하는 것과는 대조적으로, 초기화 중에 예외가 발생하면 실제 사용자가 누락 된 기능을 엿볼 때까지 아무도 알지 못합니다.

내 변경 사항은 예상대로 작동하지만 .. 올바른 일을하고 있는지 확실하지 않습니다. 이견있는 사람?

코드는 다음과 같습니다.

public class MySingleton {

    private static MySingleton INSTANCE = null;
    private MySingleton(){}


public static MySingleton getInstance(){
    if(INSTANCE == null){
        synchronized(MySingleton.class){
            if(INSTANCE == null){
                try{
                    doWork()
                }catch(Exception e){
                    throw new IllegalStateException("xyz", e);
                }
                INSTANCE = new MySingleton();
            }
        }
    }

    return INSTANCE;
}

private static void doWork() {
    // do some work
    }

}

그리고 spring config xml에서 bean은 다음과 같이 정의됩니다.

<bean id="MySingletonBean"
    class="com.MySingleton"
    factory-method="getInstance" lazy-init="false" singleton="true">
</bean>

노트 : 이것의 대부분은이 기사에서 논의 된 전략과 유사합니다. http://springtips.blogspot.com/2007/06/configuration-hell-remedy-with.html

편집 1 :

이 싱글 톤을 사용하는 클래스는 스프링 빈 (bean) 자체가 아닙니다. 그들은 스프링이 아닌 pojos이므로 봄으로 변환 할 수 없습니다. 그들은 getInstance () 메서드를 사용하여 Singleton을 유지해야합니다.

편집 2 : (아래 설명 된 설명을이 설명 섹션에 복사)  두 가지를 타겟팅하려고합니다.

EDIT 3 (최종) : 나는이 클래스를 싱글 톤으로 만들기로 결심했다. 봄 콩으로 만들지 않을 것이다. 초기화에 실패하면 로그 파일에 무언가를 기록 할 것입니다. 배포를하는 사람이주의를 기울여야합니다 .... 앞으로 언급 할 접근 방법을 포기했습니다. 앞으로 유지 보수의 악몽이 생길 것이라고 생각합니다. 사이에서 선택 - 싱글 톤 또는 봄 콩. 나는 싱글 톤을 선택했다.

해결법

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

    1.INSTANCE 필드를 double-checked locking이 제대로 작동하려면 volatile로 선언해야합니다.

    INSTANCE 필드를 double-checked locking이 제대로 작동하려면 volatile로 선언해야합니다.

    Effective Java, Item 71을 참조하십시오.

  2. ==============================

    2.왜 첫 번째 장소에서 싱글 톤 패턴을 사용하고 있습니까? Spring이 당신을 위해 bean을 만들고 (디폴트 싱글 톤 스코프로), 그것을 사용하도록하십시오. 물론 항상 누군가가 손으로 콩을 만들지 만, 이것은 제 경우에는 결코 문제가되지 않았습니다.

    왜 첫 번째 장소에서 싱글 톤 패턴을 사용하고 있습니까? Spring이 당신을 위해 bean을 만들고 (디폴트 싱글 톤 스코프로), 그것을 사용하도록하십시오. 물론 항상 누군가가 손으로 콩을 만들지 만, 이것은 제 경우에는 결코 문제가되지 않았습니다.

    의존성 주입과 스프링 관리 빈 수명주기는 삶을 상당히 쉽게 해줄 것입니다 (피할 수있는 함정이 얼마나 있는지보십시오). 또한 c-tor 또는 @PostContruct 메서드에서 throw 된 예외가 전파되어 응용 프로그램 컨텍스트 시작이 실패하게됩니다.

    업데이트 : 나는 당신의 요점을 얻는다. 이것이 내 마음에 들어온 것입니다.

    @Service
    public class Singleton {
    
        private static AtomicReference<Singleton> INSTANCE = new AtomicReference<Singleton>();
    
        public Singleton() {
            final Singleton previous = INSTANCE.getAndSet(this);
            if(previous != null)
                throw new IllegalStateException("Second singleton " + this + " created after " + previous);
        }
    
        public static Singleton getInstance() {
            return INSTANCE.get();
        }
    
    }
    

    그리고 Spring이 그 일을하도록하십시오. 가능한 경우 DI를 사용하고 Singleton.getInstance ()를 사용해야합니다.

    또한 컴파일 타임 AspectJ와 같은 하드 코어 솔루션이 기본적으로 모든 것에 Spring Bean을 짜 넣고 주입한다.

  3. ==============================

    3.왜 네가 이걸하고 싶어하는지 모르겠다. bean에게 singleton이어야한다고 Spring에 알릴 때, 해당 클래스는 singleton 일 필요는 없으며, factory를 필요로하지 않는다. Spring은 단지 하나의 인스턴스 만 생성합니다.

    왜 네가 이걸하고 싶어하는지 모르겠다. bean에게 singleton이어야한다고 Spring에 알릴 때, 해당 클래스는 singleton 일 필요는 없으며, factory를 필요로하지 않는다. Spring은 단지 하나의 인스턴스 만 생성합니다.

    링크 된 기사는 아무런 의미가 없습니다. 주입이 일어나지 않아서 볼 수 있습니다. "AnyService"는 싱글 톤 팩토리 메서드를 호출합니다. 애플리케이션 컨텍스트에서 싱글 톤이 참조되는 것은 참조 될 때까지 부적절하며 다른 Bean이이를 참조하지 않는 것처럼 보입니다.

  4. ==============================

    4.진정한 싱글 톤은 일하기가 어렵습니다.

    진정한 싱글 톤은 일하기가 어렵습니다.

    또한 휘발성 이중 검사 잠금은 속성을 작동하지 않습니다. wiki http://en.wikipedia.org/wiki/Double-checked_locking에서 읽어보십시오.

    최선의 방법은이 작업을 간단히 수행하는 것입니다.

    public class MySingleton {
    
        private static MySingleton INSTANCE = new MySingleton();
    

    실제 코드에 생성자 매개 변수가없는 경우입니다.

  5. ==============================

    5.나에게 이것은 벨트 앤 서스펜서 솔루션이라고 설명했다.

    나에게 이것은 벨트 앤 서스펜서 솔루션이라고 설명했다.

    Bean을 생성하고 그것을 구성에서 싱글 톤으로 선언하면, 다중을 생성하지 못하도록 Bean을 보호 할 필요가 없어야합니다.

    기본적으로 bean을 잘못 구성한 사람으로부터 자신을 보호합니다.

    개인적으로 스프링 구성 및 Javadoc의 설명서를 통해이를 "해결"합니다.

  6. ==============================

    6.시작시 코드를 실행하고 오류가 발생하면 시작 이벤트를 등록하는 여러 가지 방법 중 하나를 사용하십시오. http://www.baeldung.com/running-setup-logic-on-startup-in-spring을 참조하십시오.

    시작시 코드를 실행하고 오류가 발생하면 시작 이벤트를 등록하는 여러 가지 방법 중 하나를 사용하십시오. http://www.baeldung.com/running-setup-logic-on-startup-in-spring을 참조하십시오.

    예:

    @Component
    public class InitializingBeanExampleBean implements InitializingBean {
    
        private static final Logger LOG = Logger.getLogger(InitializingBeanExampleBean.class);
    
        @Autowired
        private Environment environment;
    
        @Override
        public void afterPropertiesSet() throws Exception {
            LOG.info(Arrays.asList(environment.getDefaultProfiles()));
        }
    }
    
  7. from https://stackoverflow.com/questions/6205171/correct-way-of-making-a-singleton-a-spring-bean by cc-by-sa and MIT license