简体   繁体   中英

Using Java singleton pattern (static access to the singleton) with Spring

Consider this code:

public class A {
    private static final A INSTANCE = new A();
    public static A getInstance() {
        return INSTANCE;
    }
    private A() {}
    public void doSomething() {}
}

// elsewhere in code
A.getInstance().doSomething();

How do I do the same when A requires a spring bean for construction? I don't want to inject A in each class that needs it, but want those classes to be able to access the singleton instance statically (ie, A.getInstance() ).

Accessing a Spring bean from a static context is problematic because the initialization of beans isn't tied to their construction, and Spring may instrument injected beans by wrapping them in proxies; simply passing around references to this will often result in unexpected behaviour. It's best to rely on Spring's injection mechanism.

If you really have to do it (perhaps because you need access from legacy code), use something like this:

@Service
public class A implements ApplicationContextAware {

    private static final AtomicReference<A> singleton;
    private static final CountDownLatch latch = new CountDownLatch(1);

    @Resource
    private MyInjectedBean myBean; // inject stuff...

    public static A getInstance() {
        try {
            if (latch.await(1, TimeUnit.MINUTES)) {
                return singleton.get();
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        throw new IllegalStateException("Application Context not initialized");
    }

    @Override
    public void setApplicationContext(ApplicationContext context) {
        singleton.set(context.getBean(A.class));
        latch.countDown();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM